Layers initial prototype.

Includes  an auto generated layer (GenericLayer) that wraps  all api calls.
Includes a basic handwritten layer (basicLayer)  that wraps a few apis.
Adds xglGetProcAddr as a new api, which is used to chain layers together.
All layers and loader implement  a dispatch table.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3cbeb2c..2a0db8d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,3 +23,4 @@
 add_subdirectory(loader)
 add_subdirectory(icd)
 add_subdirectory(tests)
+add_subdirectory(layers)
diff --git a/include/xgl.h b/include/xgl.h
index 7fb33cc..7f3986c 100644
--- a/include/xgl.h
+++ b/include/xgl.h
@@ -1761,6 +1761,10 @@
 // ------------------------------------------------------------------------------------------------
 // API functions
 
+void * XGLAPI xglGetProcAddr(
+    XGL_PHYSICAL_GPU gpu,
+    const XGL_CHAR * pName);
+
 // GPU initialization
 
 XGL_RESULT XGLAPI xglInitAndEnumerateGpus(
diff --git a/include/xglLayer.h b/include/xglLayer.h
new file mode 100644
index 0000000..b762e57
--- /dev/null
+++ b/include/xglLayer.h
@@ -0,0 +1,274 @@
+/* Need to define dispatch table
+ * Core struct can then have ptr to dispatch table at the top
+ * Along with object ptrs for current and next OBJ
+ */
+#pragma once
+
+#include "xgl.h"
+#include "xglDbg.h"
+#include "xglWsiX11Ext.h"
+#if defined(__GNUC__) && __GNUC__ >= 4
+#  define XGL_LAYER_EXPORT __attribute__((visibility("default")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
+#  define XGL_LAYER_EXPORT __attribute__((visibility("default")))
+#else
+#  define XGL_LAYER_EXPORT
+#endif
+
+typedef void * (XGLAPI *GetProcAddrType)(XGL_PHYSICAL_GPU gpu, const XGL_CHAR * pName);
+typedef XGL_RESULT (XGLAPI *InitAndEnumerateGpusType)(const XGL_APPLICATION_INFO* pAppInfo, const XGL_ALLOC_CALLBACKS* pAllocCb, XGL_UINT maxGpus, XGL_UINT* pGpuCount, XGL_PHYSICAL_GPU* pGpus);
+typedef XGL_RESULT (XGLAPI *GetGpuInfoType)(XGL_PHYSICAL_GPU gpu, XGL_PHYSICAL_GPU_INFO_TYPE infoType, XGL_SIZE* pDataSize, XGL_VOID* pData);
+typedef XGL_RESULT (XGLAPI *CreateDeviceType)(XGL_PHYSICAL_GPU gpu, const XGL_DEVICE_CREATE_INFO* pCreateInfo, XGL_DEVICE* pDevice);
+typedef XGL_RESULT (XGLAPI *DestroyDeviceType)(XGL_DEVICE device);
+typedef XGL_RESULT (XGLAPI *GetExtensionSupportType)(XGL_PHYSICAL_GPU gpu, const XGL_CHAR* pExtName);
+typedef XGL_RESULT (XGLAPI *GetDeviceQueueType)(XGL_DEVICE device, XGL_QUEUE_TYPE queueType, XGL_UINT queueIndex, XGL_QUEUE* pQueue);
+typedef XGL_RESULT (XGLAPI *QueueSubmitType)(XGL_QUEUE queue, XGL_UINT cmdBufferCount, const XGL_CMD_BUFFER* pCmdBuffers, XGL_UINT memRefCount, const XGL_MEMORY_REF* pMemRefs, XGL_FENCE fence);
+typedef XGL_RESULT (XGLAPI *QueueSetGlobalMemReferencesType)(XGL_QUEUE queue, XGL_UINT memRefCount, const XGL_MEMORY_REF* pMemRefs);
+typedef XGL_RESULT (XGLAPI *QueueWaitIdleType)(XGL_QUEUE queue);
+typedef XGL_RESULT (XGLAPI *DeviceWaitIdleType)(XGL_DEVICE device);
+typedef XGL_RESULT (XGLAPI *GetMemoryHeapCountType)(XGL_DEVICE device, XGL_UINT* pCount);
+typedef XGL_RESULT (XGLAPI *GetMemoryHeapInfoType)(XGL_DEVICE device, XGL_UINT heapId, XGL_MEMORY_HEAP_INFO_TYPE infoType, XGL_SIZE* pDataSize, XGL_VOID* pData);
+typedef XGL_RESULT (XGLAPI *AllocMemoryType)(XGL_DEVICE device, const XGL_MEMORY_ALLOC_INFO* pAllocInfo, XGL_GPU_MEMORY* pMem);
+typedef XGL_RESULT (XGLAPI *FreeMemoryType)(XGL_GPU_MEMORY mem);
+typedef XGL_RESULT (XGLAPI *SetMemoryPriorityType)(XGL_GPU_MEMORY mem, XGL_MEMORY_PRIORITY priority);
+typedef XGL_RESULT (XGLAPI *MapMemoryType)(XGL_GPU_MEMORY mem, XGL_FLAGS flags, XGL_VOID** ppData);
+typedef XGL_RESULT (XGLAPI *UnmapMemoryType)(XGL_GPU_MEMORY mem);
+typedef XGL_RESULT (XGLAPI *PinSystemMemoryType)(XGL_DEVICE device, const XGL_VOID* pSysMem, XGL_SIZE memSize, XGL_GPU_MEMORY* pMem);
+typedef XGL_RESULT (XGLAPI *RemapVirtualMemoryPagesType)(XGL_DEVICE device, XGL_UINT rangeCount, const XGL_VIRTUAL_MEMORY_REMAP_RANGE* pRanges, XGL_UINT preWaitSemaphoreCount, const XGL_QUEUE_SEMAPHORE* pPreWaitSemaphores, XGL_UINT postSignalSemaphoreCount, const XGL_QUEUE_SEMAPHORE* pPostSignalSemaphores);
+typedef XGL_RESULT (XGLAPI *GetMultiGpuCompatibilityType)(XGL_PHYSICAL_GPU gpu0, XGL_PHYSICAL_GPU gpu1, XGL_GPU_COMPATIBILITY_INFO* pInfo);
+typedef XGL_RESULT (XGLAPI *OpenSharedMemoryType)(XGL_DEVICE device, const XGL_MEMORY_OPEN_INFO* pOpenInfo, XGL_GPU_MEMORY* pMem);
+typedef XGL_RESULT (XGLAPI *OpenSharedQueueSemaphoreType)(XGL_DEVICE device, const XGL_QUEUE_SEMAPHORE_OPEN_INFO* pOpenInfo, XGL_QUEUE_SEMAPHORE* pSemaphore);
+typedef XGL_RESULT (XGLAPI *OpenPeerMemoryType)(XGL_DEVICE device, const XGL_PEER_MEMORY_OPEN_INFO* pOpenInfo, XGL_GPU_MEMORY* pMem);
+typedef XGL_RESULT (XGLAPI *OpenPeerImageType)(XGL_DEVICE device, const XGL_PEER_IMAGE_OPEN_INFO* pOpenInfo, XGL_IMAGE* pImage, XGL_GPU_MEMORY* pMem);
+typedef XGL_RESULT (XGLAPI *DestroyObjectType)(XGL_OBJECT object);
+typedef XGL_RESULT (XGLAPI *GetObjectInfoType)(XGL_BASE_OBJECT object, XGL_OBJECT_INFO_TYPE infoType, XGL_SIZE* pDataSize, XGL_VOID* pData);
+typedef XGL_RESULT (XGLAPI *BindObjectMemoryType)(XGL_OBJECT object, XGL_GPU_MEMORY mem, XGL_GPU_SIZE offset);
+typedef XGL_RESULT (XGLAPI *CreateFenceType)(XGL_DEVICE device, const XGL_FENCE_CREATE_INFO* pCreateInfo, XGL_FENCE* pFence);
+typedef XGL_RESULT (XGLAPI *GetFenceStatusType)(XGL_FENCE fence);
+typedef XGL_RESULT (XGLAPI *WaitForFencesType)(XGL_DEVICE device, XGL_UINT fenceCount, const XGL_FENCE* pFences, XGL_BOOL waitAll, XGL_UINT64 timeout);
+typedef XGL_RESULT (XGLAPI *CreateQueueSemaphoreType)(XGL_DEVICE device, const XGL_QUEUE_SEMAPHORE_CREATE_INFO* pCreateInfo, XGL_QUEUE_SEMAPHORE* pSemaphore);
+typedef XGL_RESULT (XGLAPI *SignalQueueSemaphoreType)(XGL_QUEUE queue, XGL_QUEUE_SEMAPHORE semaphore);
+typedef XGL_RESULT (XGLAPI *WaitQueueSemaphoreType)(XGL_QUEUE queue, XGL_QUEUE_SEMAPHORE semaphore);
+typedef XGL_RESULT (XGLAPI *CreateEventType)(XGL_DEVICE device, const XGL_EVENT_CREATE_INFO* pCreateInfo, XGL_EVENT* pEvent);
+typedef XGL_RESULT (XGLAPI *GetEventStatusType)(XGL_EVENT event);
+typedef XGL_RESULT (XGLAPI *SetEventType)(XGL_EVENT event);
+typedef XGL_RESULT (XGLAPI *ResetEventType)(XGL_EVENT event);
+typedef XGL_RESULT (XGLAPI *CreateQueryPoolType)(XGL_DEVICE device, const XGL_QUERY_POOL_CREATE_INFO* pCreateInfo, XGL_QUERY_POOL* pQueryPool);
+typedef XGL_RESULT (XGLAPI *GetQueryPoolResultsType)(XGL_QUERY_POOL queryPool, XGL_UINT startQuery, XGL_UINT queryCount, XGL_SIZE* pDataSize, XGL_VOID* pData);
+typedef XGL_RESULT (XGLAPI *GetFormatInfoType)(XGL_DEVICE device, XGL_FORMAT format, XGL_FORMAT_INFO_TYPE infoType, XGL_SIZE* pDataSize, XGL_VOID* pData);
+typedef XGL_RESULT (XGLAPI *CreateImageType)(XGL_DEVICE device, const XGL_IMAGE_CREATE_INFO* pCreateInfo, XGL_IMAGE* pImage);
+typedef XGL_RESULT (XGLAPI *GetImageSubresourceInfoType)(XGL_IMAGE image, const XGL_IMAGE_SUBRESOURCE* pSubresource, XGL_SUBRESOURCE_INFO_TYPE infoType, XGL_SIZE* pDataSize, XGL_VOID* pData);
+typedef XGL_RESULT (XGLAPI *CreateImageViewType)(XGL_DEVICE device, const XGL_IMAGE_VIEW_CREATE_INFO* pCreateInfo, XGL_IMAGE_VIEW* pView);
+typedef XGL_RESULT (XGLAPI *CreateColorAttachmentViewType)(XGL_DEVICE device, const XGL_COLOR_ATTACHMENT_VIEW_CREATE_INFO* pCreateInfo, XGL_COLOR_ATTACHMENT_VIEW* pView);
+typedef XGL_RESULT (XGLAPI *CreateDepthStencilViewType)(XGL_DEVICE device, const XGL_DEPTH_STENCIL_VIEW_CREATE_INFO* pCreateInfo, XGL_DEPTH_STENCIL_VIEW* pView);
+typedef XGL_RESULT (XGLAPI *CreateShaderType)(XGL_DEVICE device, const XGL_SHADER_CREATE_INFO* pCreateInfo, XGL_SHADER* pShader);
+typedef XGL_RESULT (XGLAPI *CreateGraphicsPipelineType)(XGL_DEVICE device, const XGL_GRAPHICS_PIPELINE_CREATE_INFO* pCreateInfo, XGL_PIPELINE* pPipeline);
+typedef XGL_RESULT (XGLAPI *CreateComputePipelineType)(XGL_DEVICE device, const XGL_COMPUTE_PIPELINE_CREATE_INFO* pCreateInfo, XGL_PIPELINE* pPipeline);
+typedef XGL_RESULT (XGLAPI *StorePipelineType)(XGL_PIPELINE pipeline, XGL_SIZE* pDataSize, XGL_VOID* pData);
+typedef XGL_RESULT (XGLAPI *LoadPipelineType)(XGL_DEVICE device, XGL_SIZE dataSize, const XGL_VOID* pData, XGL_PIPELINE* pPipeline);
+typedef XGL_RESULT (XGLAPI *CreatePipelineDeltaType)(XGL_DEVICE device, XGL_PIPELINE p1, XGL_PIPELINE p2, XGL_PIPELINE_DELTA* delta);
+typedef XGL_RESULT (XGLAPI *CreateSamplerType)(XGL_DEVICE device, const XGL_SAMPLER_CREATE_INFO* pCreateInfo, XGL_SAMPLER* pSampler);
+typedef XGL_RESULT (XGLAPI *CreateDescriptorSetType)(XGL_DEVICE device, const XGL_DESCRIPTOR_SET_CREATE_INFO* pCreateInfo, XGL_DESCRIPTOR_SET* pDescriptorSet);
+typedef XGL_VOID (XGLAPI *BeginDescriptorSetUpdateType)(XGL_DESCRIPTOR_SET descriptorSet);
+typedef XGL_VOID (XGLAPI *EndDescriptorSetUpdateType)(XGL_DESCRIPTOR_SET descriptorSet);
+typedef XGL_VOID (XGLAPI *AttachSamplerDescriptorsType)(XGL_DESCRIPTOR_SET descriptorSet, XGL_UINT startSlot, XGL_UINT slotCount, const XGL_SAMPLER* pSamplers);
+typedef XGL_VOID (XGLAPI *AttachImageViewDescriptorsType)(XGL_DESCRIPTOR_SET descriptorSet, XGL_UINT startSlot, XGL_UINT slotCount, const XGL_IMAGE_VIEW_ATTACH_INFO* pImageViews);
+typedef XGL_VOID (XGLAPI *AttachMemoryViewDescriptorsType)(XGL_DESCRIPTOR_SET descriptorSet, XGL_UINT startSlot, XGL_UINT slotCount, const XGL_MEMORY_VIEW_ATTACH_INFO* pMemViews);
+typedef XGL_VOID (XGLAPI *AttachNestedDescriptorsType)(XGL_DESCRIPTOR_SET descriptorSet, XGL_UINT startSlot, XGL_UINT slotCount, const XGL_DESCRIPTOR_SET_ATTACH_INFO* pNestedDescriptorSets);
+typedef XGL_VOID (XGLAPI *ClearDescriptorSetSlotsType)(XGL_DESCRIPTOR_SET descriptorSet, XGL_UINT startSlot, XGL_UINT slotCount);
+typedef XGL_RESULT (XGLAPI *CreateViewportStateType)(XGL_DEVICE device, const XGL_VIEWPORT_STATE_CREATE_INFO* pCreateInfo, XGL_VIEWPORT_STATE_OBJECT* pState);
+typedef XGL_RESULT (XGLAPI *CreateRasterStateType)(XGL_DEVICE device, const XGL_RASTER_STATE_CREATE_INFO* pCreateInfo, XGL_RASTER_STATE_OBJECT* pState);
+typedef XGL_RESULT (XGLAPI *CreateMsaaStateType)(XGL_DEVICE device, const XGL_MSAA_STATE_CREATE_INFO* pCreateInfo, XGL_MSAA_STATE_OBJECT* pState);
+typedef XGL_RESULT (XGLAPI *CreateColorBlendStateType)(XGL_DEVICE device, const XGL_COLOR_BLEND_STATE_CREATE_INFO* pCreateInfo, XGL_COLOR_BLEND_STATE_OBJECT* pState);
+typedef XGL_RESULT (XGLAPI *CreateDepthStencilStateType)(XGL_DEVICE device, const XGL_DEPTH_STENCIL_STATE_CREATE_INFO* pCreateInfo, XGL_DEPTH_STENCIL_STATE_OBJECT* pState);
+typedef XGL_RESULT (XGLAPI *CreateCommandBufferType)(XGL_DEVICE device, const XGL_CMD_BUFFER_CREATE_INFO* pCreateInfo, XGL_CMD_BUFFER* pCmdBuffer);
+typedef XGL_RESULT (XGLAPI *BeginCommandBufferType)(XGL_CMD_BUFFER cmdBuffer, XGL_FLAGS flags);
+typedef XGL_RESULT (XGLAPI *EndCommandBufferType)(XGL_CMD_BUFFER cmdBuffer);
+typedef XGL_RESULT (XGLAPI *ResetCommandBufferType)(XGL_CMD_BUFFER cmdBuffer);
+typedef XGL_VOID (XGLAPI *CmdBindPipelineType)(XGL_CMD_BUFFER cmdBuffer, XGL_PIPELINE_BIND_POINT pipelineBindPoint, XGL_PIPELINE pipeline);
+typedef XGL_VOID (XGLAPI *CmdBindPipelineDeltaType)(XGL_CMD_BUFFER cmdBuffer, XGL_PIPELINE_BIND_POINT pipelineBindPoint, XGL_PIPELINE_DELTA delta);
+typedef XGL_VOID (XGLAPI *CmdBindStateObjectType)(XGL_CMD_BUFFER cmdBuffer, XGL_STATE_BIND_POINT stateBindPoint, XGL_STATE_OBJECT state);
+typedef XGL_VOID (XGLAPI *CmdBindDescriptorSetType)(XGL_CMD_BUFFER cmdBuffer, XGL_PIPELINE_BIND_POINT pipelineBindPoint, XGL_UINT index, XGL_DESCRIPTOR_SET descriptorSet, XGL_UINT slotOffset);
+typedef XGL_VOID (XGLAPI *CmdBindDynamicMemoryViewType)(XGL_CMD_BUFFER cmdBuffer, XGL_PIPELINE_BIND_POINT pipelineBindPoint, const XGL_MEMORY_VIEW_ATTACH_INFO* pMemView);
+typedef XGL_VOID (XGLAPI *CmdBindIndexDataType)(XGL_CMD_BUFFER cmdBuffer, XGL_GPU_MEMORY mem, XGL_GPU_SIZE offset, XGL_INDEX_TYPE indexType);
+typedef XGL_VOID (XGLAPI *CmdBindAttachmentsType)(XGL_CMD_BUFFER cmdBuffer, XGL_UINT colorAttachmentCount, const XGL_COLOR_ATTACHMENT_BIND_INFO* pColorAttachments, const XGL_DEPTH_STENCIL_BIND_INFO* pDepthStencilAttachment);
+typedef XGL_VOID (XGLAPI *CmdPrepareMemoryRegionsType)(XGL_CMD_BUFFER cmdBuffer, XGL_UINT transitionCount, const XGL_MEMORY_STATE_TRANSITION* pStateTransitions);
+typedef XGL_VOID (XGLAPI *CmdPrepareImagesType)(XGL_CMD_BUFFER cmdBuffer, XGL_UINT transitionCount, const XGL_IMAGE_STATE_TRANSITION* pStateTransitions);
+typedef XGL_VOID (XGLAPI *CmdDrawType)(XGL_CMD_BUFFER cmdBuffer, XGL_UINT firstVertex, XGL_UINT vertexCount, XGL_UINT firstInstance, XGL_UINT instanceCount);
+typedef XGL_VOID (XGLAPI *CmdDrawIndexedType)(XGL_CMD_BUFFER cmdBuffer, XGL_UINT firstIndex, XGL_UINT indexCount, XGL_INT vertexOffset, XGL_UINT firstInstance, XGL_UINT instanceCount);
+typedef XGL_VOID (XGLAPI *CmdDrawIndirectType)(XGL_CMD_BUFFER cmdBuffer, XGL_GPU_MEMORY mem, XGL_GPU_SIZE offset, XGL_UINT32 count, XGL_UINT32 stride);
+typedef XGL_VOID (XGLAPI *CmdDrawIndexedIndirectType)(XGL_CMD_BUFFER cmdBuffer, XGL_GPU_MEMORY mem, XGL_GPU_SIZE offset, XGL_UINT32 count, XGL_UINT32 stride);
+typedef XGL_VOID (XGLAPI *CmdDispatchType)(XGL_CMD_BUFFER cmdBuffer, XGL_UINT x, XGL_UINT y, XGL_UINT z);
+typedef XGL_VOID (XGLAPI *CmdDispatchIndirectType)(XGL_CMD_BUFFER cmdBuffer, XGL_GPU_MEMORY mem, XGL_GPU_SIZE offset);
+typedef XGL_VOID (XGLAPI *CmdCopyMemoryType)(XGL_CMD_BUFFER cmdBuffer, XGL_GPU_MEMORY srcMem, XGL_GPU_MEMORY destMem, XGL_UINT regionCount, const XGL_MEMORY_COPY* pRegions);
+typedef XGL_VOID (XGLAPI *CmdCopyImageType)(XGL_CMD_BUFFER cmdBuffer, XGL_IMAGE srcImage, XGL_IMAGE destImage, XGL_UINT regionCount, const XGL_IMAGE_COPY* pRegions);
+typedef XGL_VOID (XGLAPI *CmdCopyMemoryToImageType)(XGL_CMD_BUFFER cmdBuffer, XGL_GPU_MEMORY srcMem, XGL_IMAGE destImage, XGL_UINT regionCount, const XGL_MEMORY_IMAGE_COPY* pRegions);
+typedef XGL_VOID (XGLAPI *CmdCopyImageToMemoryType)(XGL_CMD_BUFFER cmdBuffer, XGL_IMAGE srcImage, XGL_GPU_MEMORY destMem, XGL_UINT regionCount, const XGL_MEMORY_IMAGE_COPY* pRegions);
+typedef XGL_VOID (XGLAPI *CmdCloneImageDataType)(XGL_CMD_BUFFER cmdBuffer, XGL_IMAGE srcImage, XGL_IMAGE_STATE srcImageState, XGL_IMAGE destImage, XGL_IMAGE_STATE destImageState);
+typedef XGL_VOID (XGLAPI *CmdUpdateMemoryType)(XGL_CMD_BUFFER cmdBuffer, XGL_GPU_MEMORY destMem, XGL_GPU_SIZE destOffset, XGL_GPU_SIZE dataSize, const XGL_UINT32* pData);
+typedef XGL_VOID (XGLAPI *CmdFillMemoryType)(XGL_CMD_BUFFER cmdBuffer, XGL_GPU_MEMORY destMem, XGL_GPU_SIZE destOffset, XGL_GPU_SIZE fillSize, XGL_UINT32 data);
+typedef XGL_VOID (XGLAPI *CmdClearColorImageType)(XGL_CMD_BUFFER cmdBuffer, XGL_IMAGE image, const XGL_FLOAT color[4], XGL_UINT rangeCount, const XGL_IMAGE_SUBRESOURCE_RANGE* pRanges);
+typedef XGL_VOID (XGLAPI *CmdClearColorImageRawType)(XGL_CMD_BUFFER cmdBuffer, XGL_IMAGE image, const XGL_UINT32 color[4], XGL_UINT rangeCount, const XGL_IMAGE_SUBRESOURCE_RANGE* pRanges);
+typedef XGL_VOID (XGLAPI *CmdClearDepthStencilType)(XGL_CMD_BUFFER cmdBuffer, XGL_IMAGE image, XGL_FLOAT depth, XGL_UINT32 stencil, XGL_UINT rangeCount, const XGL_IMAGE_SUBRESOURCE_RANGE* pRanges);
+typedef XGL_VOID (XGLAPI *CmdResolveImageType)(XGL_CMD_BUFFER cmdBuffer, XGL_IMAGE srcImage, XGL_IMAGE destImage, XGL_UINT rectCount, const XGL_IMAGE_RESOLVE* pRects);
+typedef XGL_VOID (XGLAPI *CmdSetEventType)(XGL_CMD_BUFFER cmdBuffer, XGL_EVENT event);
+typedef XGL_VOID (XGLAPI *CmdResetEventType)(XGL_CMD_BUFFER cmdBuffer, XGL_EVENT event);
+typedef XGL_VOID (XGLAPI *CmdMemoryAtomicType)(XGL_CMD_BUFFER cmdBuffer, XGL_GPU_MEMORY destMem, XGL_GPU_SIZE destOffset, XGL_UINT64 srcData, XGL_ATOMIC_OP atomicOp);
+typedef XGL_VOID (XGLAPI *CmdBeginQueryType)(XGL_CMD_BUFFER cmdBuffer, XGL_QUERY_POOL queryPool, XGL_UINT slot, XGL_FLAGS flags);
+typedef XGL_VOID (XGLAPI *CmdEndQueryType)(XGL_CMD_BUFFER cmdBuffer, XGL_QUERY_POOL queryPool, XGL_UINT slot);
+typedef XGL_VOID (XGLAPI *CmdResetQueryPoolType)(XGL_CMD_BUFFER cmdBuffer, XGL_QUERY_POOL queryPool, XGL_UINT startQuery, XGL_UINT queryCount);
+typedef XGL_VOID (XGLAPI *CmdWriteTimestampType)(XGL_CMD_BUFFER cmdBuffer, XGL_TIMESTAMP_TYPE timestampType, XGL_GPU_MEMORY destMem, XGL_GPU_SIZE destOffset);
+typedef XGL_VOID (XGLAPI *CmdInitAtomicCountersType)(XGL_CMD_BUFFER cmdBuffer, XGL_PIPELINE_BIND_POINT pipelineBindPoint, XGL_UINT startCounter, XGL_UINT counterCount, const XGL_UINT32* pData);
+typedef XGL_VOID (XGLAPI *CmdLoadAtomicCountersType)(XGL_CMD_BUFFER cmdBuffer, XGL_PIPELINE_BIND_POINT pipelineBindPoint, XGL_UINT startCounter, XGL_UINT counterCount, XGL_GPU_MEMORY srcMem, XGL_GPU_SIZE srcOffset);
+typedef XGL_VOID (XGLAPI *CmdSaveAtomicCountersType)(XGL_CMD_BUFFER cmdBuffer, XGL_PIPELINE_BIND_POINT pipelineBindPoint, XGL_UINT startCounter, XGL_UINT counterCount, XGL_GPU_MEMORY destMem, XGL_GPU_SIZE destOffset);
+typedef XGL_RESULT (XGLAPI *DbgSetValidationLevelType)(XGL_DEVICE device, XGL_VALIDATION_LEVEL validationLevel);
+typedef XGL_RESULT (XGLAPI *DbgRegisterMsgCallbackType)(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback, XGL_VOID* pUserData);
+typedef XGL_RESULT (XGLAPI *DbgUnregisterMsgCallbackType)(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback);
+typedef XGL_RESULT (XGLAPI *DbgSetMessageFilterType)(XGL_DEVICE device, XGL_INT msgCode, XGL_DBG_MSG_FILTER filter);
+typedef XGL_RESULT (XGLAPI *DbgSetObjectTagType)(XGL_BASE_OBJECT object, XGL_SIZE tagSize, const XGL_VOID* pTag);
+typedef XGL_RESULT (XGLAPI *DbgSetGlobalOptionType)(XGL_DBG_GLOBAL_OPTION dbgOption, XGL_SIZE dataSize, const XGL_VOID* pData);
+typedef XGL_RESULT (XGLAPI *DbgSetDeviceOptionType)(XGL_DEVICE device, XGL_DBG_DEVICE_OPTION dbgOption, XGL_SIZE dataSize, const XGL_VOID* pData);
+typedef XGL_VOID (XGLAPI *CmdDbgMarkerBeginType)(XGL_CMD_BUFFER cmdBuffer, const XGL_CHAR* pMarker);
+typedef XGL_VOID (XGLAPI *CmdDbgMarkerEndType)(XGL_CMD_BUFFER cmdBuffer);
+typedef XGL_RESULT (XGLAPI *WsiX11AssociateConnectionType)(XGL_PHYSICAL_GPU gpu, const XGL_WSI_X11_CONNECTION_INFO* pConnectionInfo);
+typedef XGL_RESULT (XGLAPI *WsiX11GetMSCType)(XGL_DEVICE device, xcb_randr_crtc_t crtc, XGL_UINT64* pMsc);
+typedef XGL_RESULT (XGLAPI *WsiX11CreatePresentableImageType)(XGL_DEVICE device, const XGL_WSI_X11_PRESENTABLE_IMAGE_CREATE_INFO* pCreateInfo, XGL_IMAGE* pImage, XGL_GPU_MEMORY* pMem);
+typedef XGL_RESULT (XGLAPI *WsiX11QueuePresentType)(XGL_QUEUE queue, const XGL_WSI_X11_PRESENT_INFO* pPresentInfo, XGL_FENCE fence);
+
+typedef struct _XGL_BASE_LAYER_OBJECT
+{
+    GetProcAddrType pGPA;
+    XGL_BASE_OBJECT nextObject;
+    XGL_BASE_OBJECT baseObject;
+} XGL_BASE_LAYER_OBJECT;
+
+typedef struct _XGL_LAYER_DISPATCH_TABLE
+{
+    GetProcAddrType GetProcAddr;
+    InitAndEnumerateGpusType InitAndEnumerateGpus;
+    GetGpuInfoType GetGpuInfo;
+    CreateDeviceType CreateDevice;
+    DestroyDeviceType DestroyDevice;
+    GetExtensionSupportType GetExtensionSupport;
+    GetDeviceQueueType GetDeviceQueue;
+    QueueSubmitType QueueSubmit;
+    QueueSetGlobalMemReferencesType QueueSetGlobalMemReferences;
+    QueueWaitIdleType QueueWaitIdle;
+    DeviceWaitIdleType DeviceWaitIdle;
+    GetMemoryHeapCountType GetMemoryHeapCount;
+    GetMemoryHeapInfoType GetMemoryHeapInfo;
+    AllocMemoryType AllocMemory;
+    FreeMemoryType FreeMemory;
+    SetMemoryPriorityType SetMemoryPriority;
+    MapMemoryType MapMemory;
+    UnmapMemoryType UnmapMemory;
+    PinSystemMemoryType PinSystemMemory;
+    RemapVirtualMemoryPagesType RemapVirtualMemoryPages;
+    GetMultiGpuCompatibilityType GetMultiGpuCompatibility;
+    OpenSharedMemoryType OpenSharedMemory;
+    OpenSharedQueueSemaphoreType OpenSharedQueueSemaphore;
+    OpenPeerMemoryType OpenPeerMemory;
+    OpenPeerImageType OpenPeerImage;
+    DestroyObjectType DestroyObject;
+    GetObjectInfoType GetObjectInfo;
+    BindObjectMemoryType BindObjectMemory;
+    CreateFenceType CreateFence;
+    GetFenceStatusType GetFenceStatus;
+    WaitForFencesType WaitForFences;
+    CreateQueueSemaphoreType CreateQueueSemaphore;
+    SignalQueueSemaphoreType SignalQueueSemaphore;
+    WaitQueueSemaphoreType WaitQueueSemaphore;
+    CreateEventType CreateEvent;
+    GetEventStatusType GetEventStatus;
+    SetEventType SetEvent;
+    ResetEventType ResetEvent;
+    CreateQueryPoolType CreateQueryPool;
+    GetQueryPoolResultsType GetQueryPoolResults;
+    GetFormatInfoType GetFormatInfo;
+    CreateImageType CreateImage;
+    GetImageSubresourceInfoType GetImageSubresourceInfo;
+    CreateImageViewType CreateImageView;
+    CreateColorAttachmentViewType CreateColorAttachmentView;
+    CreateDepthStencilViewType CreateDepthStencilView;
+    CreateShaderType CreateShader;
+    CreateGraphicsPipelineType CreateGraphicsPipeline;
+    CreateComputePipelineType CreateComputePipeline;
+    StorePipelineType StorePipeline;
+    LoadPipelineType LoadPipeline;
+    CreatePipelineDeltaType CreatePipelineDelta;
+    CreateSamplerType CreateSampler;
+    CreateDescriptorSetType CreateDescriptorSet;
+    BeginDescriptorSetUpdateType BeginDescriptorSetUpdate;
+    EndDescriptorSetUpdateType EndDescriptorSetUpdate;
+    AttachSamplerDescriptorsType AttachSamplerDescriptors;
+    AttachImageViewDescriptorsType AttachImageViewDescriptors;
+    AttachMemoryViewDescriptorsType AttachMemoryViewDescriptors;
+    AttachNestedDescriptorsType AttachNestedDescriptors;
+    ClearDescriptorSetSlotsType ClearDescriptorSetSlots;
+    CreateViewportStateType CreateViewportState;
+    CreateRasterStateType CreateRasterState;
+    CreateMsaaStateType CreateMsaaState;
+    CreateColorBlendStateType CreateColorBlendState;
+    CreateDepthStencilStateType CreateDepthStencilState;
+    CreateCommandBufferType CreateCommandBuffer;
+    BeginCommandBufferType BeginCommandBuffer;
+    EndCommandBufferType EndCommandBuffer;
+    ResetCommandBufferType ResetCommandBuffer;
+    CmdBindPipelineType CmdBindPipeline;
+    CmdBindPipelineDeltaType CmdBindPipelineDelta;
+    CmdBindStateObjectType CmdBindStateObject;
+    CmdBindDescriptorSetType CmdBindDescriptorSet;
+    CmdBindDynamicMemoryViewType CmdBindDynamicMemoryView;
+    CmdBindIndexDataType CmdBindIndexData;
+    CmdBindAttachmentsType CmdBindAttachments;
+    CmdPrepareMemoryRegionsType CmdPrepareMemoryRegions;
+    CmdPrepareImagesType CmdPrepareImages;
+    CmdDrawType CmdDraw;
+    CmdDrawIndexedType CmdDrawIndexed;
+    CmdDrawIndirectType CmdDrawIndirect;
+    CmdDrawIndexedIndirectType CmdDrawIndexedIndirect;
+    CmdDispatchType CmdDispatch;
+    CmdDispatchIndirectType CmdDispatchIndirect;
+    CmdCopyMemoryType CmdCopyMemory;
+    CmdCopyImageType CmdCopyImage;
+    CmdCopyMemoryToImageType CmdCopyMemoryToImage;
+    CmdCopyImageToMemoryType CmdCopyImageToMemory;
+    CmdCloneImageDataType CmdCloneImageData;
+    CmdUpdateMemoryType CmdUpdateMemory;
+    CmdFillMemoryType CmdFillMemory;
+    CmdClearColorImageType CmdClearColorImage;
+    CmdClearColorImageRawType CmdClearColorImageRaw;
+    CmdClearDepthStencilType CmdClearDepthStencil;
+    CmdResolveImageType CmdResolveImage;
+    CmdSetEventType CmdSetEvent;
+    CmdResetEventType CmdResetEvent;
+    CmdMemoryAtomicType CmdMemoryAtomic;
+    CmdBeginQueryType CmdBeginQuery;
+    CmdEndQueryType CmdEndQuery;
+    CmdResetQueryPoolType CmdResetQueryPool;
+    CmdWriteTimestampType CmdWriteTimestamp;
+    CmdInitAtomicCountersType CmdInitAtomicCounters;
+    CmdLoadAtomicCountersType CmdLoadAtomicCounters;
+    CmdSaveAtomicCountersType CmdSaveAtomicCounters;
+    DbgSetValidationLevelType DbgSetValidationLevel;
+    DbgRegisterMsgCallbackType DbgRegisterMsgCallback;
+    DbgUnregisterMsgCallbackType DbgUnregisterMsgCallback;
+    DbgSetMessageFilterType DbgSetMessageFilter;
+    DbgSetObjectTagType DbgSetObjectTag;
+    DbgSetGlobalOptionType DbgSetGlobalOption;
+    DbgSetDeviceOptionType DbgSetDeviceOption;
+    CmdDbgMarkerBeginType CmdDbgMarkerBegin;
+    CmdDbgMarkerEndType CmdDbgMarkerEnd;
+    WsiX11AssociateConnectionType WsiX11AssociateConnection;
+    WsiX11GetMSCType WsiX11GetMSC;
+    WsiX11CreatePresentableImageType WsiX11CreatePresentableImage;
+    WsiX11QueuePresentType WsiX11QueuePresent;
+} XGL_LAYER_DISPATCH_TABLE;
+
+// ------------------------------------------------------------------------------------------------
+// API functions
+XGL_RESULT xglEnumerateLayers(
+    XGL_PHYSICAL_GPU gpu,
+    XGL_SIZE maxLayerCount,
+    XGL_CHAR* const* pOutLayers,
+    XGL_SIZE* pOutLayerCount);
diff --git a/layers/CMakeLists.txt b/layers/CMakeLists.txt
new file mode 100644
index 0000000..ebbfc42
--- /dev/null
+++ b/layers/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required (VERSION 2.8.11)
+
+add_custom_command(OUTPUT generic_layer.c
+	COMMAND ${PROJECT_SOURCE_DIR}/xgl-generate.py generic-layer > generic_layer.c
+	           DEPENDS ${PROJECT_SOURCE_DIR}/xgl-generate.py
+	                   ${PROJECT_SOURCE_DIR}/xgl.py)
+
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I ../include")
+
+add_library (XGLLayerBasic SHARED basic_plugin.c)
+add_library (XGLLayerGeneric SHARED generic_layer.c)
+#add_library (XGLLayerObjectTrack SHARED object_track.c)
+
diff --git a/layers/basic_plugin.c b/layers/basic_plugin.c
new file mode 100644
index 0000000..32ada03
--- /dev/null
+++ b/layers/basic_plugin.c
@@ -0,0 +1,434 @@
+#include <stdio.h>
+#include <dlfcn.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pthread.h>
+#include "xglLayer.h"
+
+static XGL_LAYER_DISPATCH_TABLE myTable;
+static XGL_BASE_LAYER_OBJECT *pCurObj;
+static pthread_once_t tabOnce = PTHREAD_ONCE_INIT;
+
+static void initLayerTable()
+{
+    GetProcAddrType fpGPA;
+
+    //memset(&myTable, 0 , sizeof(myTable));
+
+    //todo init the entire table to next entrypoint
+    fpGPA = pCurObj->pGPA;
+    assert(fpGPA);
+    // Layer
+    myTable.GetProcAddr = fpGPA;
+    myTable.InitAndEnumerateGpus = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglInitAndEnumerateGpus");
+    myTable.GetGpuInfo = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetGpuInfo");
+    myTable.CreateDevice = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateDevice");
+    myTable.DestroyDevice = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglDestroyDevice");
+    myTable.GetExtensionSupport = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetExtensionSupport");
+    myTable.GetDeviceQueue = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetDeviceQueue");
+    myTable.QueueSubmit = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglQueueSubmit");
+    myTable.QueueSetGlobalMemReferences = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglQueueSetGlobalMemReferences");
+    myTable.QueueWaitIdle = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglQueueWaitIdle");
+    myTable.DeviceWaitIdle = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglDeviceWaitIdle");
+    myTable.GetMemoryHeapCount = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetMemoryHeapCount");
+    myTable.GetMemoryHeapInfo = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetMemoryHeapInfo");
+    myTable.AllocMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglAllocMemory");
+    myTable.FreeMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglFreeMemory");
+    myTable.SetMemoryPriority = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglSetMemoryPriority");
+    myTable.MapMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglMapMemory");
+    myTable.UnmapMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglUnmapMemory");
+    myTable.PinSystemMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglPinSystemMemory");
+    myTable.RemapVirtualMemoryPages = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglRemapVirtualMemoryPages");
+    myTable.GetMultiGpuCompatibility = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetMultiGpuCompatibility");
+    myTable.OpenSharedMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglOpenSharedMemory");
+    myTable.OpenSharedQueueSemaphore = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglOpenSharedQueueSemaphore");
+    myTable.OpenPeerMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglOpenPeerMemory");
+    myTable.OpenPeerImage = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglOpenPeerImage");
+    myTable.DestroyObject = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglDestroyObject");
+    myTable.GetObjectInfo = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetObjectInfo");
+    myTable.BindObjectMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglBindObjectMemory");
+    myTable.CreateFence = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateFence");
+    myTable.GetFenceStatus = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetFenceStatus");
+    myTable.WaitForFences = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglWaitForFences");
+    myTable.CreateQueueSemaphore = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateQueueSemaphore");
+    myTable.SignalQueueSemaphore = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglSignalQueueSemaphore");
+    myTable.WaitQueueSemaphore = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglWaitQueueSemaphore");
+    myTable.CreateEvent = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateEvent");
+    myTable.GetEventStatus = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetEventStatus");
+    myTable.SetEvent = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglSetEvent");
+    myTable.ResetEvent = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglResetEvent");
+    myTable.CreateQueryPool = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateQueryPool");
+    myTable.GetQueryPoolResults = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetQueryPoolResults");
+    myTable.GetFormatInfo = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetFormatInfo");
+    myTable.CreateImage = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateImage");
+    myTable.GetImageSubresourceInfo = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglGetImageSubresourceInfo");
+    myTable.CreateImageView = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateImageView");
+    myTable.CreateColorAttachmentView = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateColorAttachmentView");
+    myTable.CreateDepthStencilView = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateDepthStencilView");
+    myTable.CreateShader = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateShader");
+    myTable.CreateGraphicsPipeline = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateGraphicsPipeline");
+    myTable.CreateComputePipeline = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateComputePipeline");
+    myTable.StorePipeline = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglStorePipeline");
+    myTable.LoadPipeline = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglLoadPipeline");
+    myTable.CreatePipelineDelta = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreatePipelineDelta");
+    myTable.CreateSampler = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateSampler");
+    myTable.CreateDescriptorSet = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateDescriptorSet");
+    myTable.BeginDescriptorSetUpdate = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglBeginDescriptorSetUpdate");
+    myTable.EndDescriptorSetUpdate = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglEndDescriptorSetUpdate");
+    myTable.AttachSamplerDescriptors = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglAttachSamplerDescriptors");
+    myTable.AttachImageViewDescriptors = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglAttachImageViewDescriptors");
+    myTable.AttachMemoryViewDescriptors = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglAttachMemoryViewDescriptors");
+    myTable.AttachNestedDescriptors = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglAttachNestedDescriptors");
+    myTable.ClearDescriptorSetSlots = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglClearDescriptorSetSlots");
+    myTable.CreateViewportState = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateViewportState");
+    myTable.CreateRasterState = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateRasterState");
+    myTable.CreateMsaaState = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateMsaaState");
+    myTable.CreateColorBlendState = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateColorBlendState");
+    myTable.CreateDepthStencilState = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateDepthStencilState");
+    myTable.CreateCommandBuffer = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCreateCommandBuffer");
+    myTable.BeginCommandBuffer = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglBeginCommandBuffer");
+    myTable.EndCommandBuffer = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglEndCommandBuffer");
+    myTable.ResetCommandBuffer = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglResetCommandBuffer");
+    myTable.CmdBindPipeline = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdBindPipeline");
+    myTable.CmdBindPipelineDelta = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdBindPipelineDelta");
+    myTable.CmdBindStateObject = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdBindStateObject");
+    myTable.CmdBindDescriptorSet = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdBindDescriptorSet");
+    myTable.CmdBindDynamicMemoryView = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdBindDynamicMemoryView");
+    myTable.CmdBindIndexData = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdBindIndexData");
+    myTable.CmdBindAttachments = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdBindAttachments");
+    myTable.CmdPrepareMemoryRegions = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdPrepareMemoryRegions");
+    myTable.CmdPrepareImages = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdPrepareImages");
+    myTable.CmdDraw = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdDraw");
+    myTable.CmdDrawIndexed = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdDrawIndexed");
+    myTable.CmdDrawIndirect = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdDrawIndirect");
+    myTable.CmdDrawIndexedIndirect = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdDrawIndexedIndirect");
+    myTable.CmdDispatch = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdDispatch");
+    myTable.CmdDispatchIndirect = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdDispatchIndirect");
+    myTable.CmdCopyMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdCopyMemory");
+    myTable.CmdCopyImage = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdCopyImage");
+    myTable.CmdCopyMemoryToImage = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdCopyMemoryToImage");
+    myTable.CmdCopyImageToMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdCopyImageToMemory");
+    myTable.CmdCloneImageData = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdCloneImageData");
+    myTable.CmdUpdateMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdUpdateMemory");
+    myTable.CmdFillMemory = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdFillMemory");
+    myTable.CmdClearColorImage = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdClearColorImage");
+    myTable.CmdClearColorImageRaw = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdClearColorImageRaw");
+    myTable.CmdClearDepthStencil = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdClearDepthStencil");
+    myTable.CmdResolveImage = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdResolveImage");
+    myTable.CmdSetEvent = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdSetEvent");
+    myTable.CmdResetEvent = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdResetEvent");
+    myTable.CmdMemoryAtomic = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdMemoryAtomic");
+    myTable.CmdBeginQuery = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdBeginQuery");
+    myTable.CmdEndQuery = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdEndQuery");
+    myTable.CmdResetQueryPool = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdResetQueryPool");
+    myTable.CmdWriteTimestamp = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdWriteTimestamp");
+    myTable.CmdInitAtomicCounters = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdInitAtomicCounters");
+    myTable.CmdLoadAtomicCounters = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdLoadAtomicCounters");
+    myTable.CmdSaveAtomicCounters = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdSaveAtomicCounters");
+    myTable.DbgSetValidationLevel = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglDbgSetValidationLevel");
+    myTable.DbgRegisterMsgCallback = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglDbgRegisterMsgCallback");
+    myTable.DbgUnregisterMsgCallback = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglDbgUnregisterMsgCallback");
+    myTable.DbgSetMessageFilter = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglDbgSetMessageFilter");
+    myTable.DbgSetObjectTag = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglDbgSetObjectTag");
+    myTable.DbgSetGlobalOption = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglDbgSetGlobalOption");
+    myTable.DbgSetDeviceOption = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglDbgSetDeviceOption");
+    myTable.CmdDbgMarkerBegin = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdDbgMarkerBegin");
+    myTable.CmdDbgMarkerEnd = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglCmdDbgMarkerEnd");
+    myTable.WsiX11AssociateConnection = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglWsiX11AssociateConnection");
+    myTable.WsiX11GetMSC = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglWsiX11GetMSC");
+    myTable.WsiX11CreatePresentableImage = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglWsiX11CreatePresentableImage");
+    myTable.WsiX11QueuePresent = fpGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (const XGL_CHAR *) "xglWsiX11QueuePresent");
+#if 0
+    fpNextCD = fpNextGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (XGL_CHAR *) "xglCreateDevice");
+    myTable.CreateDevice = fpNextCD;
+    fpNextGGI = fpNextGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (XGL_CHAR *) "xglGetGpuInfo");
+    myTable.GetGpuInfo = fpNextGGI;
+    fpNextGFI = fpNextGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (XGL_CHAR *) "xglGetFormatInfo");
+    myTable.GetFormatInfo = fpNextGFI;
+#endif
+    return;
+}
+
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglGetGpuInfo(XGL_PHYSICAL_GPU gpu, XGL_PHYSICAL_GPU_INFO_TYPE infoType, XGL_SIZE* pDataSize, XGL_VOID* pData)
+{
+    XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;
+    printf("At start of wrapped xglCreateDevice() call w/ gpu: %p\n", (void*)gpu);
+    pCurObj = gpuw;
+    pthread_once(&tabOnce, initLayerTable);
+    XGL_RESULT result = myTable.GetGpuInfo((XGL_PHYSICAL_GPU)gpuw->nextObject, infoType, pDataSize, pData);
+    printf("Completed wrapped xglCreateDevice() call w/ gpu: %p\n", (void*)gpu);
+    return result;
+}
+
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglCreateDevice(XGL_PHYSICAL_GPU gpu, const XGL_DEVICE_CREATE_INFO* pCreateInfo, XGL_DEVICE* pDevice)
+{
+    XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;
+    printf("At start of wrapped xglCreateDevice() call w/ gpu: %p\n", (void*)gpu);
+    pCurObj = gpuw;
+    pthread_once(&tabOnce, initLayerTable); 
+    XGL_RESULT result = myTable.CreateDevice((XGL_PHYSICAL_GPU)gpuw->nextObject, pCreateInfo, pDevice);
+    printf("Completed wrapped xglCreateDevice() call w/ pDevice: %p\n", (void*)pDevice);
+    return result;
+}
+XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglGetFormatInfo(XGL_DEVICE device, XGL_FORMAT format, XGL_FORMAT_INFO_TYPE infoType, XGL_SIZE* pDataSize, XGL_VOID* pData)
+{
+    printf("At start of wrapped xglGetFormatInfo() call w/ device: %p\n", (void*)device);
+    XGL_RESULT result = myTable.GetFormatInfo(device, format, infoType, pDataSize, pData);
+    printf("Completed wrapped xglGetFormatInfo() call w/ device: %p\n", (void*)device);
+       return result;
+}
+
+XGL_LAYER_EXPORT void * XGLAPI xglGetProcAddr(XGL_PHYSICAL_GPU gpu, const XGL_CHAR* pName) {
+    XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;
+    if (gpu == NULL)
+        return NULL;
+    pCurObj = gpuw;
+    pthread_once(&tabOnce, initLayerTable);
+    if (!strncmp("xglGetProcAddr", (const char *) pName, sizeof("xglGetProcAddr")))
+        return xglGetProcAddr;
+    else if (!strncmp("xglInitAndEnumerateGpus", (const char *) pName, sizeof("xglInitAndEnumerateGpus")))
+        return myTable.InitAndEnumerateGpus;
+    if (!strncmp("xglGetGpuInfo", (const char *) pName, sizeof ("xglGetGpuInfo")))
+        return xglGetGpuInfo;
+    else if (!strncmp("xglCreateDevice", (const char *) pName, sizeof ("xglCreateDevice")))
+        return xglCreateDevice;
+    else if (!strncmp("xglDestroyDevice", (const char *) pName, sizeof ("xglDestroyDevice")))
+        return myTable.DestroyDevice;
+    else if (!strncmp("xglGetExtensionSupport", (const char *) pName, sizeof ("xglGetExtensionSupport")))
+        return myTable.GetExtensionSupport;
+    else if (!strncmp("xglGetDeviceQueue", (const char *) pName, sizeof ("xglGetDeviceQueue")))
+        return myTable.GetDeviceQueue;
+    else if (!strncmp("xglQueueSubmit", (const char *) pName, sizeof ("xglQueueSubmit")))
+        return myTable.QueueSubmit;
+    else if (!strncmp("xglQueueSetGlobalMemReferences", (const char *) pName, sizeof ("xglQueueSetGlobalMemReferences")))
+        return myTable.QueueSetGlobalMemReferences;
+    else if (!strncmp("xglQueueWaitIdle", (const char *) pName, sizeof ("xglQueueWaitIdle")))
+        return myTable.QueueWaitIdle;
+    else if (!strncmp("xglDeviceWaitIdle", (const char *) pName, sizeof ("xglDeviceWaitIdle")))
+        return myTable.DeviceWaitIdle;
+    else if (!strncmp("xglGetMemoryHeapCount", (const char *) pName, sizeof ("xglGetMemoryHeapCount")))
+        return myTable.GetMemoryHeapCount;
+    else if (!strncmp("xglGetMemoryHeapInfo", (const char *) pName, sizeof ("xglGetMemoryHeapInfo")))
+        return myTable.GetMemoryHeapInfo;
+    else if (!strncmp("xglAllocMemory", (const char *) pName, sizeof ("xglAllocMemory")))
+        return myTable.AllocMemory;
+    else if (!strncmp("xglFreeMemory", (const char *) pName, sizeof ("xglFreeMemory")))
+        return myTable.FreeMemory;
+    else if (!strncmp("xglSetMemoryPriority", (const char *) pName, sizeof ("xglSetMemoryPriority")))
+        return myTable.SetMemoryPriority;
+    else if (!strncmp("xglMapMemory", (const char *) pName, sizeof ("xglMapMemory")))
+        return myTable.MapMemory;
+    else if (!strncmp("xglUnmapMemory", (const char *) pName, sizeof ("xglUnmapMemory")))
+        return myTable.UnmapMemory;
+    else if (!strncmp("xglPinSystemMemory", (const char *) pName, sizeof ("xglPinSystemMemory")))
+        return myTable.PinSystemMemory;
+    else if (!strncmp("xglRemapVirtualMemoryPages", (const char *) pName, sizeof ("xglRemapVirtualMemoryPages")))
+        return myTable.RemapVirtualMemoryPages;
+    else if (!strncmp("xglGetMultiGpuCompatibility", (const char *) pName, sizeof ("xglGetMultiGpuCompatibility")))
+        return myTable.GetMultiGpuCompatibility;
+    else if (!strncmp("xglOpenSharedMemory", (const char *) pName, sizeof ("xglOpenSharedMemory")))
+        return myTable.OpenSharedMemory;
+    else if (!strncmp("xglOpenSharedQueueSemaphore", (const char *) pName, sizeof ("xglOpenSharedQueueSemaphore")))
+        return myTable.OpenSharedQueueSemaphore;
+    else if (!strncmp("xglOpenPeerMemory", (const char *) pName, sizeof ("xglOpenPeerMemory")))
+        return myTable.OpenPeerMemory;
+    else if (!strncmp("xglOpenPeerImage", (const char *) pName, sizeof ("xglOpenPeerImage")))
+        return myTable.OpenPeerImage;
+    else if (!strncmp("xglDestroyObject", (const char *) pName, sizeof ("xglDestroyObject")))
+        return myTable.DestroyObject;
+    else if (!strncmp("xglGetObjectInfo", (const char *) pName, sizeof ("xglGetObjectInfo")))
+        return myTable.GetObjectInfo;
+    else if (!strncmp("xglBindObjectMemory", (const char *) pName, sizeof ("xglBindObjectMemory")))
+        return myTable.BindObjectMemory;
+    else if (!strncmp("xglCreateFence", (const char *) pName, sizeof ("xgllCreateFence")))
+        return myTable.CreateFence;
+    else if (!strncmp("xglGetFenceStatus", (const char *) pName, sizeof ("xglGetFenceStatus")))
+        return myTable.GetFenceStatus;
+    else if (!strncmp("xglWaitForFences", (const char *) pName, sizeof ("xglWaitForFences")))
+        return myTable.WaitForFences;
+    else if (!strncmp("xglCreateQueueSemaphore", (const char *) pName, sizeof ("xgllCreateQueueSemaphore")))
+        return myTable.CreateQueueSemaphore;
+    else if (!strncmp("xglSignalQueueSemaphore", (const char *) pName, sizeof ("xglSignalQueueSemaphore")))
+        return myTable.SignalQueueSemaphore;
+    else if (!strncmp("xglWaitQueueSemaphore", (const char *) pName, sizeof ("xglWaitQueueSemaphore")))
+        return myTable.WaitQueueSemaphore;
+    else if (!strncmp("xglCreateEvent", (const char *) pName, sizeof ("xgllCreateEvent")))
+        return myTable.CreateEvent;
+    else if (!strncmp("xglGetEventStatus", (const char *) pName, sizeof ("xglGetEventStatus")))
+        return myTable.GetEventStatus;
+    else if (!strncmp("xglSetEvent", (const char *) pName, sizeof ("xglSetEvent")))
+        return myTable.SetEvent;
+    else if (!strncmp("xglResetEvent", (const char *) pName, sizeof ("xgllResetEvent")))
+        return myTable.ResetEvent;
+    else if (!strncmp("xglCreateQueryPool", (const char *) pName, sizeof ("xglCreateQueryPool")))
+        return myTable.CreateQueryPool;
+    else if (!strncmp("xglGetQueryPoolResults", (const char *) pName, sizeof ("xglGetQueryPoolResults")))
+        return myTable.GetQueryPoolResults;
+    else if (!strncmp("xglGetFormatInfo", (const char *) pName, sizeof ("xgllGetFormatInfo")))
+        return xglGetFormatInfo;
+    else if (!strncmp("xglCreateImage", (const char *) pName, sizeof ("xglCreateImage")))
+        return myTable.CreateImage;
+    else if (!strncmp("xglGetImageSubresourceInfo", (const char *) pName, sizeof ("xglGetImageSubresourceInfo")))
+        return myTable.GetImageSubresourceInfo;
+    else if (!strncmp("xglCreateImageView", (const char *) pName, sizeof ("xglCreateImageView")))
+        return myTable.CreateImageView;
+    else if (!strncmp("xglCreateColorAttachmentView", (const char *) pName, sizeof ("xglCreateColorAttachmentView")))
+        return myTable.CreateColorAttachmentView;
+    else if (!strncmp("xglCreateDepthStencilView", (const char *) pName, sizeof ("xglCreateDepthStencilView")))
+        return myTable.CreateDepthStencilView;
+    else if (!strncmp("xglCreateShader", (const char *) pName, sizeof ("xglCreateShader")))
+        return myTable.CreateShader;
+    else if (!strncmp("xglCreateGraphicsPipeline", (const char *) pName, sizeof ("xglCreateGraphicsPipeline")))
+        return myTable.CreateGraphicsPipeline;
+    else if (!strncmp("xglCreateComputePipeline", (const char *) pName, sizeof ("xglCreateComputePipeline")))
+        return myTable.CreateComputePipeline;
+    else if (!strncmp("xglStorePipeline", (const char *) pName, sizeof ("xglStorePipeline")))
+        return myTable.StorePipeline;
+    else if (!strncmp("xglLoadPipeline", (const char *) pName, sizeof ("xglLoadPipeline")))
+        return myTable.LoadPipeline;
+    else if (!strncmp("xglCreatePipelineDelta", (const char *) pName, sizeof ("xglCreatePipelineDelta")))
+        return myTable.CreatePipelineDelta;
+    else if (!strncmp("xglCreateSampler", (const char *) pName, sizeof ("xglCreateSampler")))
+        return myTable.CreateSampler;
+    else if (!strncmp("xglCreateDescriptorSet", (const char *) pName, sizeof ("xglCreateDescriptorSet")))
+        return myTable.CreateDescriptorSet;
+    else if (!strncmp("xglBeginDescriptorSetUpdate", (const char *) pName, sizeof ("xglBeginDescriptorSetUpdate")))
+        return myTable.BeginDescriptorSetUpdate;
+    else if (!strncmp("xglEndDescriptorSetUpdate", (const char *) pName, sizeof ("xglEndDescriptorSetUpdate")))
+        return myTable.EndDescriptorSetUpdate;
+    else if (!strncmp("xglAttachSamplerDescriptors", (const char *) pName, sizeof ("xglAttachSamplerDescriptors")))
+        return myTable.AttachSamplerDescriptors;
+    else if (!strncmp("xglAttachImageViewDescriptors", (const char *) pName, sizeof ("xglAttachImageViewDescriptors")))
+        return myTable.AttachImageViewDescriptors;
+    else if (!strncmp("xglAttachMemoryViewDescriptors", (const char *) pName, sizeof ("xglAttachMemoryViewDescriptors")))
+        return myTable.AttachMemoryViewDescriptors;
+    else if (!strncmp("xglAttachNestedDescriptors", (const char *) pName, sizeof ("xglAttachNestedDescriptors")))
+        return myTable.AttachNestedDescriptors;
+    else if (!strncmp("xglClearDescriptorSetSlots", (const char *) pName, sizeof ("xglClearDescriptorSetSlots")))
+        return myTable.ClearDescriptorSetSlots;
+    else if (!strncmp("xglCreateViewportState", (const char *) pName, sizeof ("xglCreateViewportState")))
+        return myTable.CreateViewportState;
+    else if (!strncmp("xglCreateRasterState", (const char *) pName, sizeof ("xglCreateRasterState")))
+        return myTable.CreateRasterState;
+    else if (!strncmp("xglCreateMsaaState", (const char *) pName, sizeof ("xglCreateMsaaState")))
+        return myTable.CreateMsaaState;
+    else if (!strncmp("xglCreateColorBlendState", (const char *) pName, sizeof ("xglCreateColorBlendState")))
+        return myTable.CreateColorBlendState;
+    else if (!strncmp("xglCreateDepthStencilState", (const char *) pName, sizeof ("xglCreateDepthStencilState")))
+        return myTable.CreateDepthStencilState;
+    else if (!strncmp("xglCreateCommandBuffer", (const char *) pName, sizeof ("xglCreateCommandBuffer")))
+        return myTable.CreateCommandBuffer;
+    else if (!strncmp("xglBeginCommandBuffer", (const char *) pName, sizeof ("xglBeginCommandBuffer")))
+        return myTable.BeginCommandBuffer;
+    else if (!strncmp("xglEndCommandBuffer", (const char *) pName, sizeof ("xglEndCommandBuffer")))
+        return myTable.EndCommandBuffer;
+    else if (!strncmp("xglResetCommandBuffer", (const char *) pName, sizeof ("xglResetCommandBuffer")))
+        return myTable.ResetCommandBuffer;
+    else if (!strncmp("xglCmdBindPipeline", (const char *) pName, sizeof ("xglCmdBindPipeline")))
+        return myTable.CmdBindPipeline;
+    else if (!strncmp("xglCmdBindPipelineDelta", (const char *) pName, sizeof ("xglCmdBindPipelineDelta")))
+        return myTable.CmdBindPipelineDelta;
+    else if (!strncmp("xglCmdBindStateObject", (const char *) pName, sizeof ("xglCmdBindStateObject")))
+        return myTable.CmdBindStateObject;
+    else if (!strncmp("xglCmdBindDescriptorSet", (const char *) pName, sizeof ("xglCmdBindDescriptorSet")))
+        return myTable.CmdBindDescriptorSet;
+    else if (!strncmp("xglCmdBindDynamicMemoryView", (const char *) pName, sizeof ("xglCmdBindDynamicMemoryView")))
+        return myTable.CmdBindDynamicMemoryView;
+    else if (!strncmp("xglCmdBindIndexData", (const char *) pName, sizeof ("xglCmdBindIndexData")))
+        return myTable.CmdBindIndexData;
+    else if (!strncmp("xglCmdBindAttachments", (const char *) pName, sizeof ("xglCmdBindAttachments")))
+        return myTable.CmdBindAttachments;
+    else if (!strncmp("xglCmdPrepareMemoryRegions", (const char *) pName, sizeof ("xglCmdPrepareMemoryRegions")))
+        return myTable.CmdPrepareMemoryRegions;
+    else if (!strncmp("xglCmdPrepareImages", (const char *) pName, sizeof ("xglCmdPrepareImages")))
+        return myTable.CmdPrepareImages;
+    else if (!strncmp("xglCmdDraw", (const char *) pName, sizeof ("xglCmdDraw")))
+        return myTable.CmdDraw;
+    else if (!strncmp("xglCmdDrawIndexed", (const char *) pName, sizeof ("xglCmdDrawIndexed")))
+        return myTable.CmdDrawIndexed;
+    else if (!strncmp("xglCmdDrawIndirect", (const char *) pName, sizeof ("xglCmdDrawIndirect")))
+        return myTable.CmdDrawIndirect;
+    else if (!strncmp("xglCmdDrawIndexedIndirect", (const char *) pName, sizeof ("xglCmdDrawIndexedIndirect")))
+        return myTable.CmdDrawIndexedIndirect;
+    else if (!strncmp("xglCmdDispatch", (const char *) pName, sizeof ("xglCmdDispatch")))
+        return myTable.CmdDispatch;
+    else if (!strncmp("xglCmdDispatchIndirect", (const char *) pName, sizeof ("xglCmdDispatchIndirect")))
+        return myTable.CmdDispatchIndirect;
+    else if (!strncmp("xglCmdCopyMemory", (const char *) pName, sizeof ("xglCmdCopyMemory")))
+        return myTable.CmdCopyMemory;
+    else if (!strncmp("xglCmdCopyImage", (const char *) pName, sizeof ("xglCmdCopyImage")))
+        return myTable.CmdCopyImage;
+    else if (!strncmp("xglCmdCopyMemoryToImage", (const char *) pName, sizeof ("xglCmdCopyMemoryToImage")))
+        return myTable.CmdCopyMemoryToImage;
+    else if (!strncmp("xglCmdCopyImageToMemory", (const char *) pName, sizeof ("xglCmdCopyImageToMemory")))
+        return myTable.CmdCopyImageToMemory;
+    else if (!strncmp("xglCmdCloneImageData", (const char *) pName, sizeof ("xglCmdCloneImageData")))
+        return myTable.CmdCloneImageData;
+    else if (!strncmp("xglCmdUpdateMemory", (const char *) pName, sizeof ("xglCmdUpdateMemory")))
+        return myTable.CmdUpdateMemory;
+    else if (!strncmp("xglCmdFillMemory", (const char *) pName, sizeof ("xglCmdFillMemory")))
+        return myTable.CmdFillMemory;
+    else if (!strncmp("xglCmdClearColorImage", (const char *) pName, sizeof ("xglCmdClearColorImage")))
+        return myTable.CmdClearColorImage;
+    else if (!strncmp("xglCmdClearColorImageRaw", (const char *) pName, sizeof ("xglCmdClearColorImageRaw")))
+        return myTable.CmdClearColorImageRaw;
+    else if (!strncmp("xglCmdClearDepthStencil", (const char *) pName, sizeof ("xglCmdClearDepthStencil")))
+        return myTable.CmdClearDepthStencil;
+    else if (!strncmp("xglCmdResolveImage", (const char *) pName, sizeof ("xglCmdResolveImage")))
+        return myTable.CmdResolveImage;
+    else if (!strncmp("xglCmdSetEvent", (const char *) pName, sizeof ("xglCmdSetEvent")))
+        return myTable.CmdSetEvent;
+    else if (!strncmp("xglCmdResetEvent", (const char *) pName, sizeof ("xglCmdResetEvent")))
+        return myTable.CmdResetEvent;
+    else if (!strncmp("xglCmdMemoryAtomic", (const char *) pName, sizeof ("xglCmdMemoryAtomic")))
+        return myTable.CmdMemoryAtomic;
+    else if (!strncmp("xglCmdBeginQuery", (const char *) pName, sizeof ("xglCmdBeginQuery")))
+        return myTable.CmdBeginQuery;
+    else if (!strncmp("xglCmdEndQuery", (const char *) pName, sizeof ("xglCmdEndQuery")))
+        return myTable.CmdEndQuery;
+    else if (!strncmp("xglCmdResetQueryPool", (const char *) pName, sizeof ("xglCmdResetQueryPool")))
+        return myTable.CmdResetQueryPool;
+    else if (!strncmp("xglCmdWriteTimestamp", (const char *) pName, sizeof ("xglCmdWriteTimestamp")))
+        return myTable.CmdWriteTimestamp;
+    else if (!strncmp("xglCmdInitAtomicCounters", (const char *) pName, sizeof ("xglCmdInitAtomicCounters")))
+        return myTable.CmdInitAtomicCounters;
+    else if (!strncmp("xglCmdLoadAtomicCounters", (const char *) pName, sizeof ("xglCmdLoadAtomicCounters")))
+        return myTable.CmdLoadAtomicCounters;
+    else if (!strncmp("xglCmdSaveAtomicCounters", (const char *) pName, sizeof ("xglCmdSaveAtomicCounters")))
+        return myTable.CmdSaveAtomicCounters;
+    else if (!strncmp("xglDbgSetValidationLevel", (const char *) pName, sizeof ("xglDbgSetValidationLevel")))
+        return myTable.DbgSetValidationLevel;
+	else if (!strncmp("xglDbgRegisterMsgCallback", (const char *) pName, sizeof ("xglDbgRegisterMsgCallback")))
+        return myTable.DbgRegisterMsgCallback;
+	else if (!strncmp("xglDbgUnregisterMsgCallback", (const char *) pName, sizeof ("xglDbgUnregisterMsgCallback")))
+        return myTable.DbgUnregisterMsgCallback;
+    else if (!strncmp("xglDbgSetMessageFilter", (const char *) pName, sizeof ("xglDbgSetMessageFilter")))
+        return myTable.DbgSetMessageFilter;
+    else if (!strncmp("xglDbgSetObjectTag", (const char *) pName, sizeof ("xglDbgSetObjectTag")))
+        return myTable.DbgSetObjectTag;
+    else if (!strncmp("xglDbgSetGlobalOption", (const char *) pName, sizeof ("xglDbgSetGlobalOption")))
+        return myTable.DbgSetGlobalOption;
+    else if (!strncmp("xglDbgSetDeviceOption", (const char *) pName, sizeof ("xglDbgSetDeviceOption")))
+        return myTable.DbgSetDeviceOption;
+    else if (!strncmp("xglCmdDbgMarkerBegin", (const char *) pName, sizeof ("xglCmdDbgMarkerBegin")))
+        return myTable.CmdDbgMarkerBegin;
+    else if (!strncmp("xglCmdDbgMarkerEnd", (const char *) pName, sizeof ("xglCmdDbgMarkerEnd")))
+        return myTable.CmdDbgMarkerEnd;
+    else if (!strncmp("xglWsiX11AssociateConnection", (const char *) pName, sizeof("xglWsiX11AssociateConnection")))
+        return myTable.WsiX11AssociateConnection;
+    else if (!strncmp("xglWsiX11GetMSC", (const char *) pName, sizeof("xglWsiX11GetMSC")))
+        return myTable.WsiX11GetMSC;
+    else if (!strncmp("xglWsiX11CreatePresentableImage", (const char *) pName, sizeof("xglWsiX11CreatePresentableImage")))
+        return myTable.WsiX11CreatePresentableImage;
+    else if (!strncmp("xglWsiX11QueuePresent", (const char *) pName, sizeof("xglWsiX11QueuePresent")))
+        return myTable.WsiX11QueuePresent;
+    else {
+        XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;
+        if (gpuw->pGPA == NULL)
+            return NULL;
+        return gpuw->pGPA(gpuw->nextObject, pName);
+    }
+
+}
+
diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt
index 8c01a60..f348697 100644
--- a/loader/CMakeLists.txt
+++ b/loader/CMakeLists.txt
@@ -1,8 +1,13 @@
-add_custom_command(OUTPUT dispatch.c
+add_custom_command(OUTPUT dispatch.c ${PROJECT_SOURCE_DIR}/icd/common/icd-dispatch-table.h
 	COMMAND ${PROJECT_SOURCE_DIR}/xgl-generate.py loader > dispatch.c
+        COMMAND ${PROJECT_SOURCE_DIR}/xgl-generate.py icd-dispatch-table > ${PROJECT_SOURCE_DIR}/icd/common/icd-dispatch-table.h
 	           DEPENDS ${PROJECT_SOURCE_DIR}/xgl-generate.py
 	                   ${PROJECT_SOURCE_DIR}/xgl.py)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+include_directories(
+	${CMAKE_CURRENT_SOURCE_DIR}
+	${CMAKE_CURRENT_BINARY_DIR}
+)
 
 add_library(XGL SHARED loader.c dispatch.c)
 set_target_properties(XGL PROPERTIES SOVERSION 0)
diff --git a/loader/loader.c b/loader/loader.c
index fddbc24..c86ada2 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -37,25 +37,27 @@
 #include <unistd.h>
 #include <dlfcn.h>
 #include <pthread.h>
-
+#include <assert.h>
 #include "loader.h"
 
-typedef XGL_RESULT (XGLAPI *InitAndEnumerateGpusT)(const XGL_APPLICATION_INFO* pAppInfo, const XGL_ALLOC_CALLBACKS* pAllocCb, XGL_UINT maxGpus, XGL_UINT* pGpuCount, XGL_PHYSICAL_GPU* pGpus);
-typedef XGL_RESULT (XGLAPI *DbgRegisterMsgCallbackT)(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback, XGL_VOID* pUserData);
-typedef XGL_RESULT (XGLAPI *DbgUnregisterMsgCallbackT)(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback);
-typedef XGL_RESULT (XGLAPI *DbgSetGlobalOptionT)(XGL_INT dbgOption, XGL_SIZE dataSize, const XGL_VOID* pData);
 
 struct loader_icd {
     void *handle;
 
-    InitAndEnumerateGpusT InitAndEnumerateGpus;
-    DbgRegisterMsgCallbackT DbgRegisterMsgCallback;
-    DbgUnregisterMsgCallbackT DbgUnregisterMsgCallback;
-    DbgSetGlobalOptionT DbgSetGlobalOption;
+    GetProcAddrType GetProcAddr;
+    InitAndEnumerateGpusType InitAndEnumerateGpus;
+    DbgRegisterMsgCallbackType DbgRegisterMsgCallback;
+    DbgUnregisterMsgCallbackType DbgUnregisterMsgCallback;
+    DbgSetGlobalOptionType DbgSetGlobalOption;
 
     struct loader_icd *next;
 };
 
+struct loader_layers {
+    void *lib_handle;
+    char lib_name[1024];
+};
+
 struct loader_msg_callback {
     XGL_DBG_MSG_CALLBACK_FUNCTION func;
     XGL_VOID *data;
@@ -63,10 +65,15 @@
     struct loader_msg_callback *next;
 };
 
+
 static struct {
     bool scanned;
     struct loader_icd *icds;
-
+    XGL_LAYER_DISPATCH_TABLE *loader_dispatch;
+    XGL_UINT layer_count;
+    bool layer_scaned;
+    char layer_dirs[4096];
+    struct loader_layers layer_libs[MAX_LAYER_LIBRARIES];
     struct loader_msg_callback *msg_callbacks;
 
     bool debug_echo_enable;
@@ -198,13 +205,14 @@
     }
 
 #define LOOKUP(icd, func) do {                              \
-    icd->func = (func## T) dlsym(icd->handle, "xgl" #func); \
+    icd->func = (func## Type) dlsym(icd->handle, "xgl" #func); \
     if (!icd->func) {                                       \
         loader_log(XGL_DBG_MSG_WARNING, 0, dlerror());      \
         loader_icd_destroy(icd);                            \
         return NULL;                                        \
     }                                                       \
 } while (0)
+    LOOKUP(icd, GetProcAddr);
     LOOKUP(icd, InitAndEnumerateGpus);
     LOOKUP(icd, DbgRegisterMsgCallback);
     LOOKUP(icd, DbgUnregisterMsgCallback);
@@ -351,6 +359,603 @@
     loader.scanned = true;
 }
 
+#ifndef DEFAULT_XGL_LAYERS_PATH
+// TODO: Is this a good default locations
+#define DEFAULT_XGL_LAYERS_PATH ".:/usr/lib/i386-linux-gnu/xgl:/usr/lib/x86_64-linux-gnu/xgl"
+#endif
+
+static void layer_lib_scan(const char * libInPaths, const bool useDefaultDirs, const bool openLibs)
+{
+    const char *p, *next;
+    char *libPaths = &loader.layer_dirs[0];
+    DIR *curdir;
+    struct dirent *dent;
+    int len, i, n;
+
+    if (libInPaths){
+        strncpy(libPaths, libInPaths, sizeof(loader.layer_dirs));
+    }
+    else {
+        *libPaths = '\0';
+    }
+
+    /* cleanup any previously scanned libraries */
+    for (i = 0; i < loader.layer_count; i++) {
+        if (loader.layer_libs[i].lib_handle != NULL)
+            dlclose(loader.layer_libs[i].lib_handle);
+        loader.layer_libs[i].lib_handle = NULL;
+    }
+    loader.layer_count = 0;
+
+    if (useDefaultDirs)
+       strncat(libPaths, DEFAULT_XGL_LAYERS_PATH, sizeof(loader.layer_dirs) - sizeof(DEFAULT_XGL_LAYERS_PATH));
+
+    for (p = libPaths; *p; p = next) {
+       next = strchr(p, ':');
+       if (next == NULL) {
+          len = strlen(p);
+          next = p + len;
+       }
+       else {
+          len = next - p;
+          *(char *) next = '\0';
+          next++;
+       }
+
+       curdir = opendir(p);
+       if (curdir) {
+          dent = readdir(curdir);
+          while (dent) {
+              n = loader.layer_count;
+             /* look for wrappers starting with "libXGLlayer" */
+             if (!strncmp(dent->d_name, "libXGLLayer", strlen("libXGLLayer"))) {
+                snprintf((char *) &(loader.layer_libs[n].lib_name), sizeof(loader.layer_libs[0].lib_name), "%s/%s",p,dent->d_name);
+                if ((loader.layer_libs[n].lib_handle = dlopen((const char *) &(loader.layer_libs[n].lib_name), RTLD_LAZY)) == NULL)
+                    continue;
+
+                loader.layer_count++;
+                if (!openLibs)
+                    dlclose(loader.layer_libs[n].lib_handle);
+             }
+
+             dent = readdir(curdir);
+          }
+          closedir(curdir);
+       }
+    }
+
+    loader.layer_scaned = true;
+}
+
+#if 0
+static bool layer_lib_sort(char * str, const XGL_UINT count)
+{
+    XGL_UINT i;
+    struct loader_layers temp, *cur, *start;
+
+    start = &loader.layer_libs[count];
+    for (i = count; i < loader.layer_count; i++) {
+        cur = &loader.layer_libs[i];
+
+        if (!strcmp(str, cur->lib_name) && cur->lib_handle != NULL) {
+            if (count == i)
+                return true;
+            strcpy(temp.lib_name, cur->lib_name);
+            temp.lib_handle = cur->lib_handle;
+            strcpy(cur->lib_name, start->lib_name);
+            cur->lib_handle = start->lib_handle;
+            strcpy(start->lib_name, temp.lib_name);
+            start->lib_handle = temp.lib_handle;
+            return true;
+        }
+    }
+    return false;
+}
+#endif
+LOADER_EXPORT XGL_RESULT XGLAPI ScanForLayers(const XGL_CHAR* pLibraryDirectories, XGL_CHAR * pStr)
+{
+    size_t size = 0;
+    XGL_UINT i;
+    static XGL_CHAR *lib_str=NULL;
+
+    if (!pLibraryDirectories)
+        return XGL_ERROR_INVALID_POINTER;
+
+    if (strlen((const char *) pLibraryDirectories) > sizeof(loader.layer_dirs))
+        return XGL_ERROR_INVALID_POINTER;
+
+    layer_lib_scan((const char *) pLibraryDirectories, true, false);
+
+    for (i = 0; i < loader.layer_count; i++) {
+        size += strlen(loader.layer_libs[i].lib_name) + 1;
+    }
+
+    free(lib_str);
+    lib_str = malloc(size);
+    if (!lib_str)
+        return XGL_ERROR_OUT_OF_MEMORY;
+
+   pStr = lib_str;
+   for (i = 0; i < loader.layer_count; i++) {
+        strncat((char *) pStr, loader.layer_libs[i].lib_name, strlen(loader.layer_libs[i].lib_name));
+        strcat((char *) pStr, ":");
+    }
+    return XGL_SUCCESS;
+}
+
+static void init_dispatch_table(XGL_LAYER_DISPATCH_TABLE *tab, GetProcAddrType fpGPA, XGL_PHYSICAL_GPU gpu)
+{
+    tab->GetProcAddr = fpGPA;
+    tab->InitAndEnumerateGpus = fpGPA(gpu, (const XGL_CHAR *) "xglInitAndEnumerateGpus");
+    tab->GetGpuInfo = fpGPA(gpu, (const XGL_CHAR *) "xglGetGpuInfo");
+    tab->CreateDevice = fpGPA(gpu, (const XGL_CHAR *) "xglCreateDevice");
+    tab->DestroyDevice = fpGPA(gpu, (const XGL_CHAR *) "xglDestroyDevice");
+    tab->GetExtensionSupport = fpGPA(gpu, (const XGL_CHAR *) "xglGetExtensionSupport");
+    tab->GetDeviceQueue = fpGPA(gpu, (const XGL_CHAR *) "xglGetDeviceQueue");
+    tab->QueueSubmit = fpGPA(gpu, (const XGL_CHAR *) "xglQueueSubmit");
+    tab->QueueSetGlobalMemReferences = fpGPA(gpu, (const XGL_CHAR *) "xglQueueSetGlobalMemReferences");
+    tab->QueueWaitIdle = fpGPA(gpu, (const XGL_CHAR *) "xglQueueWaitIdle");
+    tab->DeviceWaitIdle = fpGPA(gpu, (const XGL_CHAR *) "xglDeviceWaitIdle");
+    tab->GetMemoryHeapCount = fpGPA(gpu, (const XGL_CHAR *) "xglGetMemoryHeapCount");
+    tab->GetMemoryHeapInfo = fpGPA(gpu, (const XGL_CHAR *) "xglGetMemoryHeapInfo");
+    tab->AllocMemory = fpGPA(gpu, (const XGL_CHAR *) "xglAllocMemory");
+    tab->FreeMemory = fpGPA(gpu, (const XGL_CHAR *) "xglFreeMemory");
+    tab->SetMemoryPriority = fpGPA(gpu, (const XGL_CHAR *) "xglSetMemoryPriority");
+    tab->MapMemory = fpGPA(gpu, (const XGL_CHAR *) "xglMapMemory");
+    tab->UnmapMemory = fpGPA(gpu, (const XGL_CHAR *) "xglUnmapMemory");
+    tab->PinSystemMemory = fpGPA(gpu, (const XGL_CHAR *) "xglPinSystemMemory");
+    tab->RemapVirtualMemoryPages = fpGPA(gpu, (const XGL_CHAR *) "xglRemapVirtualMemoryPages");
+    tab->GetMultiGpuCompatibility = fpGPA(gpu, (const XGL_CHAR *) "xglGetMultiGpuCompatibility");
+    tab->OpenSharedMemory = fpGPA(gpu, (const XGL_CHAR *) "xglOpenSharedMemory");
+    tab->OpenSharedQueueSemaphore = fpGPA(gpu, (const XGL_CHAR *) "xglOpenSharedQueueSemaphore");
+    tab->OpenPeerMemory = fpGPA(gpu, (const XGL_CHAR *) "xglOpenPeerMemory");
+    tab->OpenPeerImage = fpGPA(gpu, (const XGL_CHAR *) "xglOpenPeerImage");
+    tab->DestroyObject = fpGPA(gpu, (const XGL_CHAR *) "xglDestroyObject");
+    tab->GetObjectInfo = fpGPA(gpu, (const XGL_CHAR *) "xglGetObjectInfo");
+    tab->BindObjectMemory = fpGPA(gpu, (const XGL_CHAR *) "xglBindObjectMemory");
+    tab->CreateFence = fpGPA(gpu, (const XGL_CHAR *) "xglCreateFence");
+    tab->GetFenceStatus = fpGPA(gpu, (const XGL_CHAR *) "xglGetFenceStatus");
+    tab->WaitForFences = fpGPA(gpu, (const XGL_CHAR *) "xglWaitForFences");
+    tab->CreateQueueSemaphore = fpGPA(gpu, (const XGL_CHAR *) "xglCreateQueueSemaphore");
+    tab->SignalQueueSemaphore = fpGPA(gpu, (const XGL_CHAR *) "xglSignalQueueSemaphore");
+    tab->WaitQueueSemaphore = fpGPA(gpu, (const XGL_CHAR *) "xglWaitQueueSemaphore");
+    tab->CreateEvent = fpGPA(gpu, (const XGL_CHAR *) "xglCreateEvent");
+    tab->GetEventStatus = fpGPA(gpu, (const XGL_CHAR *) "xglGetEventStatus");
+    tab->SetEvent = fpGPA(gpu, (const XGL_CHAR *) "xglSetEvent");
+    tab->ResetEvent = fpGPA(gpu, (const XGL_CHAR *) "xglResetEvent");
+    tab->CreateQueryPool = fpGPA(gpu, (const XGL_CHAR *) "xglCreateQueryPool");
+    tab->GetQueryPoolResults = fpGPA(gpu, (const XGL_CHAR *) "xglGetQueryPoolResults");
+    tab->GetFormatInfo = fpGPA(gpu, (const XGL_CHAR *) "xglGetFormatInfo");
+    tab->CreateImage = fpGPA(gpu, (const XGL_CHAR *) "xglCreateImage");
+    tab->GetImageSubresourceInfo = fpGPA(gpu, (const XGL_CHAR *) "xglGetImageSubresourceInfo");
+    tab->CreateImageView = fpGPA(gpu, (const XGL_CHAR *) "xglCreateImageView");
+    tab->CreateColorAttachmentView = fpGPA(gpu, (const XGL_CHAR *) "xglCreateColorAttachmentView");
+    tab->CreateDepthStencilView = fpGPA(gpu, (const XGL_CHAR *) "xglCreateDepthStencilView");
+    tab->CreateShader = fpGPA(gpu, (const XGL_CHAR *) "xglCreateShader");
+    tab->CreateGraphicsPipeline = fpGPA(gpu, (const XGL_CHAR *) "xglCreateGraphicsPipeline");
+    tab->CreateComputePipeline = fpGPA(gpu, (const XGL_CHAR *) "xglCreateComputePipeline");
+    tab->StorePipeline = fpGPA(gpu, (const XGL_CHAR *) "xglStorePipeline");
+    tab->LoadPipeline = fpGPA(gpu, (const XGL_CHAR *) "xglLoadPipeline");
+    tab->CreatePipelineDelta = fpGPA(gpu, (const XGL_CHAR *) "xglCreatePipelineDelta");
+    tab->CreateSampler = fpGPA(gpu, (const XGL_CHAR *) "xglCreateSampler");
+    tab->CreateDescriptorSet = fpGPA(gpu, (const XGL_CHAR *) "xglCreateDescriptorSet");
+    tab->BeginDescriptorSetUpdate = fpGPA(gpu, (const XGL_CHAR *) "xglBeginDescriptorSetUpdate");
+    tab->EndDescriptorSetUpdate = fpGPA(gpu, (const XGL_CHAR *) "xglEndDescriptorSetUpdate");
+    tab->AttachSamplerDescriptors = fpGPA(gpu, (const XGL_CHAR *) "xglAttachSamplerDescriptors");
+    tab->AttachImageViewDescriptors = fpGPA(gpu, (const XGL_CHAR *) "xglAttachImageViewDescriptors");
+    tab->AttachMemoryViewDescriptors = fpGPA(gpu, (const XGL_CHAR *) "xglAttachMemoryViewDescriptors");
+    tab->AttachNestedDescriptors = fpGPA(gpu, (const XGL_CHAR *) "xglAttachNestedDescriptors");
+    tab->ClearDescriptorSetSlots = fpGPA(gpu, (const XGL_CHAR *) "xglClearDescriptorSetSlots");
+    tab->CreateViewportState = fpGPA(gpu, (const XGL_CHAR *) "xglCreateViewportState");
+    tab->CreateRasterState = fpGPA(gpu, (const XGL_CHAR *) "xglCreateRasterState");
+    tab->CreateMsaaState = fpGPA(gpu, (const XGL_CHAR *) "xglCreateMsaaState");
+    tab->CreateColorBlendState = fpGPA(gpu, (const XGL_CHAR *) "xglCreateColorBlendState");
+    tab->CreateDepthStencilState = fpGPA(gpu, (const XGL_CHAR *) "xglCreateDepthStencilState");
+    tab->CreateCommandBuffer = fpGPA(gpu, (const XGL_CHAR *) "xglCreateCommandBuffer");
+    tab->BeginCommandBuffer = fpGPA(gpu, (const XGL_CHAR *) "xglBeginCommandBuffer");
+    tab->EndCommandBuffer = fpGPA(gpu, (const XGL_CHAR *) "xglEndCommandBuffer");
+    tab->ResetCommandBuffer = fpGPA(gpu, (const XGL_CHAR *) "xglResetCommandBuffer");
+    tab->CmdBindPipeline = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindPipeline");
+    tab->CmdBindPipelineDelta = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindPipelineDelta");
+    tab->CmdBindStateObject = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindStateObject");
+    tab->CmdBindDescriptorSet = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindDescriptorSet");
+    tab->CmdBindDynamicMemoryView = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindDynamicMemoryView");
+    tab->CmdBindIndexData = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindIndexData");
+    tab->CmdBindAttachments = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindAttachments");
+    tab->CmdPrepareMemoryRegions = fpGPA(gpu, (const XGL_CHAR *) "xglCmdPrepareMemoryRegions");
+    tab->CmdPrepareImages = fpGPA(gpu, (const XGL_CHAR *) "xglCmdPrepareImages");
+    tab->CmdDraw = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDraw");
+    tab->CmdDrawIndexed = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDrawIndexed");
+    tab->CmdDrawIndirect = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDrawIndirect");
+    tab->CmdDrawIndexedIndirect = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDrawIndexedIndirect");
+    tab->CmdDispatch = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDispatch");
+    tab->CmdDispatchIndirect = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDispatchIndirect");
+    tab->CmdCopyMemory = fpGPA(gpu, (const XGL_CHAR *) "xglCmdCopyMemory");
+    tab->CmdCopyImage = fpGPA(gpu, (const XGL_CHAR *) "xglCmdCopyImage");
+    tab->CmdCopyMemoryToImage = fpGPA(gpu, (const XGL_CHAR *) "xglCmdCopyMemoryToImage");
+    tab->CmdCopyImageToMemory = fpGPA(gpu, (const XGL_CHAR *) "xglCmdCopyImageToMemory");
+    tab->CmdCloneImageData = fpGPA(gpu, (const XGL_CHAR *) "xglCmdCloneImageData");
+    tab->CmdUpdateMemory = fpGPA(gpu, (const XGL_CHAR *) "xglCmdUpdateMemory");
+    tab->CmdFillMemory = fpGPA(gpu, (const XGL_CHAR *) "xglCmdFillMemory");
+    tab->CmdClearColorImage = fpGPA(gpu, (const XGL_CHAR *) "xglCmdClearColorImage");
+    tab->CmdClearColorImageRaw = fpGPA(gpu, (const XGL_CHAR *) "xglCmdClearColorImageRaw");
+    tab->CmdClearDepthStencil = fpGPA(gpu, (const XGL_CHAR *) "xglCmdClearDepthStencil");
+    tab->CmdResolveImage = fpGPA(gpu, (const XGL_CHAR *) "xglCmdResolveImage");
+    tab->CmdSetEvent = fpGPA(gpu, (const XGL_CHAR *) "xglCmdSetEvent");
+    tab->CmdResetEvent = fpGPA(gpu, (const XGL_CHAR *) "xglCmdResetEvent");
+    tab->CmdMemoryAtomic = fpGPA(gpu, (const XGL_CHAR *) "xglCmdMemoryAtomic");
+    tab->CmdBeginQuery = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBeginQuery");
+    tab->CmdEndQuery = fpGPA(gpu, (const XGL_CHAR *) "xglCmdEndQuery");
+    tab->CmdResetQueryPool = fpGPA(gpu, (const XGL_CHAR *) "xglCmdResetQueryPool");
+    tab->CmdWriteTimestamp = fpGPA(gpu, (const XGL_CHAR *) "xglCmdWriteTimestamp");
+    tab->CmdInitAtomicCounters = fpGPA(gpu, (const XGL_CHAR *) "xglCmdInitAtomicCounters");
+    tab->CmdLoadAtomicCounters = fpGPA(gpu, (const XGL_CHAR *) "xglCmdLoadAtomicCounters");
+    tab->CmdSaveAtomicCounters = fpGPA(gpu, (const XGL_CHAR *) "xglCmdSaveAtomicCounters");
+    tab->DbgSetValidationLevel = fpGPA(gpu, (const XGL_CHAR *) "xglDbgSetValidationLevel");
+    tab->DbgRegisterMsgCallback = fpGPA(gpu, (const XGL_CHAR *) "xglDbgRegisterMsgCallback");
+    tab->DbgUnregisterMsgCallback = fpGPA(gpu, (const XGL_CHAR *) "xglDbgUnregisterMsgCallback");
+    tab->DbgSetMessageFilter = fpGPA(gpu, (const XGL_CHAR *) "xglDbgSetMessageFilter");
+    tab->DbgSetObjectTag = fpGPA(gpu, (const XGL_CHAR *) "xglDbgSetObjectTag");
+    tab->DbgSetGlobalOption = fpGPA(gpu, (const XGL_CHAR *) "xglDbgSetGlobalOption");
+    tab->DbgSetDeviceOption = fpGPA(gpu, (const XGL_CHAR *) "xglDbgSetDeviceOption");
+    tab->CmdDbgMarkerBegin = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDbgMarkerBegin");
+    tab->CmdDbgMarkerEnd = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDbgMarkerEnd");
+    tab->WsiX11AssociateConnection = fpGPA(gpu, (const XGL_CHAR *) "xglWsiX11AssociateConnection");
+    tab->WsiX11GetMSC = fpGPA(gpu, (const XGL_CHAR *) "xglWsiX11GetMSC");
+    tab->WsiX11CreatePresentableImage = fpGPA(gpu, (const XGL_CHAR *) "xglWsiX11CreatePresentableImage");
+    tab->WsiX11QueuePresent = fpGPA(gpu, (const XGL_CHAR *) "xglWsiX11QueuePresent");
+}
+
+extern XGL_UINT ActivateLayers(XGL_PHYSICAL_GPU *gpu)
+{
+    static bool layer_installed = false;
+    //const struct loader_icd *icd;
+    /* activate any layer libraries */
+    if (loader.layer_count > 0 && !layer_installed) {
+
+        //todo get icd from gpu
+        //icd = loader.icds;  // We are only going to configure the first driver
+        //SetDispatchType IcdSetDispatch = dlsym(icd->handle, "xglSetDispatch");
+
+        // TODO For now just assume  all layers scanned will be  activated in the order they were scanned
+        XGL_BASE_LAYER_OBJECT *gpuObj = (XGL_BASE_LAYER_OBJECT *) *gpu;
+        XGL_BASE_LAYER_OBJECT *nextGpuObj;
+        GetProcAddrType nextGPA = gpuObj->pGPA;
+        for (XGL_INT i = loader.layer_count - 1; i >= 0; i--) {
+
+            if ((loader.layer_libs[i].lib_handle = dlopen((const char *) &(loader.layer_libs[i].lib_name), RTLD_LAZY | RTLD_DEEPBIND)) == NULL) {
+                loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to open layer library %s got error %d", loader.layer_libs[i].lib_name, dlerror());
+                continue;
+            } else {
+                loader_log(XGL_DBG_MSG_UNKNOWN, 0, "Inserting layer lib %s",loader.layer_libs[i].lib_name);
+            }
+
+            //create newly wrapped gpu object
+            nextGpuObj = malloc(sizeof(XGL_BASE_LAYER_OBJECT));
+            if (! nextGpuObj)
+                loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to malloc Gpu object for layer");
+            nextGpuObj->pGPA = nextGPA;
+            nextGpuObj->baseObject = gpuObj->baseObject;
+            nextGpuObj->nextObject = gpuObj;
+            gpuObj = nextGpuObj;
+
+            nextGPA = dlsym(loader.layer_libs[i].lib_handle, "xglGetProcAddr");
+            if (!nextGPA) {
+                loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to find xglGetProcAddr in layer %s", loader.layer_libs[i].lib_name);
+                continue;
+            }
+
+            if (i == 0) {
+                //TODO handle multiple icd case
+                init_dispatch_table(loader.loader_dispatch, nextGPA, gpuObj);
+                //IcdSetDispatch(&new_table, true);
+            }
+        }
+        *gpu = ((XGL_PHYSICAL_GPU *) gpuObj);
+        layer_installed = true;
+    }
+    return loader.layer_count;
+}
+
+#if 0
+LOADER_EXPORT XGL_RESULT xglSetLayers(const XGL_CHAR * pStr)
+{
+    char *p, *next, *str;
+    int len;
+    XGL_UINT count= 0;
+
+    if (!pStr)
+        return XGL_ERROR_INVALID_POINTER;
+
+    p= (char *) pStr;
+    str = malloc(strlen(p) + 1);
+    do {
+        next = strchr(p, ':');
+        if (next == NULL) {
+            len = strlen(p);
+            next = p + len;
+        }
+        else {
+            len = next - p;
+            *(char *) next = '\0';
+            next++;
+        }
+
+        strncpy(str, p, len);
+        str[len] = '\0';
+        if (layer_lib_sort(str, count))
+           count++;
+        p = next;
+
+    } while (*p  && count < MAX_LAYER_LIBRARIES-1);
+
+    for (int i = count; i < loader.layer_count; i++) {
+        loader.layer_libs[i].lib_handle = NULL;
+    }
+
+    loader.layer_count = count;
+    free(str);
+
+    return XGL_SUCCESS;
+}
+
+#endif
+
+LOADER_EXPORT void * XGLAPI xglGetProcAddr(XGL_PHYSICAL_GPU gpu, const XGL_CHAR * pName) {
+
+    if (gpu == NULL)
+        return NULL;
+
+    XGL_LAYER_DISPATCH_TABLE * disp_table = * (XGL_LAYER_DISPATCH_TABLE **) gpu;
+    if (disp_table == NULL)
+        return NULL;
+
+    if (!strncmp("xglGetProcAddr", (const char *) pName, sizeof("xglGetProcAddr")))
+        return xglGetProcAddr;
+    else if (!strncmp("xglInitAndEnumerateGpus", (const char *) pName, sizeof("xglInitAndEnumerateGpus")))
+        return disp_table->InitAndEnumerateGpus;
+    else if (!strncmp("xglGetGpuInfo", (const char *) pName, sizeof ("xglGetGpuInfo")))
+        return disp_table->GetGpuInfo;
+    else if (!strncmp("xglCreateDevice", (const char *) pName, sizeof ("xglCreateDevice")))
+        return disp_table->CreateDevice;
+    else if (!strncmp("xglDestroyDevice", (const char *) pName, sizeof ("xglDestroyDevice")))
+        return disp_table->DestroyDevice;
+    else if (!strncmp("xglGetExtensionSupport", (const char *) pName, sizeof ("xglGetExtensionSupport")))
+        return disp_table->GetExtensionSupport;
+    else if (!strncmp("xglGetDeviceQueue", (const char *) pName, sizeof ("xglGetDeviceQueue")))
+        return disp_table->GetDeviceQueue;
+    else if (!strncmp("xglQueueSubmit", (const char *) pName, sizeof ("xglQueueSubmit")))
+        return disp_table->QueueSubmit;
+    else if (!strncmp("xglQueueSetGlobalMemReferences", (const char *) pName, sizeof ("xglQueueSetGlobalMemReferences")))
+        return disp_table->QueueSetGlobalMemReferences;
+    else if (!strncmp("xglQueueWaitIdle", (const char *) pName, sizeof ("xglQueueWaitIdle")))
+        return disp_table->QueueWaitIdle;
+    else if (!strncmp("xglDeviceWaitIdle", (const char *) pName, sizeof ("xglDeviceWaitIdle")))
+        return disp_table->DeviceWaitIdle;
+    else if (!strncmp("xglGetMemoryHeapCount", (const char *) pName, sizeof ("xglGetMemoryHeapCount")))
+        return disp_table->GetMemoryHeapCount;
+    else if (!strncmp("xglGetMemoryHeapInfo", (const char *) pName, sizeof ("xglGetMemoryHeapInfo")))
+        return disp_table->GetMemoryHeapInfo;
+    else if (!strncmp("xglAllocMemory", (const char *) pName, sizeof ("xglAllocMemory")))
+        return disp_table->AllocMemory;
+    else if (!strncmp("xglFreeMemory", (const char *) pName, sizeof ("xglFreeMemory")))
+        return disp_table->FreeMemory;
+    else if (!strncmp("xglSetMemoryPriority", (const char *) pName, sizeof ("xglSetMemoryPriority")))
+        return disp_table->SetMemoryPriority;
+    else if (!strncmp("xglMapMemory", (const char *) pName, sizeof ("xglMapMemory")))
+        return disp_table->MapMemory;
+    else if (!strncmp("xglUnmapMemory", (const char *) pName, sizeof ("xglUnmapMemory")))
+        return disp_table->UnmapMemory;
+    else if (!strncmp("xglPinSystemMemory", (const char *) pName, sizeof ("xglPinSystemMemory")))
+        return disp_table->PinSystemMemory;
+    else if (!strncmp("xglRemapVirtualMemoryPages", (const char *) pName, sizeof ("xglRemapVirtualMemoryPages")))
+        return disp_table->RemapVirtualMemoryPages;
+    else if (!strncmp("xglGetMultiGpuCompatibility", (const char *) pName, sizeof ("xglGetMultiGpuCompatibility")))
+        return disp_table->GetMultiGpuCompatibility;
+    else if (!strncmp("xglOpenSharedMemory", (const char *) pName, sizeof ("xglOpenSharedMemory")))
+        return disp_table->OpenSharedMemory;
+    else if (!strncmp("xglOpenSharedQueueSemaphore", (const char *) pName, sizeof ("xglOpenSharedQueueSemaphore")))
+        return disp_table->OpenSharedQueueSemaphore;
+    else if (!strncmp("xglOpenPeerMemory", (const char *) pName, sizeof ("xglOpenPeerMemory")))
+        return disp_table->OpenPeerMemory;
+    else if (!strncmp("xglOpenPeerImage", (const char *) pName, sizeof ("xglOpenPeerImage")))
+        return disp_table->OpenPeerImage;
+    else if (!strncmp("xglDestroyObject", (const char *) pName, sizeof ("xglDestroyObject")))
+        return disp_table->DestroyObject;
+    else if (!strncmp("xglGetObjectInfo", (const char *) pName, sizeof ("xglGetObjectInfo")))
+        return disp_table->GetObjectInfo;
+    else if (!strncmp("xglBindObjectMemory", (const char *) pName, sizeof ("xglBindObjectMemory")))
+        return disp_table->BindObjectMemory;
+    else if (!strncmp("xglCreateFence", (const char *) pName, sizeof ("xgllCreateFence")))
+        return disp_table->CreateFence;
+    else if (!strncmp("xglGetFenceStatus", (const char *) pName, sizeof ("xglGetFenceStatus")))
+        return disp_table->GetFenceStatus;
+    else if (!strncmp("xglWaitForFences", (const char *) pName, sizeof ("xglWaitForFences")))
+        return disp_table->WaitForFences;
+    else if (!strncmp("xglCreateQueueSemaphore", (const char *) pName, sizeof ("xgllCreateQueueSemaphore")))
+        return disp_table->CreateQueueSemaphore;
+    else if (!strncmp("xglSignalQueueSemaphore", (const char *) pName, sizeof ("xglSignalQueueSemaphore")))
+        return disp_table->SignalQueueSemaphore;
+    else if (!strncmp("xglWaitQueueSemaphore", (const char *) pName, sizeof ("xglWaitQueueSemaphore")))
+        return disp_table->WaitQueueSemaphore;
+    else if (!strncmp("xglCreateEvent", (const char *) pName, sizeof ("xgllCreateEvent")))
+        return disp_table->CreateEvent;
+    else if (!strncmp("xglGetEventStatus", (const char *) pName, sizeof ("xglGetEventStatus")))
+        return disp_table->GetEventStatus;
+    else if (!strncmp("xglSetEvent", (const char *) pName, sizeof ("xglSetEvent")))
+        return disp_table->SetEvent;
+    else if (!strncmp("xglResetEvent", (const char *) pName, sizeof ("xgllResetEvent")))
+        return disp_table->ResetEvent;
+    else if (!strncmp("xglCreateQueryPool", (const char *) pName, sizeof ("xglCreateQueryPool")))
+        return disp_table->CreateQueryPool;
+    else if (!strncmp("xglGetQueryPoolResults", (const char *) pName, sizeof ("xglGetQueryPoolResults")))
+        return disp_table->GetQueryPoolResults;
+    else if (!strncmp("xglGetFormatInfo", (const char *) pName, sizeof ("xglGetFormatInfo")))
+        return disp_table->GetFormatInfo;
+    else if (!strncmp("xglCreateImage", (const char *) pName, sizeof ("xglCreateImage")))
+        return disp_table->CreateImage;
+    else if (!strncmp("xglGetImageSubresourceInfo", (const char *) pName, sizeof ("xglGetImageSubresourceInfo")))
+        return disp_table->GetImageSubresourceInfo;
+    else if (!strncmp("xglCreateImageView", (const char *) pName, sizeof ("xglCreateImageView")))
+        return disp_table->CreateImageView;
+    else if (!strncmp("xglCreateColorAttachmentView", (const char *) pName, sizeof ("xglCreateColorAttachmentView")))
+        return disp_table->CreateColorAttachmentView;
+    else if (!strncmp("xglCreateDepthStencilView", (const char *) pName, sizeof ("xglCreateDepthStencilView")))
+        return disp_table->CreateDepthStencilView;
+    else if (!strncmp("xglCreateShader", (const char *) pName, sizeof ("xglCreateShader")))
+        return disp_table->CreateShader;
+    else if (!strncmp("xglCreateGraphicsPipeline", (const char *) pName, sizeof ("xglCreateGraphicsPipeline")))
+        return disp_table->CreateGraphicsPipeline;
+    else if (!strncmp("xglCreateComputePipeline", (const char *) pName, sizeof ("xglCreateComputePipeline")))
+        return disp_table->CreateComputePipeline;
+    else if (!strncmp("xglStorePipeline", (const char *) pName, sizeof ("xglStorePipeline")))
+        return disp_table->StorePipeline;
+    else if (!strncmp("xglLoadPipeline", (const char *) pName, sizeof ("xglLoadPipeline")))
+        return disp_table->LoadPipeline;
+    else if (!strncmp("xglCreatePipelineDelta", (const char *) pName, sizeof ("xglCreatePipelineDelta")))
+        return disp_table->CreatePipelineDelta;
+    else if (!strncmp("xglCreateSampler", (const char *) pName, sizeof ("xglCreateSampler")))
+        return disp_table->CreateSampler;
+    else if (!strncmp("xglCreateDescriptorSet", (const char *) pName, sizeof ("xglCreateDescriptorSet")))
+        return disp_table->CreateDescriptorSet;
+    else if (!strncmp("xglBeginDescriptorSetUpdate", (const char *) pName, sizeof ("xglBeginDescriptorSetUpdate")))
+        return disp_table->BeginDescriptorSetUpdate;
+    else if (!strncmp("xglEndDescriptorSetUpdate", (const char *) pName, sizeof ("xglEndDescriptorSetUpdate")))
+        return disp_table->EndDescriptorSetUpdate;
+    else if (!strncmp("xglAttachSamplerDescriptors", (const char *) pName, sizeof ("xglAttachSamplerDescriptors")))
+        return disp_table->AttachSamplerDescriptors;
+    else if (!strncmp("xglAttachImageViewDescriptors", (const char *) pName, sizeof ("xglAttachImageViewDescriptors")))
+        return disp_table->AttachImageViewDescriptors;
+    else if (!strncmp("xglAttachMemoryViewDescriptors", (const char *) pName, sizeof ("xglAttachMemoryViewDescriptors")))
+        return disp_table->AttachMemoryViewDescriptors;
+    else if (!strncmp("xglAttachNestedDescriptors", (const char *) pName, sizeof ("xglAttachNestedDescriptors")))
+        return disp_table->AttachNestedDescriptors;
+    else if (!strncmp("xglClearDescriptorSetSlots", (const char *) pName, sizeof ("xglClearDescriptorSetSlots")))
+        return disp_table->ClearDescriptorSetSlots;
+    else if (!strncmp("xglCreateViewportState", (const char *) pName, sizeof ("xglCreateViewportState")))
+        return disp_table->CreateViewportState;
+    else if (!strncmp("xglCreateRasterState", (const char *) pName, sizeof ("xglCreateRasterState")))
+        return disp_table->CreateRasterState;
+    else if (!strncmp("xglCreateMsaaState", (const char *) pName, sizeof ("xglCreateMsaaState")))
+        return disp_table->CreateMsaaState;
+    else if (!strncmp("xglCreateColorBlendState", (const char *) pName, sizeof ("xglCreateColorBlendState")))
+        return disp_table->CreateColorBlendState;
+    else if (!strncmp("xglCreateDepthStencilState", (const char *) pName, sizeof ("xglCreateDepthStencilState")))
+        return disp_table->CreateDepthStencilState;
+    else if (!strncmp("xglCreateCommandBuffer", (const char *) pName, sizeof ("xglCreateCommandBuffer")))
+        return disp_table->CreateCommandBuffer;
+    else if (!strncmp("xglBeginCommandBuffer", (const char *) pName, sizeof ("xglBeginCommandBuffer")))
+        return disp_table->BeginCommandBuffer;
+    else if (!strncmp("xglEndCommandBuffer", (const char *) pName, sizeof ("xglEndCommandBuffer")))
+        return disp_table->EndCommandBuffer;
+    else if (!strncmp("xglResetCommandBuffer", (const char *) pName, sizeof ("xglResetCommandBuffer")))
+        return disp_table->ResetCommandBuffer;
+    else if (!strncmp("xglCmdBindPipeline", (const char *) pName, sizeof ("xglCmdBindPipeline")))
+        return disp_table->CmdBindPipeline;
+    else if (!strncmp("xglCmdBindPipelineDelta", (const char *) pName, sizeof ("xglCmdBindPipelineDelta")))
+        return disp_table->CmdBindPipelineDelta;
+    else if (!strncmp("xglCmdBindStateObject", (const char *) pName, sizeof ("xglCmdBindStateObject")))
+        return disp_table->CmdBindStateObject;
+    else if (!strncmp("xglCmdBindDescriptorSet", (const char *) pName, sizeof ("xglCmdBindDescriptorSet")))
+        return disp_table->CmdBindDescriptorSet;
+    else if (!strncmp("xglCmdBindDynamicMemoryView", (const char *) pName, sizeof ("xglCmdBindDynamicMemoryView")))
+        return disp_table->CmdBindDynamicMemoryView;
+    else if (!strncmp("xglCmdBindIndexData", (const char *) pName, sizeof ("xglCmdBindIndexData")))
+        return disp_table->CmdBindIndexData;
+    else if (!strncmp("xglCmdBindAttachments", (const char *) pName, sizeof ("xglCmdBindAttachments")))
+        return disp_table->CmdBindAttachments;
+    else if (!strncmp("xglCmdPrepareMemoryRegions", (const char *) pName, sizeof ("xglCmdPrepareMemoryRegions")))
+        return disp_table->CmdPrepareMemoryRegions;
+    else if (!strncmp("xglCmdPrepareImages", (const char *) pName, sizeof ("xglCmdPrepareImages")))
+        return disp_table->CmdPrepareImages;
+    else if (!strncmp("xglCmdDraw", (const char *) pName, sizeof ("xglCmdDraw")))
+        return disp_table->CmdDraw;
+    else if (!strncmp("xglCmdDrawIndexed", (const char *) pName, sizeof ("xglCmdDrawIndexed")))
+        return disp_table->CmdDrawIndexed;
+    else if (!strncmp("xglCmdDrawIndirect", (const char *) pName, sizeof ("xglCmdDrawIndirect")))
+        return disp_table->CmdDrawIndirect;
+    else if (!strncmp("xglCmdDrawIndexedIndirect", (const char *) pName, sizeof ("xglCmdDrawIndexedIndirect")))
+        return disp_table->CmdDrawIndexedIndirect;
+    else if (!strncmp("xglCmdDispatch", (const char *) pName, sizeof ("xglCmdDispatch")))
+        return disp_table->CmdDispatch;
+    else if (!strncmp("xglCmdDispatchIndirect", (const char *) pName, sizeof ("xglCmdDispatchIndirect")))
+        return disp_table->CmdDispatchIndirect;
+    else if (!strncmp("xglCmdCopyMemory", (const char *) pName, sizeof ("xglCmdCopyMemory")))
+        return disp_table->CmdCopyMemory;
+    else if (!strncmp("xglCmdCopyImage", (const char *) pName, sizeof ("xglCmdCopyImage")))
+        return disp_table->CmdCopyImage;
+    else if (!strncmp("xglCmdCopyMemoryToImage", (const char *) pName, sizeof ("xglCmdCopyMemoryToImage")))
+        return disp_table->CmdCopyMemoryToImage;
+    else if (!strncmp("xglCmdCopyImageToMemory", (const char *) pName, sizeof ("xglCmdCopyImageToMemory")))
+        return disp_table->CmdCopyImageToMemory;
+    else if (!strncmp("xglCmdCloneImageData", (const char *) pName, sizeof ("xglCmdCloneImageData")))
+        return disp_table->CmdCloneImageData;
+    else if (!strncmp("xglCmdUpdateMemory", (const char *) pName, sizeof ("xglCmdUpdateMemory")))
+        return disp_table->CmdUpdateMemory;
+    else if (!strncmp("xglCmdFillMemory", (const char *) pName, sizeof ("xglCmdFillMemory")))
+        return disp_table->CmdFillMemory;
+    else if (!strncmp("xglCmdClearColorImage", (const char *) pName, sizeof ("xglCmdClearColorImage")))
+        return disp_table->CmdClearColorImage;
+    else if (!strncmp("xglCmdClearColorImageRaw", (const char *) pName, sizeof ("xglCmdClearColorImageRaw")))
+        return disp_table->CmdClearColorImageRaw;
+    else if (!strncmp("xglCmdClearDepthStencil", (const char *) pName, sizeof ("xglCmdClearDepthStencil")))
+        return disp_table->CmdClearDepthStencil;
+    else if (!strncmp("xglCmdResolveImage", (const char *) pName, sizeof ("xglCmdResolveImage")))
+        return disp_table->CmdResolveImage;
+    else if (!strncmp("xglCmdSetEvent", (const char *) pName, sizeof ("xglCmdSetEvent")))
+        return disp_table->CmdSetEvent;
+    else if (!strncmp("xglCmdResetEvent", (const char *) pName, sizeof ("xglCmdResetEvent")))
+        return disp_table->CmdResetEvent;
+    else if (!strncmp("xglCmdMemoryAtomic", (const char *) pName, sizeof ("xglCmdMemoryAtomic")))
+        return disp_table->CmdMemoryAtomic;
+    else if (!strncmp("xglCmdBeginQuery", (const char *) pName, sizeof ("xglCmdBeginQuery")))
+        return disp_table->CmdBeginQuery;
+    else if (!strncmp("xglCmdEndQuery", (const char *) pName, sizeof ("xglCmdEndQuery")))
+        return disp_table->CmdEndQuery;
+    else if (!strncmp("xglCmdResetQueryPool", (const char *) pName, sizeof ("xglCmdResetQueryPool")))
+        return disp_table->CmdResetQueryPool;
+    else if (!strncmp("xglCmdWriteTimestamp", (const char *) pName, sizeof ("xglCmdWriteTimestamp")))
+        return disp_table->CmdWriteTimestamp;
+    else if (!strncmp("xglCmdInitAtomicCounters", (const char *) pName, sizeof ("xglCmdInitAtomicCounters")))
+        return disp_table->CmdInitAtomicCounters;
+    else if (!strncmp("xglCmdLoadAtomicCounters", (const char *) pName, sizeof ("xglCmdLoadAtomicCounters")))
+        return disp_table->CmdLoadAtomicCounters;
+    else if (!strncmp("xglCmdSaveAtomicCounters", (const char *) pName, sizeof ("xglCmdSaveAtomicCounters")))
+        return disp_table->CmdSaveAtomicCounters;
+    else if (!strncmp("xglDbgSetValidationLevel", (const char *) pName, sizeof ("xglDbgSetValidationLevel")))
+        return disp_table->DbgSetValidationLevel;
+    else if (!strncmp("xglDbgRegisterMsgCallback", (const char *) pName, sizeof ("xglDbgRegisterMsgCallback")))
+        return disp_table->DbgRegisterMsgCallback;
+    else if (!strncmp("xglDbgUnregisterMsgCallback", (const char *) pName, sizeof ("xglDbgUnregisterMsgCallback")))
+        return disp_table->DbgUnregisterMsgCallback;
+    else if (!strncmp("xglDbgSetMessageFilter", (const char *) pName, sizeof ("xglDbgSetMessageFilter")))
+        return disp_table->DbgSetMessageFilter;
+    else if (!strncmp("xglDbgSetObjectTag", (const char *) pName, sizeof ("xglDbgSetObjectTag")))
+        return disp_table->DbgSetObjectTag;
+    else if (!strncmp("xglDbgSetGlobalOption", (const char *) pName, sizeof ("xglDbgSetGlobalOption")))
+        return disp_table->DbgSetGlobalOption;
+    else if (!strncmp("xglDbgSetDeviceOption", (const char *) pName, sizeof ("xglDbgSetDeviceOption")))
+        return disp_table->DbgSetDeviceOption;
+    else if (!strncmp("xglCmdDbgMarkerBegin", (const char *) pName, sizeof ("xglCmdDbgMarkerBegin")))
+        return disp_table->CmdDbgMarkerBegin;
+    else if (!strncmp("xglCmdDbgMarkerEnd", (const char *) pName, sizeof ("xglCmdDbgMarkerEnd")))
+        return disp_table->CmdDbgMarkerEnd;
+    else if (!strncmp("xglWsiX11AssociateConnection", (const char *) pName, sizeof("xglWsiX11AssociateConnection")))
+        return disp_table->WsiX11AssociateConnection;
+    else if (!strncmp("xglWsiX11GetMSC", (const char *) pName, sizeof("xglWsiX11GetMSC")))
+        return disp_table->WsiX11GetMSC;
+    else if (!strncmp("xglWsiX11CreatePresentableImage", (const char *) pName, sizeof("xglWsiX11CreatePresentableImage")))
+        return disp_table->WsiX11CreatePresentableImage;
+    else if (!strncmp("xglWsiX11QueuePresent", (const char *) pName, sizeof("xglWsiX11QueuePresent")))
+        return disp_table->WsiX11QueuePresent;
+    else  {
+        XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;
+        if (gpuw->pGPA == NULL)
+            return NULL;
+        return gpuw->pGPA(gpuw->nextObject, pName);
+    }
+}
+
 LOADER_EXPORT XGL_RESULT XGLAPI xglInitAndEnumerateGpus(const XGL_APPLICATION_INFO* pAppInfo, const XGL_ALLOC_CALLBACKS* pAllocCb, XGL_UINT maxGpus, XGL_UINT* pGpuCount, XGL_PHYSICAL_GPU* pGpus)
 {
     static pthread_once_t once = PTHREAD_ONCE_INIT;
@@ -366,6 +971,8 @@
     icd = loader.icds;
     while (icd) {
         XGL_PHYSICAL_GPU gpus[XGL_MAX_PHYSICAL_GPUS];
+        XGL_BASE_LAYER_OBJECT * wrappedGpus;
+        GetProcAddrType getProcAddr = icd->GetProcAddr;
         XGL_UINT n, max = maxGpus - count;
 
         if (max > XGL_MAX_PHYSICAL_GPUS) {
@@ -374,7 +981,18 @@
 
         res = icd->InitAndEnumerateGpus(pAppInfo, pAllocCb, max, &n, gpus);
         if (res == XGL_SUCCESS && n) {
-            memcpy(pGpus + count, gpus, sizeof(*pGpus) * n);
+            wrappedGpus = (XGL_BASE_LAYER_OBJECT*) malloc(n * sizeof(XGL_BASE_LAYER_OBJECT));
+            loader.loader_dispatch = (XGL_LAYER_DISPATCH_TABLE *) malloc(n * sizeof(XGL_LAYER_DISPATCH_TABLE));
+            for (int i = 0; i < n; i++) {
+                (wrappedGpus + i)->baseObject = gpus[i];
+                (wrappedGpus + i)->pGPA = getProcAddr; //loader.loader_dispatch + i; //getProcAddr;
+                (wrappedGpus + i)->nextObject = gpus[i];
+                memcpy(pGpus + count, &wrappedGpus, sizeof(*pGpus));
+                init_dispatch_table(loader.loader_dispatch + i, getProcAddr, wrappedGpus + i);
+                const XGL_LAYER_DISPATCH_TABLE * *disp = (const XGL_LAYER_DISPATCH_TABLE *  *) gpus[i];
+                *disp = loader.loader_dispatch + i;
+            }
+
             count += n;
 
             if (count >= maxGpus) {
@@ -385,6 +1003,10 @@
         icd = icd->next;
     }
 
+    /* get layer libraries */
+    if (!loader.layer_scaned)
+        layer_lib_scan(NULL, true, false);
+
     *pGpuCount = count;
 
     return (count > 0) ? XGL_SUCCESS : res;
diff --git a/loader/loader.h b/loader/loader.h
index b76f634..d819142 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -31,7 +31,7 @@
 #include <xgl.h>
 #include <xglDbg.h>
 #include <xglWsiX11Ext.h>
-
+#include <xglLayer.h>
 #if defined(__GNUC__) && __GNUC__ >= 4
 #  define LOADER_EXPORT __attribute__((visibility("default")))
 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
@@ -40,4 +40,6 @@
 #  define LOADER_EXPORT
 #endif
 
+extern XGL_UINT ActivateLayers(XGL_PHYSICAL_GPU *gpu);
+#define MAX_LAYER_LIBRARIES 16
 #endif /* LOADER_H */
diff --git a/xgl-generate.py b/xgl-generate.py
index 900f50c..6e790d8 100755
--- a/xgl-generate.py
+++ b/xgl-generate.py
@@ -108,36 +108,149 @@
     %s;
 };""" % ";\n    ".join(entries)
 
-    def _generate_icd_dispatch_entrypoints(self, qual=""):
+    def _generate_dispatch_entrypoints(self, qual="", unwrap=False, layer=False):
         if qual:
             qual += " "
 
         funcs = []
         for proto in self.protos:
-            if not xgl.is_dispatchable(proto):
-                continue
-
-            decl = proto.c_func(prefix="xgl", attr="XGLAPI")
-            stmt = "(*disp)->%s" % proto.c_call()
-            if proto.ret != "XGL_VOID":
-                stmt = "return " + stmt
-
-            funcs.append("%s%s\n"
-                         "{\n"
-                         "    const struct icd_dispatch_table * const *disp =\n"
-                         "        (const struct icd_dispatch_table * const *) %s;\n"
-                         "    %s;\n"
-                         "}" % (qual, decl, proto.params[0].name, stmt))
+            if not layer:
+                if not xgl.is_dispatchable(proto):
+                    continue
+                decl = proto.c_func(prefix="xgl", attr="XGLAPI")
+                stmt = "(*disp)->%s" % proto.c_call()
+                if proto.ret != "XGL_VOID":
+                    stmt = "return " + stmt
+                if proto.name == "CreateDevice" and qual == "LOADER_EXPORT ":
+                    stmt_cd = "XGL_RESULT res = " + "(*disp)->%s" % proto.c_call()
+                    funcs.append("%s%s\n"
+                             "{\n"
+                             "    ActivateLayers(&%s);\n"
+                             "    XGL_BASE_LAYER_OBJECT* wrapped_obj = (XGL_BASE_LAYER_OBJECT*)%s;\n"
+                             "    const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
+                             "            (const XGL_LAYER_DISPATCH_TABLE * const *) wrapped_obj->baseObject;\n"
+                             "    %s = wrapped_obj->nextObject;\n"
+                             "    %s;\n"
+                             "    const XGL_LAYER_DISPATCH_TABLE * *disp_dev = (const XGL_LAYER_DISPATCH_TABLE *  *) *%s;\n"
+                             "    *disp_dev = (const XGL_LAYER_DISPATCH_TABLE *) *disp;\n"
+                             "    return res;\n"
+                             "}" % (qual, decl, proto.params[0].name, proto.params[0].name, proto.params[0].name, stmt_cd, proto.params[2].name))
+                elif proto.params[0].ty != "XGL_PHYSICAL_GPU":
+                    funcs.append("%s%s\n"
+                             "{\n"
+                             "    const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
+                             "        (const XGL_LAYER_DISPATCH_TABLE * const *) %s;\n"
+                             "    %s;\n"
+                             "}" % (qual, decl, proto.params[0].name, stmt))
+                else:
+                    funcs.append("%s%s\n"
+                             "{\n"
+                             "    XGL_BASE_LAYER_OBJECT* wrapped_obj = (XGL_BASE_LAYER_OBJECT*)%s;\n"
+                             "    const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
+                             "        (const XGL_LAYER_DISPATCH_TABLE * const *) wrapped_obj->baseObject;\n"
+                             "    %s = wrapped_obj->nextObject;\n"
+                             "    %s;\n"
+                                 "}" % (qual, decl, proto.params[0].name, proto.params[0].name, stmt))
+            elif proto.name != "GetProcAddr":
+                decl = proto.c_func(prefix="xgl", attr="XGLAPI")
+                param0_name = proto.params[0].name
+                ret_val = ''
+                stmt = ''
+                if proto.ret != "XGL_VOID":
+                    ret_val = "XGL_RESULT result = "
+                    stmt = "    return result;\n"
+                if proto.params[0].ty != "XGL_PHYSICAL_GPU":
+                    funcs.append('%s%s\n'
+                             '{\n'
+                             '    %snextTable.%s;\n'
+                             '%s'
+                             '}' % (qual, decl, ret_val, proto.c_call(), stmt))
+                else:
+                    c_call = proto.c_call().replace("(" + proto.params[0].name, "((XGL_PHYSICAL_GPU)gpuw->nextObject", 1)
+                    funcs.append('%s%s\n'
+                             '{\n'
+                             '    XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) %s;\n'
+                             '    printf("At start of layered %s\\n");\n'
+                             '    pCurObj = gpuw;\n'
+                             '    pthread_once(&tabOnce, initLayerTable);\n'
+                             '    %snextTable.%s;\n'
+                             '    printf("Completed layered %s\\n");\n'
+                             '%s'
+                             '}' % (qual, decl, proto.params[0].name, proto.name, ret_val, c_call, proto.name, stmt))
 
         return "\n\n".join(funcs)
 
+    def _generate_layer_gpa_function(self, prefix="xgl"):
+        func_body = []
+        func_body.append("XGL_LAYER_EXPORT XGL_VOID* XGLAPI xglGetProcAddr(XGL_PHYSICAL_GPU gpu, const XGL_CHAR* funcName)\n"
+                         "{\n"
+                         "    XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;\n"
+                         "    if (gpu == NULL)\n"
+                         "        return NULL;\n"
+                         "    pCurObj = gpuw;\n"
+                         "    pthread_once(&tabOnce, initLayerTable);\n\n"
+                         '    if (!strncmp("xglGetProcAddr", (const char *) funcName, sizeof("xglGetProcAddr")))\n'
+                         '        return xglGetProcAddr;')
+        for name in xgl.icd_dispatch_table:
+            if name == "GetProcAddr":
+                continue
+            func_body.append('    else if (!strncmp("%s%s", (const char *) funcName, sizeof("%s%s")))\n'
+                             '        return %s%s;' % (prefix, name, prefix, name, prefix, name))
+        func_body.append("    else {\n"
+                         "        XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;\n"
+                         "        if (gpuw->pGPA == NULL)\n"
+                         "            return NULL;\n"
+                         "        return gpuw->pGPA(gpuw->nextObject, funcName);\n"
+                         "    }\n"
+                         "}\n")
+        return "\n".join(func_body)
+
+    def _generate_layer_dispatch_table(self, prefix='xgl'):
+        func_body = []
+        func_body.append('static void initLayerTable()\n'
+                         '{\n'
+                         '    GetProcAddrType fpNextGPA;\n'
+                         '    fpNextGPA = pCurObj->pGPA;\n'
+                         '    assert(fpNextGPA);\n');
+
+        for name in xgl.icd_dispatch_table:
+            func_body.append('    %sType fp%s = fpNextGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (XGL_CHAR *) "%s%s");\n'
+                             '    nextTable.%s = fp%s;' % (name, name, prefix, name, name, name))
+
+        func_body.append("}\n")
+        return "\n".join(func_body)
+
 class LoaderSubcommand(Subcommand):
     def generate_header(self):
         return "#include \"loader.h\""
 
     def generate_body(self):
-        body = [self._generate_icd_dispatch_table(),
-                self._generate_icd_dispatch_entrypoints("LOADER_EXPORT")]
+        body = [self._generate_dispatch_entrypoints("LOADER_EXPORT")]
+
+        return "\n\n".join(body)
+
+class LayerFuncsSubcommand(Subcommand):
+    def generate_header(self):
+        return '#include <xglLayer.h>\n#include "loader.h"'
+
+    def generate_body(self):
+        return self._generate_dispatch_entrypoints("static", True)
+
+class LayerDispatchSubcommand(Subcommand):
+    def generate_header(self):
+        return '#include "layer_wrappers.h"'
+
+    def generate_body(self):
+        return self._generate_layer_dispatch_table()
+
+class GenericLayerSubcommand(Subcommand):
+    def generate_header(self):
+        return '#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n#include <pthread.h>\n#include "xglLayer.h"\n\nstatic XGL_LAYER_DISPATCH_TABLE nextTable;\nstatic XGL_BASE_LAYER_OBJECT *pCurObj;\nstatic pthread_once_t tabOnce = PTHREAD_ONCE_INIT;\n'
+
+    def generate_body(self):
+        body = [self._generate_layer_dispatch_table(),
+                self._generate_dispatch_entrypoints("XGL_LAYER_EXPORT", True, True),
+                self._generate_layer_gpa_function()]
 
         return "\n\n".join(body)
 
@@ -150,7 +263,7 @@
         return "#include \"icd.h\""
 
     def generate_body(self):
-        return self._generate_icd_dispatch_entrypoints("ICD_EXPORT")
+        return self._generate_dispatch_entrypoints("ICD_EXPORT")
 
 class IcdDispatchDummyImplSubcommand(Subcommand):
     def run(self):
@@ -224,6 +337,9 @@
 def main():
     subcommands = {
             "loader": LoaderSubcommand,
+            "layer-funcs" : LayerFuncsSubcommand,
+            "layer-dispatch" : LayerDispatchSubcommand,
+            "generic-layer" : GenericLayerSubcommand,
             "icd-dispatch-table": IcdDispatchTableSubcommand,
             "icd-dispatch-entrypoints": IcdDispatchEntrypointsSubcommand,
             "icd-dispatch-dummy-impl": IcdDispatchDummyImplSubcommand,
diff --git a/xgl.py b/xgl.py
index 62ae0fb..6f2b738 100644
--- a/xgl.py
+++ b/xgl.py
@@ -87,6 +87,10 @@
 
 # XGL core API
 core = (
+    Proto("void *", "GetProcAddr",
+        (Param("XGL_PHYSICAL_GPU", "gpu"),
+         Param("const XGL_CHAR*", "pName"))),
+
     Proto("XGL_RESULT", "InitAndEnumerateGpus",
         (Param("const XGL_APPLICATION_INFO*", "pAppInfo"),
          Param("const XGL_ALLOC_CALLBACKS*", "pAllocCb"),
@@ -726,6 +730,7 @@
 # XXX figure out the real order
 # XXX this is not extensible
 icd_dispatch_table = (
+    "GetProcAddr",
     "InitAndEnumerateGpus",
     "GetGpuInfo",
     "CreateDevice",
@@ -847,14 +852,18 @@
     "WsiX11QueuePresent",
 )
 
+def is_name_dispatchable(name):
+    return name not in (
+        "GetProcAddr",
+        "InitAndEnumerateGpus",
+        "DbgRegisterMsgCallback",
+        "DbgUnregisterMsgCallback",
+        "DbgSetGlobalOption")
+
 def is_dispatchable(proto):
     """Return true if the prototype is dispatchable.
 
     That is, return true when the prototype takes a XGL_PHYSICAL_GPU or
     XGL_BASE_OBJECT.
     """
-    return proto.name not in (
-        "InitAndEnumerateGpus",
-        "DbgRegisterMsgCallback",
-        "DbgUnregisterMsgCallback",
-        "DbgSetGlobalOption")
+    return is_name_dispatchable(proto.name)