demos: Changes to use new WSI swapchain extensions.
diff --git a/demos/cube.c b/demos/cube.c
index a345030..7bdef0f 100644
--- a/demos/cube.c
+++ b/demos/cube.c
@@ -37,7 +37,8 @@
 #endif // _WIN32
 
 #include <vulkan.h>
-#include <vk_wsi_lunarg.h>
+#include <vk_wsi_swapchain.h>
+#include <vk_wsi_device_swapchain.h>
 #include "vk_debug_report_lunarg.h"
 
 #include "icd-spv.h"
@@ -80,6 +81,15 @@
    } while (0)
 #endif // _WIN32
 
+#define GET_INSTANCE_PROC_ADDR(inst, entrypoint)                        \
+{                                                                       \
+    demo->fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
+    if (demo->fp##entrypoint == NULL) {                                 \
+        ERR_EXIT("vkGetInstanceProcAddr failed to find vk"#entrypoint,  \
+                 "vkGetInstanceProcAddr Failure");                      \
+    }                                                                   \
+}
+
 #define GET_DEVICE_PROC_ADDR(dev, entrypoint)                           \
 {                                                                       \
     demo->fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint);   \
@@ -282,6 +292,12 @@
     free(message);
 }
 
+typedef struct _SwapChainBuffers {
+    VkImage image;
+    VkCmdBuffer cmd;
+    VkAttachmentView view;
+} SwapChainBuffers;
+
 struct demo {
 #ifdef _WIN32
 #define APP_NAME_STR_LEN 80
@@ -294,6 +310,7 @@
     xcb_window_t window;
     xcb_intern_atom_reply_t *atom_wm_delete_window;
 #endif // _WIN32
+    VkPlatformHandleXcbWSI platform_handle_xcb;
     bool prepared;
     bool use_staging_buffer;
     bool use_glsl;
@@ -311,19 +328,19 @@
     int width, height;
     VkFormat format;
 
+    PFN_vkGetPhysicalDeviceSurfaceSupportWSI fpGetPhysicalDeviceSurfaceSupportWSI;
+    PFN_vkGetSurfaceInfoWSI fpGetSurfaceInfoWSI;
     PFN_vkCreateSwapChainWSI fpCreateSwapChainWSI;
     PFN_vkDestroySwapChainWSI fpDestroySwapChainWSI;
     PFN_vkGetSwapChainInfoWSI fpGetSwapChainInfoWSI;
+    PFN_vkAcquireNextImageWSI fpAcquireNextImageWSI;
     PFN_vkQueuePresentWSI fpQueuePresentWSI;
+    VkSurfaceDescriptionWindowWSI surface_description;
+    size_t swapChainImageCount;
     VkSwapChainWSI swap_chain;
-    VkCmdPool cmd_pool;
-    struct {
-        VkImage image;
-        VkDeviceMemory mem;
-        VkCmdBuffer cmd;
+    SwapChainBuffers *buffers;
 
-        VkAttachmentView view;
-    } buffers[DEMO_BUFFER_COUNT];
+    VkCmdPool cmd_pool;
 
     struct {
         VkFormat format;
@@ -551,23 +568,57 @@
 
 static void demo_draw(struct demo *demo)
 {
-    const VkPresentInfoWSI present = {
-        .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI,
-        .pNext = NULL,
-        .image = demo->buffers[demo->current_buffer].image,
-        .flipInterval = 0,
-    };
     VkResult U_ASSERT_ONLY err;
+    VkSemaphore presentCompleteSemaphore;
+    VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {
+        .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+        .pNext = NULL,
+        .flags = VK_FENCE_CREATE_SIGNALED_BIT,
+    };
     VkFence nullFence = { VK_NULL_HANDLE };
 
+    err = vkCreateSemaphore(demo->device,
+                            &presentCompleteSemaphoreCreateInfo,
+                            &presentCompleteSemaphore);
+    assert(!err);
+
+    // Get the index of the next available swapchain image:
+    err = demo->fpAcquireNextImageWSI(demo->device, demo->swap_chain,
+                                      UINT64_MAX,
+                                      presentCompleteSemaphore,
+                                      &demo->current_buffer);
+    // TODO: Deal with the VK_SUBOPTIMAL_WSI and VK_ERROR_OUT_OF_DATE_WSI
+    // return codes
+    assert(!err);
+
+    // Wait for the present complete semaphore to be signaled to ensure
+    // that the image won't be rendered to until the presentation
+    // engine has fully released ownership to the application, and it is
+    // okay to render to the image.
+    vkQueueWaitSemaphore(demo->queue, presentCompleteSemaphore);
+
+// FIXME/TODO: DEAL WITH VK_IMAGE_LAYOUT_PRESENT_SOURCE_WSI
     err = vkQueueSubmit(demo->queue, 1, &demo->buffers[demo->current_buffer].cmd,
             nullFence);
     assert(!err);
 
+    VkPresentInfoWSI present = {
+        .sType = VK_STRUCTURE_TYPE_QUEUE_PRESENT_INFO_WSI,
+        .pNext = NULL,
+        .swapChainCount = 1,
+        .swapChains = &demo->swap_chain,
+        .imageIndices = &demo->current_buffer,
+    };
+
+// TBD/TODO: SHOULD THE "present" PARAMETER BE "const" IN THE HEADER?
     err = demo->fpQueuePresentWSI(demo->queue, &present);
+    // TODO: Deal with the VK_SUBOPTIMAL_WSI and VK_ERROR_OUT_OF_DATE_WSI
+    // return codes
     assert(!err);
 
-    demo->current_buffer = (demo->current_buffer + 1) % DEMO_BUFFER_COUNT;
+// FIXME: UNCOMMENT THE FOLLOWING LINE ONCE WE HAVE A NEW-ENOUGH "vulkan.h" HEADER:
+//    err = vkDestroySemaphore(demo->device, presentCompleteSemaphore);
+    assert(!err);
 
     err = vkQueueWaitIdle(demo->queue);
     assert(err == VK_SUCCESS);
@@ -575,35 +626,120 @@
 
 static void demo_prepare_buffers(struct demo *demo)
 {
+    VkResult U_ASSERT_ONLY err;
+
+    // Check the surface properties and formats
+    size_t capsSize;
+    size_t presentModesSize;
+    err = demo->fpGetSurfaceInfoWSI(demo->device,
+        (const VkSurfaceDescriptionWSI *)&demo->surface_description,
+        VK_SURFACE_INFO_TYPE_PROPERTIES_WSI, &capsSize, NULL);
+    assert(!err);
+    err = demo->fpGetSurfaceInfoWSI(demo->device,
+        (const VkSurfaceDescriptionWSI *)&demo->surface_description,
+        VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI, &presentModesSize, NULL);
+    assert(!err);
+
+    VkSurfacePropertiesWSI *surfProperties =
+        (VkSurfacePropertiesWSI *)malloc(capsSize);
+    VkSurfacePresentModePropertiesWSI *presentModes =
+        (VkSurfacePresentModePropertiesWSI *)malloc(presentModesSize);
+
+    err = demo->fpGetSurfaceInfoWSI(demo->device,
+        (const VkSurfaceDescriptionWSI *)&demo->surface_description,
+        VK_SURFACE_INFO_TYPE_PROPERTIES_WSI, &capsSize, surfProperties);
+    assert(!err);
+    err = demo->fpGetSurfaceInfoWSI(demo->device,
+        (const VkSurfaceDescriptionWSI *)&demo->surface_description,
+        VK_SURFACE_INFO_TYPE_PRESENT_MODES_WSI, &presentModesSize, presentModes);
+    assert(!err);
+
+    VkExtent2D swapChainExtent;
+    // width and height are either both -1, or both not -1.
+    if (surfProperties->currentExtent.width == -1)
+    {
+        // If the surface size is undefined, the size is set to
+        // the size of the images requested.
+        swapChainExtent.width = demo->width;
+        swapChainExtent.height = demo->height;
+    }
+    else
+    {
+        // If the surface size is defined, the swap chain size must match
+        swapChainExtent = surfProperties->currentExtent;
+    }
+
+    // If mailbox mode is available, use it, as is the lowest-latency non-
+    // tearing mode.  If not, fall back to IMMEDIATE which should always be
+    // available.    
+    VkPresentModeWSI swapChainPresentMode = VK_PRESENT_MODE_IMMEDIATE_WSI;
+    size_t presentModeCount = presentModesSize / sizeof(VkSurfacePresentModePropertiesWSI);
+    for (size_t i = 0; i < presentModeCount; i++) {
+        if (presentModes[i].presentMode == VK_PRESENT_MODE_MAILBOX_WSI) {
+            swapChainPresentMode = VK_PRESENT_MODE_MAILBOX_WSI;
+            break;
+        }
+    }
+
+    // Determine the number of VkImage's to use in the swap chain (we desire to
+    // own only 1 image at a time, besides the images being displayed and
+    // queued for display):
+    uint32_t desiredNumberOfSwapChainImages = surfProperties->minImageCount + 1;
+    if ((surfProperties->maxImageCount > 0) &&
+        (desiredNumberOfSwapChainImages > surfProperties->maxImageCount))
+    {
+        // Application must settle for fewer images than desired:
+        desiredNumberOfSwapChainImages = surfProperties->maxImageCount;
+    }
+
+    VkSurfaceTransformFlagBitsWSI preTransform;
+    if (surfProperties->supportedTransforms & VK_SURFACE_TRANSFORM_NONE_BIT_WSI) {
+        preTransform = VK_SURFACE_TRANSFORM_NONE_WSI;
+    } else {
+        preTransform = surfProperties->currentTransform;
+    }
+
     const VkSwapChainCreateInfoWSI swap_chain = {
         .sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI,
         .pNext = NULL,
-        .pNativeWindowSystemHandle = demo->connection,
-        .pNativeWindowHandle = (void *) (intptr_t) demo->window,
-        .displayCount = 1,
-        .imageCount = DEMO_BUFFER_COUNT,
+        .pSurfaceDescription = (const VkSurfaceDescriptionWSI *)&demo->surface_description,
+        .minImageCount = desiredNumberOfSwapChainImages,
         .imageFormat = demo->format,
         .imageExtent = {
-            .width = demo->width,
-            .height = demo->height,
+            .width = swapChainExtent.width,
+            .height = swapChainExtent.height,
         },
+        .preTransform = preTransform,
         .imageArraySize = 1,
-        .imageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+        .presentMode = swapChainPresentMode,
+        .oldSwapChain.handle = 0,
+        .clipped = true,
     };
-    VkSwapChainImageInfoWSI images[DEMO_BUFFER_COUNT];
-    size_t images_size = sizeof(images);
-    VkResult U_ASSERT_ONLY err;
     uint32_t i;
 
     err = demo->fpCreateSwapChainWSI(demo->device, &swap_chain, &demo->swap_chain);
     assert(!err);
 
-    err = demo->fpGetSwapChainInfoWSI(demo->swap_chain,
-            VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
-            &images_size, images);
-    assert(!err && images_size == sizeof(images));
+    size_t swapChainImagesSize;
+    err = demo->fpGetSwapChainInfoWSI(demo->device, demo->swap_chain,
+                                      VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI,
+                                      &swapChainImagesSize, NULL);
+    assert(!err);
 
-    for (i = 0; i < DEMO_BUFFER_COUNT; i++) {
+    VkSwapChainImagePropertiesWSI* swapChainImages = (VkSwapChainImagePropertiesWSI*)malloc(swapChainImagesSize);
+    assert(swapChainImages);
+    err = demo->fpGetSwapChainInfoWSI(demo->device, demo->swap_chain,
+                                      VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI,
+                                      &swapChainImagesSize, swapChainImages);
+    assert(!err);
+
+    // The number of images within the swap chain is determined based on the size of the info returned
+    demo->swapChainImageCount = swapChainImagesSize / sizeof(VkSwapChainImagePropertiesWSI);
+
+    demo->buffers = (SwapChainBuffers*)malloc(sizeof(SwapChainBuffers)*demo->swapChainImageCount);
+    assert(demo->buffers);
+
+    for (i = 0; i < demo->swapChainImageCount; i++) {
         VkAttachmentViewCreateInfo color_attachment_view = {
             .sType = VK_STRUCTURE_TYPE_ATTACHMENT_VIEW_CREATE_INFO,
             .pNext = NULL,
@@ -613,8 +749,7 @@
             .arraySize = 1,
         };
 
-        demo->buffers[i].image = images[i].image;
-        demo->buffers[i].mem = images[i].memory;
+        demo->buffers[i].image = swapChainImages[i].image;
 
         demo_set_image_layout(demo, demo->buffers[i].image,
                                VK_IMAGE_ASPECT_COLOR,
@@ -1681,7 +1816,7 @@
     demo_prepare_pipeline(demo);
     demo_prepare_dynamic_states(demo);
 
-    for (int i = 0; i < DEMO_BUFFER_COUNT; i++) {
+    for (uint32_t i = 0; i < demo->swapChainImageCount; i++) {
         err = vkCreateCommandBuffer(demo->device, &cmd, &demo->buffers[i].cmd);
         assert(!err);
     }
@@ -1691,7 +1826,7 @@
 
     demo_prepare_framebuffers(demo);
 
-    for (int i = 0; i < DEMO_BUFFER_COUNT; i++) {
+    for (uint32_t i = 0; i < demo->swapChainImageCount; i++) {
         demo->current_buffer = i;
         demo_draw_build_cmd(demo, demo->buffers[i].cmd);
     }
@@ -1735,7 +1870,7 @@
         vkFreeMemory(demo->device, demo->textures[i].mem);
         vkDestroySampler(demo->device, demo->textures[i].sampler);
     }
-    demo->fpDestroySwapChainWSI(demo->swap_chain);
+    demo->fpDestroySwapChainWSI(demo->device, demo->swap_chain);
 
     vkDestroyAttachmentView(demo->device, demo->depth.view);
     vkDestroyImage(demo->device, demo->depth.image);
@@ -1745,10 +1880,11 @@
     vkDestroyBuffer(demo->device, demo->uniform_data.buf);
     vkFreeMemory(demo->device, demo->uniform_data.mem);
 
-    for (i = 0; i < DEMO_BUFFER_COUNT; i++) {
+    for (i = 0; i < demo->swapChainImageCount; i++) {
         vkDestroyAttachmentView(demo->device, demo->buffers[i].view);
         vkDestroyCommandBuffer(demo->device, demo->buffers[i].cmd);
     }
+    free(demo->buffers);
 
     vkDestroyCommandPool(demo->device, demo->cmd_pool);
     vkDestroyDevice(demo->device);
@@ -1799,10 +1935,10 @@
 {
     switch(uMsg)
     {
-    case WM_CLOSE: 
+    case WM_CLOSE:
         PostQuitMessage(0);
         break;
-    case WM_PAINT: 
+    case WM_PAINT:
         demo_run(&demo);
         return 0;
     default:
@@ -2045,9 +2181,9 @@
     err = vkGetGlobalExtensionProperties(NULL, &instance_extension_count, instance_extensions);
     assert(!err);
     for (uint32_t i = 0; i < instance_extension_count; i++) {
-        if (!strcmp(VK_WSI_LUNARG_EXTENSION_NAME, instance_extensions[i].extName)) {
+        if (!strcmp("VK_WSI_swapchain", instance_extensions[i].extName)) {
             WSIextFound = 1;
-            extension_names[enabled_extension_count++] = VK_WSI_LUNARG_EXTENSION_NAME;
+            extension_names[enabled_extension_count++] = "VK_WSI_swapchain";
         }
         if (!strcmp(DEBUG_REPORT_EXTENSION_NAME, instance_extensions[i].extName)) {
             if (demo->validate) {
@@ -2058,7 +2194,7 @@
     }
     if (!WSIextFound) {
         ERR_EXIT("vkGetGlobalExtensionProperties failed to find the "
-                 "\"VK_WSI_LunarG\" extension.\n\nDo you have a compatible "
+                 "\"VK_WSI_swapchain\" extension.\n\nDo you have a compatible "
                  "Vulkan installable client driver (ICD) installed?\nPlease "
                  "look at the Getting Started guide for additional "
                  "information.\n",
@@ -2153,24 +2289,22 @@
     err = vkGetPhysicalDeviceExtensionProperties(
               demo->gpu, NULL, &device_extension_count, device_extensions);
     assert(!err);
-#if 0
-    /* Will need this check in future */
+
     for (uint32_t i = 0; i < device_extension_count; i++) {
-        if (!strcmp(VK_WSI_LUNARG_EXTENSION_NAME, device_extensions[i].extName)) {
+        if (!strcmp("VK_WSI_device_swapchain", device_extensions[i].extName)) {
             WSIextFound = 1;
-            extension_names[enabled_extension_count++] = VK_WSI_LUNARG_EXTENSION_NAME;
+            extension_names[enabled_extension_count++] = "VK_WSI_device_swapchain";
         }
         assert(enabled_extension_count < 64);
     }
     if (!WSIextFound) {
-        ERR_EXIT("vkGetGlobalExtensionProperties failed to find the "
-                 "\"VK_WSI_LunarG\" extension.\n\nDo you have a compatible "
+        ERR_EXIT("vkGetPhysicalDeviceExtensionProperties failed to find the "
+                 "\"VK_WSI_device_swapchain\" extension.\n\nDo you have a compatible "
                  "Vulkan installable client driver (ICD) installed?\nPlease "
                  "look at the Getting Started guide for additional "
                  "information.\n",
                  "vkCreateInstance Failure");
     }
-#endif
 
     VkDeviceCreateInfo device = {
         .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
@@ -2223,10 +2357,13 @@
 
     free(device_layers);
 
+    GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceSupportWSI);
+    GET_DEVICE_PROC_ADDR(demo->device, GetSurfaceInfoWSI);
     GET_DEVICE_PROC_ADDR(demo->device, CreateSwapChainWSI);
     GET_DEVICE_PROC_ADDR(demo->device, CreateSwapChainWSI);
     GET_DEVICE_PROC_ADDR(demo->device, DestroySwapChainWSI);
     GET_DEVICE_PROC_ADDR(demo->device, GetSwapChainInfoWSI);
+    GET_DEVICE_PROC_ADDR(demo->device, AcquireNextImageWSI);
     GET_DEVICE_PROC_ADDR(demo->device, QueuePresentWSI);
 
     err = vkGetPhysicalDeviceProperties(demo->gpu, &demo->gpu_props);
@@ -2240,22 +2377,105 @@
     assert(!err);
     assert(queue_count >= 1);
 
-    // Graphics queue and MemMgr queue can be separate.
-    // TODO: Add support for separate queues, including synchronization,
-    //       and appropriate tracking for QueueSubmit
+    // Construct the WSI surface description:
+    demo->surface_description.sType = VK_STRUCTURE_TYPE_SURFACE_DESCRIPTION_WINDOW_WSI;
+    demo->surface_description.pNext = NULL;
+#ifdef _WIN32
+    demo->surface_description.platform = VK_PLATFORM_WIN32_WSI;
+    demo->surface_description.pPlatformHandle = demo->connection;
+    demo->surface_description.pPlatformWindow = demo->window;
+#else  // _WIN32
+    demo->platform_handle_xcb.connection = demo->connection;
+    demo->platform_handle_xcb.root = demo->screen->root;
+    demo->surface_description.platform = VK_PLATFORM_XCB_WSI;
+    demo->surface_description.pPlatformHandle = &demo->platform_handle_xcb;
+    demo->surface_description.pPlatformWindow = &demo->window;
+#endif // _WIN32
+
+    // Iterate over each queue to learn whether it supports presenting to WSI:
+    VkBool32* supportsPresent = (VkBool32 *)malloc(queue_count * sizeof(VkBool32));
     for (i = 0; i < queue_count; i++) {
-        if (demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
-            break;
+        demo->fpGetPhysicalDeviceSurfaceSupportWSI(demo->gpu, i,
+                                                   (VkSurfaceDescriptionWSI *) &demo->surface_description,
+                                                   &supportsPresent[i]);
     }
-    assert(i < queue_count);
-    demo->graphics_queue_node_index = i;
+
+    // Search for a graphics and a present queue in the array of queue
+    // families, try to find one that supports both
+    uint32_t graphicsQueueNodeIndex = UINT32_MAX;
+    uint32_t presentQueueNodeIndex  = UINT32_MAX;
+    for (i = 0; i < queue_count; i++) {
+        if ((demo->queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) {
+            if (graphicsQueueNodeIndex == UINT32_MAX) {
+                graphicsQueueNodeIndex = i;
+            }
+            
+            if (supportsPresent[i] == VK_TRUE) {
+                graphicsQueueNodeIndex = i;
+                presentQueueNodeIndex = i;
+                break;
+            }
+        }
+    }
+    if (presentQueueNodeIndex == UINT32_MAX) {
+        // If didn't find a queue that supports both graphics and present, then
+        // find a separate present queue.
+        for (size_t i = 0; i < queue_count; ++i) {
+            if (supportsPresent[i] == VK_TRUE) {
+                presentQueueNodeIndex = i;
+                break;
+            }
+        }
+    }
+    free(supportsPresent);
+
+    // Generate error if could not find both a graphics and a present queue
+    if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX) {
+        ERR_EXIT("Could not find a graphics and a present queue\n",
+                 "WSI Initialization Failure");
+    }
+
+    // TODO: Add support for separate queues, including presentation,
+    //       synchronization, and appropriate tracking for QueueSubmit
+    // While it is possible for an application to use a separate graphics and a
+    // present queues, this demo program assumes it is only using one:
+    if (graphicsQueueNodeIndex != presentQueueNodeIndex) {
+        ERR_EXIT("Could not find a common graphics and a present queue\n",
+                 "WSI Initialization Failure");
+    }
+
+    demo->graphics_queue_node_index = graphicsQueueNodeIndex;
 
     err = vkGetDeviceQueue(demo->device, demo->graphics_queue_node_index,
             0, &demo->queue);
     assert(!err);
 
-    // for now hardcode format till get WSI support
-    demo->format = VK_FORMAT_B8G8R8A8_UNORM;
+    // Get the list of VkFormat's that are supported:
+    size_t formatsSize;
+    err = demo->fpGetSurfaceInfoWSI(demo->device,
+                                    (VkSurfaceDescriptionWSI *) &demo->surface_description,
+                                    VK_SURFACE_INFO_TYPE_FORMATS_WSI,
+                                    &formatsSize, NULL);
+    assert(!err);
+    VkSurfaceFormatPropertiesWSI *surfFormats = (VkSurfaceFormatPropertiesWSI *)malloc(formatsSize);
+    err = demo->fpGetSurfaceInfoWSI(demo->device,
+                                    (VkSurfaceDescriptionWSI *) &demo->surface_description,
+                                    VK_SURFACE_INFO_TYPE_FORMATS_WSI,
+                                    &formatsSize, surfFormats);
+    assert(!err);
+    // If the format list includes just one entry of VK_FORMAT_UNDEFINED,
+    // the surface has no preferred format.  Otherwise, at least one
+    // supported format will be returned.
+    size_t formatCount = formatsSize / sizeof(VkSurfaceFormatPropertiesWSI);
+    if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
+    {
+        demo->format = VK_FORMAT_B8G8R8A8_UNORM;
+    }
+    else
+    {
+        assert(formatCount >= 1);
+        demo->format = surfFormats[0].format;
+    }
 
     demo->quit = false;
     demo->curFrame = 0;