switch to VK_WSI_LunarG

Switch from VK_WSI_X11 to VK_WSI_LunarG

v2:

 - split out glave changes
 - redo mem_tracker changes
 - rebase

Conflicts:

	demos/cube.c
	demos/tri.c

v3 (from Ian):

 - Put "#if 0" around non-upstream members of VkDisplayPropertiesWSI.
diff --git a/include/vkDbg.h b/include/vkDbg.h
index 43a5599..cc3c425 100644
--- a/include/vkDbg.h
+++ b/include/vkDbg.h
@@ -109,8 +109,11 @@
     VK_DBG_OBJECT_PIPELINE_LAYOUT,
     VK_DBG_OBJECT_DESCRIPTOR_POOL,
 
+    VK_DBG_OBJECT_DISPLAY_WSI,
+    VK_DBG_OBJECT_SWAP_CHAIN_WSI,
+
     VK_DBG_OBJECT_TYPE_BEGIN_RANGE = VK_DBG_OBJECT_UNKNOWN,
-    VK_DBG_OBJECT_TYPE_END_RANGE   = VK_DBG_OBJECT_DESCRIPTOR_POOL,
+    VK_DBG_OBJECT_TYPE_END_RANGE   = VK_DBG_OBJECT_SWAP_CHAIN_WSI,
     VK_NUM_DBG_OBJECT_TYPE         = (VK_DBG_OBJECT_TYPE_END_RANGE - VK_DBG_OBJECT_TYPE_BEGIN_RANGE + 1),
 } VK_DBG_OBJECT_TYPE;
 
diff --git a/include/vkLayer.h b/include/vkLayer.h
index 70c36a9..55fb384 100644
--- a/include/vkLayer.h
+++ b/include/vkLayer.h
@@ -6,9 +6,7 @@
 
 #include "vulkan.h"
 #include "vkDbg.h"
-#if defined(__linux__) || defined(XCB_NVIDIA)
-#include "vkWsiX11Ext.h"
-#endif
+#include "vk_wsi_lunarg.h"
 #if defined(__GNUC__) && __GNUC__ >= 4
 #  define VK_LAYER_EXPORT __attribute__((visibility("default")))
 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
@@ -153,12 +151,11 @@
     PFN_vkDbgSetDeviceOption DbgSetDeviceOption;
     PFN_vkCmdDbgMarkerBegin CmdDbgMarkerBegin;
     PFN_vkCmdDbgMarkerEnd CmdDbgMarkerEnd;
-#if defined(__linux__) || defined(XCB_NVIDIA)
-    PFN_vkWsiX11AssociateConnection WsiX11AssociateConnection;
-    PFN_vkWsiX11GetMSC WsiX11GetMSC;
-    PFN_vkWsiX11CreatePresentableImage WsiX11CreatePresentableImage;
-    PFN_vkWsiX11QueuePresent WsiX11QueuePresent;
-#endif // WIN32
+    PFN_vkGetDisplayInfoWSI GetDisplayInfoWSI;
+    PFN_vkCreateSwapChainWSI CreateSwapChainWSI;
+    PFN_vkDestroySwapChainWSI DestroySwapChainWSI;
+    PFN_vkGetSwapChainInfoWSI GetSwapChainInfoWSI;
+    PFN_vkQueuePresentWSI QueuePresentWSI;
 } VkLayerDispatchTable;
 
 // LL node for tree of dbg callback functions
diff --git a/include/vkWsiWinExt.h b/include/vkWsiWinExt.h
deleted file mode 100644
index f3ee0f3..0000000
--- a/include/vkWsiWinExt.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* IN DEVELOPMENT.  DO NOT SHIP. */
-
-#ifndef __VKWSIWINEXT_H__
-#define __VKWSIWINEXT_H__
-
-// This is just to get windows to build.
-// Need to replace with the declarations for Windows wsi.
-typedef void VK_WSI_X11_CONNECTION_INFO;
-typedef unsigned int xcb_window_t;
-typedef unsigned int xcb_randr_crtc_t;
-typedef void VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO;
-typedef void VK_WSI_X11_PRESENT_INFO;
-
-#endif // __VKWSIWINEXT_H__
diff --git a/include/vkWsiX11Ext.h b/include/vkWsiX11Ext.h
deleted file mode 100644
index 3b39c64..0000000
--- a/include/vkWsiX11Ext.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* IN DEVELOPMENT.  DO NOT SHIP. */
-
-#ifndef __VKWSIX11EXT_H__
-#define __VKWSIX11EXT_H__
-
-#include <xcb/xcb.h>
-#include <xcb/randr.h>
-#include "vulkan.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif // __cplusplus
-
-typedef struct _VK_WSI_X11_CONNECTION_INFO {
-    xcb_connection_t*                           pConnection;
-    xcb_window_t                                root;
-    xcb_randr_provider_t                        provider;
-} VK_WSI_X11_CONNECTION_INFO;
-
-typedef struct _VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO
-{
-    VkFormat          format;
-    VkFlags           usage;           // VkImageUsageFlags
-    VkExtent2D        extent;
-    VkFlags           flags;
-} VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO;
-
-typedef struct _VK_WSI_X11_PRESENT_INFO
-{
-    /* which window to present to */
-    xcb_window_t destWindow;
-    VkImage srcImage;
-
-    /**
-     * After the command buffers in the queue have been completed, if the MSC
-     * of \p crtc is less than or equal to \p target_msc, wait until it
-     * reaches \p target_msc.
-     *
-     * If the current MSC of \p crtc is greater than \p target_msc, adjust
-     * \p target_msc as following:
-     *
-     *   if (divisor) {
-     *       target_msc = crtc_msc - (crtc_msc % divisor) + remainder;
-     *       if (target_msc < crtc_msc)
-     *           target_msc += divisor;
-     *   } else {
-     *       target_msc = crtc_msc;
-     *   }
-     *
-     * In other words, either set \p target_msc to an absolute value (require
-     * vkWsiX11GetMSC(), potentially a round-trip to the server, to get the
-     * current MSC first), or set \p target_msc to zero and set a "swap
-     * interval".
-     *
-     * \p crtc can be XCB_NONE.  In that case, a suitable CRTC is picked based
-     * on \p destWindow.
-     */
-    xcb_randr_crtc_t crtc;
-    uint64_t target_msc;
-    uint64_t divisor;
-    uint64_t remainder;
-
-    /**
-     * After waiting for the current and target MSCs to match, the
-     * presentation is scheduled.  When \p async is false, it will occur the
-     * next time current MSC is incremented.  When \p async is true, it will
-     * occur as soon as possible.
-     */
-    bool32_t async;
-
-    /**
-     * When \p flip is false, the contents of \p srcImage are copied to
-     * \p destWindow when the presentation occurs.  When \p flip is true,
-     * \p srcImage is made the front buffer of \p destWindow.
-     *
-     * An error may be returned if \p flip is true but \p destWindow can not
-     * be flipped to.
-     */
-    bool32_t flip;
-} VK_WSI_X11_PRESENT_INFO;
-
-typedef VkResult (VKAPI *PFN_vkWsiX11AssociateConnection)(VkPhysicalDevice gpu, const VK_WSI_X11_CONNECTION_INFO* pConnectionInfo);
-typedef VkResult (VKAPI *PFN_vkWsiX11GetMSC)(VkDevice device, xcb_window_t window, xcb_randr_crtc_t crtc, uint64_t* pMsc);
-typedef VkResult (VKAPI *PFN_vkWsiX11CreatePresentableImage)(VkDevice device, const VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO* pCreateInfo, VkImage* pImage, VkDeviceMemory* pMem);
-typedef VkResult (VKAPI *PFN_vkWsiX11QueuePresent)(VkQueue queue, const VK_WSI_X11_PRESENT_INFO* pPresentInfo, VkFence fence);
-
-/**
- * Associate an X11 connection with a GPU.  This should be done before device
- * creation.  If the device is already created,
- * VK_ERROR_DEVICE_ALREADY_CREATED is returned.
- *
- * Truth is, given a connection, we could find the associated GPU.  But
- * without having a GPU as the first parameter, the loader could not find the
- * dispatch table.
- *
- * This function is available when vkGetGlobalExtensionInfo says "VK_WSI_X11"
- * is supported.
- */
-VkResult VKAPI vkWsiX11AssociateConnection(
-    VkPhysicalDevice                            gpu,
-    const VK_WSI_X11_CONNECTION_INFO*          pConnectionInfo);
-
-/**
- * Return the current MSC (Media Stream Counter, incremented for each vblank)
- * of \p crtc.  If crtc is \p XCB_NONE, a suitable CRTC is picked based on \p
- * win.
- */
-VkResult VKAPI vkWsiX11GetMSC(
-    VkDevice                                  device,
-    xcb_window_t                                window,
-    xcb_randr_crtc_t                            crtc,
-    uint64_t*                                   pMsc);
-
-/**
- * Create an VkImage that can be presented.  An VkDeviceMemory is created
- * and bound automatically.  The memory returned can only be used in
- * vkQueue[Add|Remove]MemReference.  Destroying the memory or binding another memory to the
- * image is not allowed.
- */
-VkResult VKAPI vkWsiX11CreatePresentableImage(
-    VkDevice                                  device,
-    const VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO* pCreateInfo,
-    VkImage*                                  pImage,
-    VkDeviceMemory*                             pMem);
-
-/**
- * Present an image to an X11 window.  The presentation always occurs after
- * the command buffers in the queue have been completed, subject to other
- * parameters specified in VK_WSI_X11_PRESENT_INFO.
- *
- * Fence is reached when the presentation occurs.
- */
-VkResult VKAPI vkWsiX11QueuePresent(
-    VkQueue                                   queue,
-    const VK_WSI_X11_PRESENT_INFO*             pPresentInfo,
-    VkFence                                   fence);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-
-#endif // __VKWSIX11EXT_H__
diff --git a/layers/glave_snapshot.c b/layers/glave_snapshot.c
index 1a399b9..b4a2507 100644
--- a/layers/glave_snapshot.c
+++ b/layers/glave_snapshot.c
@@ -525,7 +525,8 @@
     GLV_VK_SNAPSHOT_LL_NODE *pTrav = s_delta.pGlobalObjs;
     while (pTrav != NULL)
     {
-        if (pTrav->obj.objType == VK_OBJECT_TYPE_PRESENTABLE_IMAGE_MEMORY)
+        if (pTrav->obj.objType == VK_OBJECT_TYPE_SWAP_CHAIN_IMAGE_WSI ||
+            pTrav->obj.objType == VK_OBJECT_TYPE_SWAP_CHAIN_MEMORY_WSI)
         {
             GLV_VK_SNAPSHOT_LL_NODE *pDel = pTrav;
             pTrav = pTrav->pNextGlobal;
@@ -1691,58 +1692,67 @@
     nextTable.CmdDbgMarkerEnd(cmdBuffer);
 }
 
-#if defined(__linux__) || defined(XCB_NVIDIA)
-
-VK_LAYER_EXPORT VkResult VKAPI vkWsiX11AssociateConnection(VkPhysicalGpu gpu, const VK_WSI_X11_CONNECTION_INFO* pConnectionInfo)
+VK_LAYER_EXPORT VkResult VKAPI xglGetDisplayInfoWSI(VkDisplayWSI display, VkDisplayInfoTypeWSI infoType, size_t* pDataSize, void* pData)
 {
-    VkBaseLayerObject* gpuw = (VkBaseLayerObject *) gpu;
     loader_platform_thread_lock_mutex(&objLock);
-    ll_increment_use_count((void*)gpu, VK_OBJECT_TYPE_PHYSICAL_GPU);
+    ll_increment_use_count((void*)display, VK_OBJECT_TYPE_DISPLAY_WSI);
     loader_platform_thread_unlock_mutex(&objLock);
-    pCurObj = gpuw;
-    loader_platform_thread_once(&tabOnce, initGlaveSnapshot);
-    VkResult result = nextTable.WsiX11AssociateConnection((VkPhysicalGpu)gpuw->nextObject, pConnectionInfo);
+    VkResult result = nextTable.GetDisplayInfoWSI(display, infoType, pDataSize, pData);
     return result;
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkWsiX11GetMSC(VkDevice device, xcb_window_t window, xcb_randr_crtc_t crtc, uint64_t* pMsc)
+VK_LAYER_EXPORT VkResult VKAPI xglCreateSwapChainWSI(VkDevice device, const VkSwapChainCreateInfoWSI* pCreateInfo, VkSwapChainWSI* pSwapChain)
 {
     loader_platform_thread_lock_mutex(&objLock);
     ll_increment_use_count((void*)device, VK_OBJECT_TYPE_DEVICE);
     loader_platform_thread_unlock_mutex(&objLock);
-    VkResult result = nextTable.WsiX11GetMSC(device, window, crtc, pMsc);
-    return result;
-}
-
-VK_LAYER_EXPORT VkResult VKAPI vkWsiX11CreatePresentableImage(VkDevice device, const VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO* pCreateInfo, VkImage* pImage, VkGpuMemory* pMem)
-{
-    loader_platform_thread_lock_mutex(&objLock);
-    ll_increment_use_count((void*)device, VK_OBJECT_TYPE_DEVICE);
-    loader_platform_thread_unlock_mutex(&objLock);
-    VkResult result = nextTable.WsiX11CreatePresentableImage(device, pCreateInfo, pImage, pMem);
-
+    VkResult result = nextTable.CreateSwapChainWSI(device, pCreateInfo, pSwapChain);
     if (result == VK_SUCCESS)
     {
         loader_platform_thread_lock_mutex(&objLock);
 
+#if 0
         GLV_VK_SNAPSHOT_LL_NODE* pNode = snapshot_insert_object(&s_delta, *pImage, VK_OBJECT_TYPE_IMAGE);
         pNode->obj.pStruct = NULL;
 
         GLV_VK_SNAPSHOT_LL_NODE* pMemNode = snapshot_insert_object(&s_delta, *pMem, VK_OBJECT_TYPE_PRESENTABLE_IMAGE_MEMORY);
         pMemNode->obj.pStruct = NULL;
+#else
+        snapshot_insert_object(&s_delta, (void*)*pSwapChain, VK_OBJECT_TYPE_SWAP_CHAIN_WSI);
+#endif
 
         loader_platform_thread_unlock_mutex(&objLock);
     }
     return result;
+
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkWsiX11QueuePresent(VkQueue queue, const VK_WSI_X11_PRESENT_INFO* pPresentInfo, VkFence fence)
+VK_LAYER_EXPORT VkResult VKAPI xglDestroySwapChainWSI(VkSwapChainWSI swapChain)
 {
-    VkResult result = nextTable.WsiX11QueuePresent(queue, pPresentInfo, fence);
+    VkResult result = nextTable.DestroySwapChainWSI(swapChain);
+    loader_platform_thread_lock_mutex(&objLock);
+    snapshot_remove_object(&s_delta, (void*)swapChain);
+    loader_platform_thread_unlock_mutex(&objLock);
     return result;
 }
 
-#endif
+VK_LAYER_EXPORT VkResult VKAPI xglGetSwapChainInfoWSI(VkSwapChainWSI swapChain, VkSwapChainInfoTypeWSI infoType, size_t* pDataSize, void* pData)
+{
+    loader_platform_thread_lock_mutex(&objLock);
+    ll_increment_use_count((void*)swapChain, VK_OBJECT_TYPE_SWAP_CHAIN_WSI);
+    loader_platform_thread_unlock_mutex(&objLock);
+    VkResult result = nextTable.GetSwapChainInfoWSI(swapChain, infoType, pDataSize, pData);
+    return result;
+}
+
+VK_LAYER_EXPORT VkResult VKAPI xglQueuePresentWSI(VkQueue queue, const VkPresentInfoWSI* pPresentInfo)
+{
+    loader_platform_thread_lock_mutex(&objLock);
+    ll_increment_use_count((void*)queue, VK_OBJECT_TYPE_QUEUE);
+    loader_platform_thread_unlock_mutex(&objLock);
+    VkResult result = nextTable.QueuePresentWSI(queue, pPresentInfo);
+    return result;
+}
 
 //=================================================================================================
 // Exported methods
diff --git a/layers/glave_snapshot.h b/layers/glave_snapshot.h
index f0de0e9..9ca095b 100644
--- a/layers/glave_snapshot.h
+++ b/layers/glave_snapshot.h
@@ -90,7 +90,11 @@
     VK_OBJECT_TYPE_DYNAMIC_RS_STATE_OBJECT,
     VK_OBJECT_TYPE_FENCE,
     VK_OBJECT_TYPE_CMD_BUFFER,
-    VK_OBJECT_TYPE_PRESENTABLE_IMAGE_MEMORY,
+
+    VK_OBJECT_TYPE_DISPLAY_WSI,
+    VK_OBJECT_TYPE_SWAP_CHAIN_WSI,
+    VK_OBJECT_TYPE_SWAP_CHAIN_IMAGE_WSI,
+    VK_OBJECT_TYPE_SWAP_CHAIN_MEMORY_WSI,
 
     VK_NUM_OBJECT_TYPE,
     VK_OBJECT_TYPE_ANY, // Allow global object list to be queried/retrieved
@@ -157,8 +161,14 @@
             return "QUERY_POOL";
         case VK_OBJECT_TYPE_DESCRIPTOR_POOL:
             return "DESCRIPTOR_POOL";
-        case VK_OBJECT_TYPE_PRESENTABLE_IMAGE_MEMORY:
-            return "PRESENTABLE_IMAGE_MEMORY";
+        case VK_OBJECT_TYPE_DISPLAY_WSI:
+            return "DISPLAY_WSI";
+        case VK_OBJECT_TYPE_SWAP_CHAIN_WSI:
+            return "SWAP_CHAIN_WSI";
+        case VK_OBJECT_TYPE_SWAP_CHAIN_IMAGE_WSI:
+            return "SWAP_CHAIN_IMAGE_WSI";
+        case VK_OBJECT_TYPE_SWAP_CHAIN_MEMORY_WSI:
+            return "SWAP_CHAIN_MEMORY_WSI";
         default:
             return "UNKNOWN";
     }
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index 10215e6..bf0a325 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -29,6 +29,7 @@
 #include <assert.h>
 #include <list>
 #include <map>
+#include <vector>
 using namespace std;
 
 #include "loader_platform.h"
@@ -55,6 +56,7 @@
 map<VkObject,     MT_OBJ_INFO*>     objectMap;
 map<uint64_t,       MT_FENCE_INFO*>   fenceMap;    // Map fenceId to fence info
 map<VkQueue,      MT_QUEUE_INFO*>   queueMap;
+map<VkSwapChainWSI, MT_SWAP_CHAIN_INFO*>   swapChainMap;
 
 // TODO : Add per-device fence completion
 static uint64_t     g_currentFenceId  = 1;
@@ -78,6 +80,12 @@
     queueMap.clear();
 }
 
+static void addSwapChainInfo(const VkSwapChainWSI swapChain)
+{
+    MT_SWAP_CHAIN_INFO* pInfo = new MT_SWAP_CHAIN_INFO;
+    swapChainMap[swapChain] = pInfo;
+}
+
 // Add new CBInfo for this cb to map container
 static void addCBInfo(const VkCmdBuffer cb)
 {
@@ -362,7 +370,7 @@
     pInfo->refCount           = 0;
     memset(&pInfo->allocInfo, 0, sizeof(VkMemoryAllocInfo));
 
-    if (pAllocInfo) {  // MEM alloc created by vkWsiX11CreatePresentableImage() doesn't have alloc info struct
+    if (pAllocInfo) {  // MEM alloc created by vkCreateSwapChainWSI() doesn't have alloc info struct
         memcpy(&pInfo->allocInfo, pAllocInfo, sizeof(VkMemoryAllocInfo));
         // TODO:  Update for real hardware, actually process allocation info structures
         pInfo->allocInfo.pNext = NULL;
@@ -570,7 +578,7 @@
     } else {
         if (pInfo->allocInfo.allocationSize == 0 && !internal) {
             char str[1024];
-            sprintf(str, "Attempting to free memory associated with a Presentable Image, %p, this should not be explicitly freed\n", (void*)mem);
+            sprintf(str, "Attempting to free memory associated with a Persistent Image, %p, this should not be explicitly freed\n", (void*)mem);
             layerCbMsg(VK_DBG_MSG_WARNING, VK_VALIDATION_LEVEL_0, mem, 0, MEMTRACK_INVALID_MEM_OBJ, "MEM", str);
             result = VK_FALSE;
         } else {
@@ -767,7 +775,7 @@
             sprintf(str, "    Mem Alloc info:\n%s", pAllocInfoMsg.c_str());
             layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, NULL, 0, MEMTRACK_NONE, "MEM", str);
         } else {
-            sprintf(str, "    Mem Alloc info is NULL (alloc done by vkWsiX11CreatePresentableImage())");
+            sprintf(str, "    Mem Alloc info is NULL (alloc done by vkCreateSwapChainWSI())");
             layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, NULL, 0, MEMTRACK_NONE, "MEM", str);
         }
 
@@ -1938,40 +1946,82 @@
     return result;
 }
 
-#if !defined(WIN32)
-VK_LAYER_EXPORT VkResult VKAPI vkWsiX11CreatePresentableImage(VkDevice device, const VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO* pCreateInfo,
-    VkImage* pImage, VkDeviceMemory* pMem)
+VK_LAYER_EXPORT VkResult VKAPI vkCreateSwapChainWSI(VkDevice device, const VkSwapChainCreateInfoWSI* pCreateInfo, VkSwapChainWSI* pSwapChain)
 {
-    VkResult result = nextTable.WsiX11CreatePresentableImage(device, pCreateInfo, pImage, pMem);
-    loader_platform_thread_lock_mutex(&globalLock);
+    VkResult result = nextTable.CreateSwapChainWSI(device, pCreateInfo, pSwapChain);
+
     if (VK_SUCCESS == result) {
-        // Add image object, then insert the new Mem Object and then bind it to created image
-        addObjectInfo(*pImage, VK_STRUCTURE_TYPE_MAX_ENUM, pCreateInfo, sizeof(VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO), "wsi_x11_image");
-        addMemObjInfo(*pMem, NULL);
-        if (VK_FALSE == updateObjectBinding(*pImage, *pMem)) {
-            char str[1024];
-            sprintf(str, "In vkWsiX11CreatePresentableImage(), unable to set image %p binding to mem obj %p", (void*)*pImage, (void*)*pMem);
-            layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, *pImage, 0, MEMTRACK_MEMORY_BINDING_ERROR, "MEM", str);
-        }
+        loader_platform_thread_lock_mutex(&globalLock);
+        addSwapChainInfo(*pSwapChain);
+        loader_platform_thread_unlock_mutex(&globalLock);
     }
-    printObjList();
-    printMemList();
-    loader_platform_thread_unlock_mutex(&globalLock);
+
     return result;
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkWsiX11QueuePresent(VkQueue queue, const VK_WSI_X11_PRESENT_INFO*  pPresentInfo, VkFence fence)
+VK_LAYER_EXPORT VkResult VKAPI vkDestroySwapChainWSI(VkSwapChainWSI swapChain)
 {
     loader_platform_thread_lock_mutex(&globalLock);
-    addFenceInfo(fence, queue);
-    char            str[1024];
-    sprintf(str, "In vkWsiX11QueuePresent(), checking queue %p for fence %p", queue, fence);
-    layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, queue, 0, MEMTRACK_NONE, "MEM", str);
+
+    if (swapChainMap.find(swapChain) != swapChainMap.end()) {
+        MT_SWAP_CHAIN_INFO* pInfo = swapChainMap[swapChain];
+
+        for (std::vector<VkSwapChainImageInfoWSI>::const_iterator it = pInfo->images.begin();
+             it != pInfo->images.end(); it++) {
+            clearObjectBinding(it->image);
+            freeMemObjInfo(it->memory, true);
+
+            MT_OBJ_INFO* pDelInfo = objectMap[it->image];
+            delete pDelInfo;
+            objectMap.erase(it->image);
+        }
+
+        delete pInfo;
+        swapChainMap.erase(swapChain);
+    }
+
     loader_platform_thread_unlock_mutex(&globalLock);
-    VkResult result = nextTable.WsiX11QueuePresent(queue, pPresentInfo, fence);
+
+    return nextTable.DestroySwapChainWSI(swapChain);
+}
+
+VK_LAYER_EXPORT VkResult VKAPI vkGetSwapChainInfoWSI(VkSwapChainWSI swapChain, VkSwapChainInfoTypeWSI infoType, size_t* pDataSize, void* pData)
+{
+    VkResult result = nextTable.GetSwapChainInfoWSI(swapChain, infoType, pDataSize, pData);
+
+    if (infoType == VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI && result == VK_SUCCESS) {
+        const size_t count = *pDataSize / sizeof(VkSwapChainImageInfoWSI);
+        MT_SWAP_CHAIN_INFO *pInfo = swapChainMap[swapChain];
+
+        if (pInfo->images.empty()) {
+            pInfo->images.resize(count);
+            memcpy(&pInfo->images[0], pData, sizeof(pInfo->images[0]) * count);
+
+            for (std::vector<VkSwapChainImageInfoWSI>::const_iterator it = pInfo->images.begin();
+                 it != pInfo->images.end(); it++) {
+                // Add image object, then insert the new Mem Object and then bind it to created image
+                addObjectInfo(it->image, VK_STRUCTURE_TYPE_MAX_ENUM, &pInfo->createInfo, sizeof(pInfo->createInfo), "persistent_image");
+                addMemObjInfo(it->memory, NULL);
+                if (VK_FALSE == updateObjectBinding(it->image, it->memory)) {
+                    char str[1024];
+                    sprintf(str, "In vkGetSwapChainInfoWSI(), unable to set image %p binding to mem obj %p", (void*)it->image, (void*)it->memory);
+                    layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, it->image, 0, MEMTRACK_MEMORY_BINDING_ERROR, "MEM", str);
+                }
+            }
+        } else {
+            const bool mismatch = (pInfo->images.size() != count ||
+                    memcmp(&pInfo->images[0], pData, sizeof(pInfo->images[0]) * count));
+
+            if (mismatch) {
+                char str[1024];
+                sprintf(str, "vkGetSwapChainInfoWSI(%p, VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI) returned mismatching data", swapChain);
+                layerCbMsg(VK_DBG_MSG_WARNING, VK_VALIDATION_LEVEL_0, (VkBaseObject) swapChain, 0, MEMTRACK_NONE, "SWAP_CHAIN", str);
+            }
+        }
+    }
+
     return result;
 }
-#endif // WIN32
 
 VK_LAYER_EXPORT void* VKAPI vkGetProcAddr(VkPhysicalDevice gpu, const char* funcName)
 {
@@ -2122,12 +2172,12 @@
         return (void*) vkQueueAddMemReferences;
     if (!strcmp(funcName, "vkQueueRemoveMemReferences"))
         return (void*) vkQueueRemoveMemReferences;
-#if !defined(WIN32)
-    if (!strcmp(funcName, "vkWsiX11CreatePresentableImage"))
-        return (void*) vkWsiX11CreatePresentableImage;
-    if (!strcmp(funcName, "vkWsiX11QueuePresent"))
-        return (void*) vkWsiX11QueuePresent;
-#endif
+    if (!strcmp(funcName, "vkCreateSwapChainWSI"))
+        return (void*) vkCreateSwapChainWSI;
+    if (!strcmp(funcName, "vkDestroySwapChainWSI"))
+        return (void*) vkDestroySwapChainWSI;
+    if (!strcmp(funcName, "vkGetSwapChainInfoWSI"))
+        return (void*) vkGetSwapChainInfoWSI;
     else {
         if (gpuw->pGPA == NULL)
             return NULL;
diff --git a/layers/mem_tracker.h b/layers/mem_tracker.h
index d1d2b82..417da1d 100644
--- a/layers/mem_tracker.h
+++ b/layers/mem_tracker.h
@@ -22,6 +22,7 @@
  * DEALINGS IN THE SOFTWARE.
  */
 #pragma once
+#include <vector>
 #include "vkLayer.h"
 
 #ifdef __cplusplus
@@ -108,9 +109,7 @@
         VkComputePipelineCreateInfo          compute_pipeline_create_info;
         VkSamplerCreateInfo                   sampler_create_info;
         VkFenceCreateInfo                     fence_create_info;
-#ifndef _WIN32
-        VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO wsi_x11_presentable_image_create_info;
-#endif // _WIN32
+        VkSwapChainCreateInfoWSI            swap_chain_create_info;
     } create_info;
     char object_name[64];
 };
@@ -143,6 +142,11 @@
     list<VkDeviceMemory>          pMemRefList;
 };
 
+struct MT_SWAP_CHAIN_INFO {
+    VkSwapChainCreateInfoWSI createInfo;
+    std::vector<VkSwapChainImageInfoWSI> images;
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/layers/object_track.h b/layers/object_track.h
index 64e95b0..7b86c37 100644
--- a/layers/object_track.h
+++ b/layers/object_track.h
@@ -87,7 +87,11 @@
     VkObjectTypeDynamicRsState,
     VkObjectTypeFence,
     VkObjectTypeCmdBuffer,
-    VkObjectTypePresentableImageMemory,
+
+    VkObjectTypeDisplayWSI,
+    VkObjectTypeSwapChainWSI,
+    VkObjectTypeSwapChainImageWSI,
+    VkObjectTypeSwapChainMemoryWSI,
 
     VkObjectTypeUnknown,
     VkNumObjectType,
@@ -155,8 +159,15 @@
             return "QUERY_POOL";
         case VkObjectTypeDescriptorPool:
             return "DESCRIPTOR_POOL";
-        case VkObjectTypePresentableImageMemory:
-            return "PRESENTABLE_IMAGE_MEMORY";
+
+        case VkObjectTypeDisplayWSI:
+            return "DISPLAY_WSI";
+        case VkObjectTypeSwapChainWSI:
+            return "SWAP_CHAIN_WSI";
+        case VkObjectTypeSwapChainImageWSI:
+            return "SWAP_CHAIN_IMAGE_WSI";
+        case VkObjectTypeSwapChainMemoryWSI:
+            return "SWAP_CHAIN_MEMORY_WSI";
         default:
             return "UNKNOWN";
     }
diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp
index e3058a5..b3eb1dc 100644
--- a/layers/param_checker.cpp
+++ b/layers/param_checker.cpp
@@ -1952,39 +1952,35 @@
     nextTable.CmdDbgMarkerEnd(cmdBuffer);
 }
 
-#if defined(__linux__) || defined(XCB_NVIDIA)
-
-VK_LAYER_EXPORT VkResult VKAPI vkWsiX11AssociateConnection(VkPhysicalDevice gpu, const VK_WSI_X11_CONNECTION_INFO* pConnectionInfo)
+VK_LAYER_EXPORT VkResult VKAPI vkGetDisplayInfoWSI(VkDisplayWSI display, VkDisplayInfoTypeWSI infoType, size_t* pDataSize, void* pData)
 {
-    pCurObj = (VkBaseLayerObject *) gpu;
-    loader_platform_thread_once(&tabOnce, initParamChecker);
-
-    VkResult result = nextTable.WsiX11AssociateConnection(gpu, pConnectionInfo);
+    VkResult result = nextTable.GetDisplayInfoWSI(display, infoType, pDataSize, pData);
     return result;
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkWsiX11GetMSC(VkDevice device, xcb_window_t window, xcb_randr_crtc_t crtc, uint64_t* pMsc)
+VK_LAYER_EXPORT VkResult VKAPI vkCreateSwapChainWSI(VkDevice device, const VkSwapChainCreateInfoWSI* pCreateInfo, VkSwapChainWSI* pSwapChain)
 {
-
-    VkResult result = nextTable.WsiX11GetMSC(device, window, crtc, pMsc);
+    VkResult result = nextTable.CreateSwapChainWSI(device, pCreateInfo, pSwapChain);
     return result;
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkWsiX11CreatePresentableImage(VkDevice device, const VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO* pCreateInfo, VkImage* pImage, VkDeviceMemory* pMem)
+VK_LAYER_EXPORT VkResult VKAPI vkDestroySwapChainWSI(VkSwapChainWSI swapChain)
 {
-
-    VkResult result = nextTable.WsiX11CreatePresentableImage(device, pCreateInfo, pImage, pMem);
+    VkResult result = nextTable.DestroySwapChainWSI(swapChain);
     return result;
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkWsiX11QueuePresent(VkQueue queue, const VK_WSI_X11_PRESENT_INFO* pPresentInfo, VkFence fence)
+VK_LAYER_EXPORT VkResult VKAPI vkGetSwapChainInfoWSI(VkSwapChainWSI swapChain, VkSwapChainInfoTypeWSI infoType, size_t* pDataSize, void* pData)
 {
-
-    VkResult result = nextTable.WsiX11QueuePresent(queue, pPresentInfo, fence);
+    VkResult result = nextTable.GetSwapChainInfoWSI(swapChain, infoType, pDataSize, pData);
     return result;
 }
 
-#endif
+VK_LAYER_EXPORT VkResult VKAPI vkQueuePresentWSI(VkQueue queue, const VkPresentInfoWSI* pPresentInfo)
+{
+    VkResult result = nextTable.QueuePresentWSI(queue, pPresentInfo);
+    return result;
+}
 
 #include "vk_generic_intercept_proc_helper.h"
 VK_LAYER_EXPORT void* VKAPI vkGetProcAddr(VkPhysicalDevice gpu, const char* funcName)
diff --git a/loader/loader.h b/loader/loader.h
index 79d77c8..ce157bf 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -30,11 +30,7 @@
 
 #include <vulkan.h>
 #include <vkDbg.h>
-#if defined(WIN32)
-// FIXME: NEED WINDOWS EQUIVALENT
-#else // WIN32
-#include <vkWsiX11Ext.h>
-#endif // WIN32
+#include <vk_wsi_lunarg.h>
 #include <vkLayer.h>
 #include <vkIcd.h>
 #include <assert.h>
diff --git a/tests/test_environment.cpp b/tests/test_environment.cpp
index 03beb12..90483ec 100644
--- a/tests/test_environment.cpp
+++ b/tests/test_environment.cpp
@@ -7,7 +7,7 @@
 namespace vk_testing {
 
 Environment::Environment() :
-    m_connection(NULL), default_dev_(0)
+    default_dev_(0)
 {
     app_.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
     app_.pAppName = "vk_testing";
@@ -77,64 +77,8 @@
     }
 }
 
-void Environment::X11SetUp()
-{
-
-    uint32_t count;
-    VkResult err;
-    const xcb_setup_t *setup;
-    xcb_screen_iterator_t iter;
-    int scr;
-    VkInstanceCreateInfo instInfo = {};
-    instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
-    instInfo.pNext = NULL;
-    instInfo.pAppInfo = &app_;
-    instInfo.pAllocCb = NULL;
-    instInfo.extensionCount = 0;
-    instInfo.ppEnabledExtensionNames = NULL;
-
-    err = vkCreateInstance(&instInfo, &inst);
-    ASSERT_EQ(VK_SUCCESS, err);
-    err = vkEnumeratePhysicalDevices(inst, &count, NULL);
-    ASSERT_EQ(VK_SUCCESS, err);
-    ASSERT_LE(count, ARRAY_SIZE(gpus));
-    err = vkEnumeratePhysicalDevices(inst, &count, gpus);
-    ASSERT_EQ(VK_SUCCESS, err);
-    ASSERT_GT(count, default_dev_);
-
-    m_connection = xcb_connect(NULL, &scr);
-
-    setup = xcb_get_setup(m_connection);
-    iter = xcb_setup_roots_iterator(setup);
-    while (scr-- > 0)
-        xcb_screen_next(&iter);
-
-    m_screen = iter.data;
-
-    VK_WSI_X11_CONNECTION_INFO connection_info = {};
-    connection_info.pConnection = m_connection;
-    connection_info.root = m_screen->root;
-    connection_info.provider = 0;
-
-    err = vkWsiX11AssociateConnection(gpus[0], &connection_info);
-    assert(!err);
-
-
-    devs_.reserve(count);
-    for (uint32_t i = 0; i < count; i++) {
-        devs_.push_back(new Device(gpus[i]));
-        if (i == default_dev_) {
-            devs_[i]->init();
-            ASSERT_NE(true, devs_[i]->graphics_queues().empty());
-        }
-    }
-}
-
 void Environment::TearDown()
 {
-    if (m_connection)
-        xcb_disconnect(m_connection);
-
     // destroy devices first
     for (std::vector<Device *>::iterator it = devs_.begin(); it != devs_.end(); it++)
         delete *it;
diff --git a/tests/test_environment.h b/tests/test_environment.h
index 43530a7..fba8885 100644
--- a/tests/test_environment.h
+++ b/tests/test_environment.h
@@ -1,7 +1,7 @@
 #ifndef TEST_ENVIRONMENT_H
 #define TEST_ENVIRONMENT_H
+
 #include "vktestbinding.h"
-#include <vkWsiX11Ext.h>
 
 namespace vk_testing {
 class Environment : public ::testing::Environment {
@@ -11,10 +11,7 @@
     bool parse_args(int argc, char **argv);
 
     virtual void SetUp();
-    virtual void X11SetUp();
     virtual void TearDown();
-    xcb_connection_t         *m_connection;
-    xcb_screen_t             *m_screen;
 
     const std::vector<Device *> &devices() { return devs_; }
     Device &default_device() { return *(devs_[default_dev_]); }
diff --git a/tests/vktestbinding.cpp b/tests/vktestbinding.cpp
index abfaca4..10afce8 100644
--- a/tests/vktestbinding.cpp
+++ b/tests/vktestbinding.cpp
@@ -150,7 +150,7 @@
 {
     // Extensions to enable
     static const char *known_exts[] = {
-        "VK_WSI_X11",
+        "VK_WSI_LunarG",
     };
     std::vector<const char *> exts;
     size_t extSize = sizeof(uint32_t);
diff --git a/tests/vktestframework.cpp b/tests/vktestframework.cpp
index 8f9f360..20904a3 100644
--- a/tests/vktestframework.cpp
+++ b/tests/vktestframework.cpp
@@ -28,6 +28,8 @@
 #include <limits.h>
 #include <math.h>
 #include <wand/MagickWand.h>
+#include <xcb/xcb.h>
+#include <vk_wsi_lunarg.h>
 
 // Command-line options
 enum TOptions {
@@ -47,6 +49,43 @@
     EOptionDefaultDesktop     = 0x1000,
 };
 
+class TestFrameworkVkPresent
+{
+public:
+    TestFrameworkVkPresent(vk_testing::Device &device);
+
+    void Run();
+    void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn);
+    void CreateMyWindow();
+    void CreateSwapChain();
+    void TearDown();
+
+protected:
+    vk_testing::Device                    &m_device;
+    vk_testing::Queue                     &m_queue;
+    vk_testing::CmdBuffer                  m_cmdbuf;
+
+private:
+    xcb_connection_t                       *m_connection;
+    xcb_screen_t                           *m_screen;
+    xcb_window_t                            m_window;
+    xcb_intern_atom_reply_t                *m_atom_wm_delete_window;
+    std::list<VkTestImageRecord>           m_images;
+
+    VkSwapChainWSI                          m_swap_chain;
+
+    bool                                    m_quit;
+    bool                                    m_pause;
+
+    uint32_t                                m_width;
+    uint32_t                                m_height;
+
+    std::list<VkTestImageRecord>::iterator m_display_image;
+
+    void Display();
+    void HandleEvent(xcb_generic_event_t *event);
+};
+
 #ifndef _WIN32
 
 #include <errno.h>
@@ -380,10 +419,8 @@
     }
 }
 
-static vk_testing::Environment *environment;
-
-TestFrameworkVkPresent::TestFrameworkVkPresent() :
-   m_device(environment->default_device()),
+TestFrameworkVkPresent::TestFrameworkVkPresent(vk_testing::Device &device) :
+   m_device(device),
    m_queue(*m_device.graphics_queues()[0]),
    m_cmdbuf(m_device, vk_testing::CmdBuffer::create_info(m_device.graphics_queue_node_index_))
 {
@@ -397,11 +434,12 @@
 {
     VkResult err;
 
-    VK_WSI_X11_PRESENT_INFO present = {};
-    present.destWindow = m_window;
-    present.srcImage = m_display_image->m_presentableImage;
+    VkPresentInfoWSI present = {};
+    present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_WSI;
+    present.image = m_display_image->m_presentableImage;
+    present.flipInterval = 1;
 
-    xcb_change_property (environment->m_connection,
+    xcb_change_property (m_connection,
                          XCB_PROP_MODE_REPLACE,
                          m_window,
                          XCB_ATOM_WM_NAME,
@@ -410,7 +448,7 @@
                          m_display_image->m_title.size(),
                          m_display_image->m_title.c_str());
 
-    err = vkWsiX11QueuePresent(m_queue.obj(), &present, NULL);
+    err = vkQueuePresentWSI(m_queue.obj(), &present);
     assert(!err);
 
     m_queue.wait();
@@ -466,15 +504,15 @@
 
 void  TestFrameworkVkPresent::Run()
 {
-    xcb_flush(environment->m_connection);
+    xcb_flush(m_connection);
 
     while (! m_quit) {
         xcb_generic_event_t *event;
 
         if (m_pause) {
-            event = xcb_wait_for_event(environment->m_connection);
+            event = xcb_wait_for_event(m_connection);
         } else {
-            event = xcb_poll_for_event(environment->m_connection);
+            event = xcb_poll_for_event(m_connection);
         }
         if (event) {
             HandleEvent(event);
@@ -483,26 +521,42 @@
     }
 }
 
-void TestFrameworkVkPresent::CreatePresentableImages()
+void TestFrameworkVkPresent::CreateSwapChain()
 {
     VkResult err;
 
+    VkSwapChainCreateInfoWSI swap_chain = {};
+    swap_chain.sType = VK_STRUCTURE_TYPE_SWAP_CHAIN_CREATE_INFO_WSI;
+    swap_chain.pNativeWindowSystemHandle = (void *) m_connection;
+    swap_chain.pNativeWindowHandle = (void *) (intptr_t) m_window;
+    swap_chain.imageCount = m_images.size();
+    swap_chain.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
+    swap_chain.imageExtent.width = m_width;
+    swap_chain.imageExtent.height = m_height;
+    swap_chain.imageArraySize = 1;
+    swap_chain.imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT;
+    swap_chain.swapModeFlags = VK_SWAP_MODE_FLIP_BIT_WSI |
+                               VK_SWAP_MODE_BLIT_BIT_WSI;
+
+    err = vkCreateSwapChainWSI(m_device.obj(), &swap_chain, &m_swap_chain);
+    assert(!err);
+
+    size_t size = sizeof(VkSwapChainImageInfoWSI) * m_images.size();
+    std::vector<VkSwapChainImageInfoWSI> persistent_images;
+    persistent_images.resize(m_images.size());
+    err = vkGetSwapChainInfoWSI(m_swap_chain,
+            VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI,
+            &size, &persistent_images[0]);
+    assert(!err && size == sizeof(VkSwapChainImageInfoWSI) * m_images.size());
+
     m_display_image = m_images.begin();
 
     for (int x=0; x < m_images.size(); x++)
     {
-        VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO presentable_image_info = {};
-        presentable_image_info.format = VK_FORMAT_B8G8R8A8_UNORM;
-        presentable_image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
-        presentable_image_info.extent.width = m_display_image->m_width;
-        presentable_image_info.extent.height = m_display_image->m_height;
-        presentable_image_info.flags = 0;
-
         void *dest_ptr;
 
-        err = vkWsiX11CreatePresentableImage(m_device.obj(), &presentable_image_info,
-                        &m_display_image->m_presentableImage, &m_display_image->m_presentableMemory);
-        assert(!err);
+        m_display_image->m_presentableImage = persistent_images[x].image;
+        m_display_image->m_presentableMemory = persistent_images[x].memory;
 
         vk_testing::Buffer buf;
         buf.init(m_device, (VkDeviceSize) m_display_image->m_data_size);
@@ -535,15 +589,7 @@
         vkQueueRemoveMemReferences(m_queue.obj(), 1, &m_display_image->m_presentableMemory);
         vkQueueRemoveMemReferences(m_queue.obj(), buf.memories().size(), &buf.memories()[0]);
 
-        if (m_display_image->m_width > m_width)
-            m_width = m_display_image->m_width;
-
-        if (m_display_image->m_height > m_height)
-            m_height = m_display_image->m_height;
-
-
         ++m_display_image;
-
     }
 
     m_display_image = m_images.begin();
@@ -556,67 +602,83 @@
 
 void  TestFrameworkVkPresent::CreateMyWindow()
 {
+    const xcb_setup_t *setup;
+    xcb_screen_iterator_t iter;
+    int scr;
     uint32_t value_mask, value_list[32];
 
-    m_window = xcb_generate_id(environment->m_connection);
+    m_connection = xcb_connect(NULL, &scr);
+
+    setup = xcb_get_setup(m_connection);
+    iter = xcb_setup_roots_iterator(setup);
+    while (scr-- > 0)
+        xcb_screen_next(&iter);
+
+    m_screen = iter.data;
+
+    for (std::list<VkTestImageRecord>::const_iterator it = m_images.begin();
+         it != m_images.end(); it++) {
+        if (m_width < it->m_width)
+            m_width = it->m_width;
+        if (m_height < it->m_height)
+            m_height = it->m_height;
+    }
+
+    m_window = xcb_generate_id(m_connection);
 
     value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
-    value_list[0] = environment->m_screen->black_pixel;
+    value_list[0] = m_screen->black_pixel;
     value_list[1] = XCB_EVENT_MASK_KEY_RELEASE |
                     XCB_EVENT_MASK_EXPOSURE |
                     XCB_EVENT_MASK_STRUCTURE_NOTIFY;
 
-    xcb_create_window(environment->m_connection,
+    xcb_create_window(m_connection,
             XCB_COPY_FROM_PARENT,
-            m_window, environment->m_screen->root,
+            m_window, m_screen->root,
             0, 0, m_width, m_height, 0,
             XCB_WINDOW_CLASS_INPUT_OUTPUT,
-            environment->m_screen->root_visual,
+            m_screen->root_visual,
             value_mask, value_list);
 
     /* Magic code that will send notification when window is destroyed */
-    xcb_intern_atom_cookie_t cookie = xcb_intern_atom(environment->m_connection, 1, 12,
+    xcb_intern_atom_cookie_t cookie = xcb_intern_atom(m_connection, 1, 12,
                                                       "WM_PROTOCOLS");
-    xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(environment->m_connection, cookie, 0);
+    xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(m_connection, cookie, 0);
 
-    xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(environment->m_connection, 0, 16, "WM_DELETE_WINDOW");
-    m_atom_wm_delete_window = xcb_intern_atom_reply(environment->m_connection, cookie2, 0);
+    xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW");
+    m_atom_wm_delete_window = xcb_intern_atom_reply(m_connection, cookie2, 0);
 
-    xcb_change_property(environment->m_connection, XCB_PROP_MODE_REPLACE,
+    xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE,
                         m_window, (*reply).atom, 4, 32, 1,
                         &(*m_atom_wm_delete_window).atom);
     free(reply);
 
-    xcb_map_window(environment->m_connection, m_window);
+    xcb_map_window(m_connection, m_window);
 }
 
 void TestFrameworkVkPresent::TearDown()
 {
-    std::list<VkTestImageRecord>::const_iterator iterator;
-    for (iterator = m_images.begin(); iterator != m_images.end(); ++iterator) {
-        vkDestroyObject(iterator->m_presentableImage);
-    }
-    xcb_destroy_window(environment->m_connection, m_window);
+    vkDestroySwapChainWSI(m_swap_chain);
+    xcb_destroy_window(m_connection, m_window);
+    xcb_disconnect(m_connection);
 }
 
 void VkTestFramework::Finish()
 {
     if (m_images.size() == 0) return;
 
-    environment = new vk_testing::Environment();
-    ::testing::AddGlobalTestEnvironment(environment);
-    environment->X11SetUp();
-
+    vk_testing::Environment env;
+    env.SetUp();
     {
-        TestFrameworkVkPresent vkPresent;
+        TestFrameworkVkPresent vkPresent(env.default_device());
 
         vkPresent.InitPresentFramework(m_images);
-        vkPresent.CreatePresentableImages();
         vkPresent.CreateMyWindow();
+        vkPresent.CreateSwapChain();
         vkPresent.Run();
         vkPresent.TearDown();
     }
-    environment->TearDown();
+    env.TearDown();
 }
 
 //
diff --git a/tests/vktestframework.h b/tests/vktestframework.h
index ba53923..02fd107 100644
--- a/tests/vktestframework.h
+++ b/tests/vktestframework.h
@@ -38,7 +38,6 @@
 #include <iostream>
 #include <fstream>
 #include <list>
-#include <vkWsiX11Ext.h>
 
 // Can be used by tests to record additional details / description of test
 #define TEST_DESCRIPTION(desc) RecordProperty("description", desc)
@@ -116,40 +115,6 @@
 
 };
 
-
-class TestFrameworkVkPresent
-{
-public:
-    TestFrameworkVkPresent();
-
-    void Run();
-    void InitPresentFramework(std::list<VkTestImageRecord> &imagesIn);
-    void CreateMyWindow();
-    void CreatePresentableImages();
-    void TearDown();
-
-protected:
-    vk_testing::Device                    &m_device;
-    vk_testing::Queue                     &m_queue;
-    vk_testing::CmdBuffer                  m_cmdbuf;
-
-private:
-    xcb_window_t                            m_window;
-    xcb_intern_atom_reply_t                *m_atom_wm_delete_window;
-    std::list<VkTestImageRecord>           m_images;
-
-    bool                                    m_quit;
-    bool                                    m_pause;
-
-    uint32_t                                m_width;
-    uint32_t                                m_height;
-
-    std::list<VkTestImageRecord>::iterator m_display_image;
-
-    void Display();
-    void HandleEvent(xcb_generic_event_t *event);
-};
-
 class TestEnvironment : public ::testing::Environment
 {
  public:
diff --git a/vk-generate.py b/vk-generate.py
index 39af406..550ebc1 100755
--- a/vk-generate.py
+++ b/vk-generate.py
@@ -133,6 +133,29 @@
             setup.append("uint32_t i;")
             setup.append("for (i = 0; i < *%s; i++)" % pcount)
             setup.append("    %s(%s[i], disp);" % (method, psets))
+        elif proto.name == "GetPhysicalDeviceInfo":
+            ptype = proto.params[-3].name
+            psize = proto.params[-2].name
+            pdata = proto.params[-1].name
+            cond = ("%s == VK_PHYSICAL_DEVICE_INFO_TYPE_DISPLAY_PROPERTIES_WSI && "
+                    "%s && %s" % (ptype, pdata, cond))
+            setup.append("VkDisplayPropertiesWSI *info = %s;" % pdata)
+            setup.append("uint32_t count = *%s / sizeof(*info), i;" % psize)
+            setup.append("for (i = 0; i < count; i++) {")
+            setup.append("    %s(info[i].display, disp);" % method)
+            setup.append("}")
+        elif proto.name == "GetSwapChainInfoWSI":
+            ptype = proto.params[-3].name
+            psize = proto.params[-2].name
+            pdata = proto.params[-1].name
+            cond = ("%s == VK_SWAP_CHAIN_INFO_TYPE_PERSISTENT_IMAGES_WSI && "
+                    "%s && %s" % (ptype, pdata, cond))
+            setup.append("VkSwapChainImageInfoWSI *info = %s;" % pdata)
+            setup.append("uint32_t count = *%s / sizeof(*info), i;" % psize)
+            setup.append("for (i = 0; i < count; i++) {")
+            setup.append("    %s(info[i].image, disp);" % method)
+            setup.append("    %s(info[i].memory, disp);" % method)
+            setup.append("}")
         else:
             obj_params = proto.object_out_params()
             for param in obj_params:
@@ -187,12 +210,8 @@
 
             func.append("}")
 
-            if 'WsiX11AssociateConnection' == proto.name:
-                funcs.append("#if defined(__linux__) || defined(XCB_NVIDIA)")
-
             funcs.append("\n".join(func))
 
-        funcs.append("#endif")
         return "\n\n".join(funcs)
 
     def generate_body(self):
@@ -218,15 +237,12 @@
     def _generate_init(self):
         stmts = []
         for proto in self.protos:
-            if 'WsiX11AssociateConnection' == proto.name:
-                stmts.append("#if defined(__linux__) || defined(XCB_NVIDIA)")
             if self.is_dispatchable_object_first_param(proto) or proto.name == "CreateInstance":
                 stmts.append("table->%s = (PFN_vk%s) gpa(gpu, \"vk%s\");" %
                         (proto.name, proto.name, proto.name))
             else:
                 stmts.append("table->%s = vk%s; /* non-dispatchable */" %
                              (proto.name, proto.name))
-        stmts.append("#endif")
 
         func = []
         func.append("static inline void %s_initialize_dispatch_table(VkLayerDispatchTable *table,"
@@ -244,13 +260,10 @@
     def _generate_lookup(self):
         lookups = []
         for proto in self.protos:
-            if 'WsiX11AssociateConnection' == proto.name:
-                lookups.append("#if defined(__linux__) || defined(XCB_NVIDIA)")
             if self.is_dispatchable_object_first_param(proto):
                 lookups.append("if (!strcmp(name, \"%s\"))" % (proto.name))
                 lookups.append("    return (void *) table->%s;"
                     % (proto.name))
-        lookups.append("#endif")
 
         func = []
         func.append("static inline void *%s_lookup_dispatch_table(const VkLayerDispatchTable *table,"
@@ -321,13 +334,10 @@
 
         lookups = []
         for proto in self.protos:
-            if 'WsiX11AssociateConnection' == proto.name:
-                lookups.append("#if defined(__linux__) || defined(XCB_NVIDIA)")
             lookups.append("if (!strcmp(%s, \"%s\"))" %
                     (gpa_pname, proto.name))
             lookups.append("    return (%s) %s%s;" %
                     (gpa_proto.ret, self.prefix, proto.name))
-        lookups.append("#endif")
 
         body = []
         body.append("%s %s" % (self.qual, gpa_decl))
@@ -366,12 +376,9 @@
                 lookups.append("/* no %s%s */" % (self.prefix, proto.name))
                 continue
 
-            if 'WsiX11AssociateConnection' == proto.name:
-                lookups.append("#if defined(__linux__) || defined(XCB_NVIDIA)")
             lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
             lookups.append("    return (%s) %s%s;" %
                     (self.gpa.ret, self.prefix, proto.name))
-        lookups.append("#endif")
 
         body = []
         body.append("static inline %s layer_intercept_proc(const char *name)" %
@@ -479,12 +486,9 @@
                 lookups.append("/* no %s%s */" % (self.prefix, proto.name))
                 continue
 
-            if 'WsiX11AssociateConnection' == proto.name:
-                lookups.append("#if defined(__linux__) || defined(XCB_NVIDIA)")
             lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
             lookups.append("    return (%s) %s%s;" %
                     (self.gpa.ret, self.prefix, proto.name))
-        lookups.append("#endif")
 
         special_lookups = []
         # these functions require special trampoline code beyond just the normal create object trampoline code
diff --git a/vk-layer-generate.py b/vk-layer-generate.py
index 9fcc68f..8bcc132 100755
--- a/vk-layer-generate.py
+++ b/vk-layer-generate.py
@@ -308,24 +308,16 @@
         prefix="vk"
         lookups = []
         for proto in intercepted:
-            if 'WsiX11' in proto.name:
-                lookups.append("#if defined(__linux__) || defined(XCB_NVIDIA)")
             lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
             lookups.append("    return (void*) %s%s;" %
                     (prefix, proto.name))
-            if 'WsiX11' in proto.name:
-                lookups.append("#endif")
 
         prefix="vk"
         lookups = []
         for proto in intercepted:
-            if 'WsiX11' in proto.name:
-                lookups.append("#if defined(__linux__) || defined(XCB_NVIDIA)")
             lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
             lookups.append("    return (void*) %s%s;" %
                     (prefix, proto.name))
-            if 'WsiX11' in proto.name:
-                lookups.append("#endif")
 
         # add customized layer_intercept_proc
         body = []
@@ -485,8 +477,6 @@
         if proto.ret != "void":
             ret_val = "VkResult result = "
             stmt = "    return result;\n"
-        if 'WsiX11AssociateConnection' == proto.name:
-            funcs.append("#if defined(__linux__) || defined(XCB_NVIDIA)")
         if proto.name == "EnumerateLayers":
             funcs.append('%s%s\n'
                      '{\n'
@@ -516,8 +506,6 @@
                      '    %snextTable.%s;\n'
                      '%s'
                      '}' % (qual, decl, ret_val, proto.c_call(), stmt))
-        if 'WsiX11QueuePresent' == proto.name:
-            funcs.append("#endif")
         return "\n\n".join(funcs)
 
     def generate_body(self):
@@ -669,7 +657,7 @@
         funcs = []
         sp_param_dict = {} # Store 'index' for struct param to print, or an name of binding "Count" param for array to print
         create_params = 0 # Num of params at end of function that are created and returned as output values
-        if 'WsiX11CreatePresentableImage' in proto.name or 'AllocDescriptorSets' in proto.name:
+        if 'AllocDescriptorSets' in proto.name:
             create_params = -2
         elif 'Create' in proto.name or 'Alloc' in proto.name or 'MapMemory' in proto.name:
             create_params = -1
@@ -701,7 +689,7 @@
                 prev_count_name = ''
             elif 'pDescriptorSets' == p.name and proto.params[-1].name == 'pCount':
                 sp_param_dict[pindex] = '*pCount'
-            elif 'Wsi' not in proto.name and vk_helper.is_type(p.ty.strip('*').replace('const ', ''), 'struct'):
+            elif vk_helper.is_type(p.ty.strip('*').replace('const ', ''), 'struct'):
                 sp_param_dict[pindex] = 'index'
             if p.name.endswith('Count'):
                 if '*' in p.ty:
@@ -753,8 +741,6 @@
                     log_func += '\n        %s' % (cis_print_func)
                     log_func += '\n        (*outputStream) << "   %s[" << i << "] (" << %s%s[i] << ")" << endl << tmp_str << endl;' % (proto.params[sp_index].name, '&', proto.params[sp_index].name)
                     log_func += '\n    }'
-        if 'WsiX11AssociateConnection' == proto.name:
-            funcs.append("#if defined(__linux__) || defined(XCB_NVIDIA)")
         if proto.name == "EnumerateLayers":
             c_call = proto.c_call().replace("(" + proto.params[0].name, "((VkPhysicalDevice)gpuw->nextObject", 1)
             funcs.append('%s%s\n'
@@ -813,8 +799,6 @@
                      '    %s%s%s\n'
                      '%s'
                      '}' % (qual, decl, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
-        if 'WsiX11QueuePresent' == proto.name:
-            funcs.append("#endif")
         return "\n\n".join(funcs)
 
     def generate_body(self):
@@ -1121,7 +1105,8 @@
         header_txt.append('        }')
         header_txt.append('        pTrav = pTrav->pNextObj;')
         header_txt.append('    }')
-        header_txt.append('    if (objType != VkObjectTypePresentableImageMemory) {')
+        header_txt.append('    if (objType != VkObjectTypeSwapChainImageWSI &&')
+        header_txt.append('        objType != VkObjectTypeSwapChainMemoryWSI) {')
         header_txt.append('        // If we do not find it print an error')
         header_txt.append('        char str[1024];')
         header_txt.append('        sprintf(str, "Unable to obtain status for non-existent object %p of %s type", pObj, string_VK_OBJECT_TYPE(objType));')
@@ -1158,7 +1143,7 @@
         destroy_line = ''
         funcs = []
         # Special cases for API funcs that don't use an object as first arg
-        if True in [no_use_proto in proto.name for no_use_proto in ['GlobalOption', 'CreateInstance', 'QueueSubmit', 'QueueAddMemReferences', 'QueueRemoveMemReferences', 'QueueWaitIdle', 'GetGlobalExtensionInfo', 'CreateDevice', 'GetGpuInfo', 'QueueSignalSemaphore', 'QueueWaitSemaphore', 'WsiX11QueuePresent']]:
+        if True in [no_use_proto in proto.name for no_use_proto in ['GlobalOption', 'CreateInstance', 'QueueSubmit', 'QueueAddMemReferences', 'QueueRemoveMemReferences', 'QueueWaitIdle', 'GetGlobalExtensionInfo', 'CreateDevice', 'GetGpuInfo', 'QueueSignalSemaphore', 'QueueWaitSemaphore']]:
             using_line = ''
         else:
             using_line = '    loader_platform_thread_lock_mutex(&objLock);\n'
@@ -1191,12 +1176,6 @@
             create_line += '        ll_insert_obj((void*)pDescriptorSets[i], VkObjectTypeDescriptorSet);\n'
             create_line += '        loader_platform_thread_unlock_mutex(&objLock);\n'
             create_line += '    }\n'
-        elif 'CreatePresentableImage' in proto.name:
-            create_line = '    loader_platform_thread_lock_mutex(&objLock);\n'
-            create_line += '    ll_insert_obj((void*)*%s, %s);\n' % (proto.params[-2].name, obj_type_mapping[proto.params[-2].ty.strip('*').replace('const ', '')])
-            create_line += '    ll_insert_obj((void*)*pMem, VkObjectTypePresentableImageMemory);\n'
-
-            create_line += '    loader_platform_thread_unlock_mutex(&objLock);\n'
         elif 'Create' in proto.name or 'Alloc' in proto.name:
             create_line = '    loader_platform_thread_lock_mutex(&objLock);\n'
             create_line += '    ll_insert_obj((void*)*%s, %s);\n' % (proto.params[-1].name, obj_type_mapping[proto.params[-1].ty.strip('*').replace('const ', '')])
@@ -1214,7 +1193,8 @@
                 using_line = ''
             if 'DestroyDevice' in proto.name:
                 destroy_line += '    // Report any remaining objects in LL\n    objNode *pTrav = pGlobalHead;\n    while (pTrav) {\n'
-                destroy_line += '        if (pTrav->obj.objType == VkObjectTypePresentableImageMemory) {\n'
+                destroy_line += '        if (pTrav->obj.objType == VkObjectTypeSwapChainImageWSI ||\n'
+                destroy_line += '            pTrav->obj.objType == VkObjectTypeSwapChainMemoryWSI) {\n'
                 destroy_line += '            objNode *pDel = pTrav;\n'
                 destroy_line += '            pTrav = pTrav->pNextGlobal;\n'
                 destroy_line += '            ll_destroy_obj((void*)(pDel->obj.pObj));\n'
@@ -1237,8 +1217,6 @@
         if proto.ret != "void":
             ret_val = "VkResult result = "
             stmt = "    return result;\n"
-        if 'WsiX11AssociateConnection' == proto.name:
-            funcs.append("#if defined(__linux__) || defined(XCB_NVIDIA)")
         if proto.name == "EnumerateLayers":
             funcs.append('%s%s\n'
                      '{\n'
@@ -1302,8 +1280,6 @@
                      '%s%s'
                      '%s'
                      '}' % (qual, decl, using_line, ret_val, proto.c_call(), create_line, destroy_line, stmt))
-        if 'WsiX11QueuePresent' == proto.name:
-            funcs.append("#endif")
         return "\n\n".join(funcs)
 
     def generate_body(self):
diff --git a/vulkan.py b/vulkan.py
index 72cb9cd..044a98c 100755
--- a/vulkan.py
+++ b/vulkan.py
@@ -923,40 +923,48 @@
     ],
 )
 
-wsi_x11 = Extension(
-    name="VK_WSI_X11",
-    headers=["vkWsiX11Ext.h"],
-    objects=[],
+wsi_lunarg = Extension(
+    name="VK_WSI_LunarG",
+    headers=["vk_wsi_lunarg.h"],
+    objects=[
+        "VkDisplayWSI",
+        "VkSwapChainWSI",
+    ],
     protos=[
-        Proto("VkResult", "WsiX11AssociateConnection",
-            [Param("VkPhysicalDevice", "gpu"),
-             Param("const VK_WSI_X11_CONNECTION_INFO*", "pConnectionInfo")]),
+        Proto("VkResult", "GetDisplayInfoWSI",
+            [Param("VkDisplayWSI", "display"),
+             Param("VkDisplayInfoTypeWSI", "infoType"),
+             Param("size_t*", "pDataSize"),
+             Param("void*", "pData")]),
 
-        Proto("VkResult", "WsiX11GetMSC",
+        Proto("VkResult", "CreateSwapChainWSI",
             [Param("VkDevice", "device"),
-             Param("xcb_window_t", "window"),
-             Param("xcb_randr_crtc_t", "crtc"),
-             Param("uint64_t*", "pMsc")]),
+             Param("const VkSwapChainCreateInfoWSI*", "pCreateInfo"),
+             Param("VkSwapChainWSI*", "pSwapChain")]),
 
-        Proto("VkResult", "WsiX11CreatePresentableImage",
-            [Param("VkDevice", "device"),
-             Param("const VK_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO*", "pCreateInfo"),
-             Param("VkImage*", "pImage"),
-             Param("VkDeviceMemory*", "pMem")]),
+        Proto("VkResult", "DestroySwapChainWSI",
+            [Param("VkSwapChainWSI", "swapChain")]),
 
-        Proto("VkResult", "WsiX11QueuePresent",
+        Proto("VkResult", "GetSwapChainInfoWSI",
+            [Param("VkSwapChainWSI", "swapChain"),
+             Param("VkSwapChainInfoTypeWSI", "infoType"),
+             Param("size_t*", "pDataSize"),
+             Param("void*", "pData")]),
+
+        Proto("VkResult", "QueuePresentWSI",
             [Param("VkQueue", "queue"),
-             Param("const VK_WSI_X11_PRESENT_INFO*", "pPresentInfo"),
-             Param("VkFence", "fence")]),
+             Param("const VkPresentInfoWSI*", "pPresentInfo")]),
     ],
 )
 
-extensions = [core, wsi_x11]
+extensions = [core, wsi_lunarg]
 
 object_root_list = [
     "VkInstance",
     "VkPhysicalDevice",
-    "VkBaseObject"
+    "VkBaseObject",
+    "VkDisplayWSI",
+    "VkSwapChainWSI",
 ]
 
 object_base_list = [