layers: Add memory management to DrawState

Added code in DrawState to free memory allocations
Updated DrawState Layout to save full CreateInfo tree
diff --git a/layers/draw_state.c b/layers/draw_state.c
index 615eaa4..4dc377c 100644
--- a/layers/draw_state.c
+++ b/layers/draw_state.c
@@ -307,6 +307,65 @@
     }
     loader_platform_thread_unlock_mutex(&globalLock);
 }
+// Free all allocated nodes for Dynamic State objs
+static void freeDynamicState()
+{
+    for (uint32_t i = 0; i < XGL_NUM_STATE_BIND_POINT; i++) {
+        DYNAMIC_STATE_NODE* pStateNode = g_pDynamicStateHead[i];
+        DYNAMIC_STATE_NODE* pFreeMe = pStateNode;
+        while (pStateNode) {
+            pFreeMe = pStateNode;
+            pStateNode = pStateNode->pNext;
+            assert(pFreeMe->pCreateInfo);
+            if (XGL_STRUCTURE_TYPE_DYNAMIC_VP_STATE_CREATE_INFO == pFreeMe->pCreateInfo->sType) {
+                XGL_DYNAMIC_VP_STATE_CREATE_INFO* pVPCI = (XGL_DYNAMIC_VP_STATE_CREATE_INFO*)pFreeMe->pCreateInfo;
+                if (pVPCI->pViewports) {
+                    void** ppToFree = (void**)&pVPCI->pViewports;
+                    free(*ppToFree);
+                }
+                if (pVPCI->pScissors) {
+                    void** ppToFree = (void**)&pVPCI->pScissors;
+                    free(*ppToFree);
+                }
+            }
+            free(pFreeMe->pCreateInfo);
+            free(pFreeMe);
+        }
+    }
+}
+// Free all sampler nodes
+static void freeSamplers()
+{
+    SAMPLER_NODE* pSampler = g_pSamplerHead;
+    SAMPLER_NODE* pFreeMe = pSampler;
+    while (pSampler) {
+        pFreeMe = pSampler;
+        pSampler = pSampler->pNext;
+        free(pFreeMe);
+    }
+}
+// Free all image nodes
+static void freeImages()
+{
+    IMAGE_NODE* pImage = g_pImageHead;
+    IMAGE_NODE* pFreeMe = pImage;
+    while (pImage) {
+        pFreeMe = pImage;
+        pImage = pImage->pNext;
+        free(pFreeMe);
+    }
+}
+// Free all buffer nodes
+static void freeBuffers()
+{
+    BUFFER_NODE* pBuffer = g_pBufferHead;
+    BUFFER_NODE* pFreeMe = pBuffer;
+    while (pBuffer) {
+        pFreeMe = pBuffer;
+        pBuffer = pBuffer->pNext;
+        free(pFreeMe);
+    }
+}
 static GLOBAL_CB_NODE* getCBNode(XGL_CMD_BUFFER cb);
 // Print the last bound dynamic state
 static void printDynamicState(const XGL_CMD_BUFFER cb)
@@ -417,7 +476,36 @@
         pTrav = (GENERIC_HEADER*)pTrav->pNext;
     }
 }
-
+// Free the Pipeline nodes
+static void freePipelines()
+{
+    PIPELINE_NODE* pPipeline = g_pPipelineHead;
+    PIPELINE_NODE* pFreeMe = pPipeline;
+    while (pPipeline) {
+        pFreeMe = pPipeline;
+        GENERIC_HEADER* pShadowTrav = (GENERIC_HEADER*)pPipeline->pCreateTree;
+        GENERIC_HEADER* pShadowFree = pShadowTrav;
+        while (pShadowTrav) {
+            pShadowFree = pShadowTrav;
+            pShadowTrav = (GENERIC_HEADER*)pShadowTrav->pNext;
+            if (XGL_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO == pShadowFree->sType) {
+                // Free the vtx data shadowed directly into pPipeline node
+                if (pFreeMe->pVertexBindingDescriptions)
+                    free(pFreeMe->pVertexBindingDescriptions);
+                if (pFreeMe->pVertexAttributeDescriptions)
+                    free(pFreeMe->pVertexAttributeDescriptions);
+            }
+            else if (XGL_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO == pShadowFree->sType) {
+                // Free attachment data shadowed into pPipeline node
+                if (pFreeMe->pAttachments)
+                    free(pFreeMe->pAttachments);
+            }
+            free(pShadowFree);
+        }
+        pPipeline = pPipeline->pNext;
+        free(pFreeMe);
+    }
+}
 // Block of code at start here specifically for managing/tracking DSs
 
 // ptr to HEAD of LL of DS Regions
@@ -440,7 +528,6 @@
     loader_platform_thread_unlock_mutex(&globalLock);
     return NULL;
 }
-
 // Return Set node ptr for specified set or else NULL
 static SET_NODE* getSetNode(XGL_DESCRIPTOR_SET set)
 {
@@ -531,10 +618,12 @@
 }
 
 // Verify that the descriptor type in the update struct matches what's expected by the layout
-static bool32_t validateUpdateType(GENERIC_HEADER* pUpdateStruct, XGL_DESCRIPTOR_TYPE type)
+static bool32_t validateUpdateType(GENERIC_HEADER* pUpdateStruct, const LAYOUT_NODE* pLayout)//XGL_DESCRIPTOR_TYPE type)
 {
     // First get actual type of update
     XGL_DESCRIPTOR_TYPE actualType;
+    uint32_t i = 0;
+    uint32_t bound = getUpdateUpperBound(pUpdateStruct);
     switch (pUpdateStruct->sType)
     {
         case XGL_STRUCTURE_TYPE_UPDATE_SAMPLERS:
@@ -556,9 +645,11 @@
             // TODO : Flag specific error for this case
             return 0;
     }
-    if (actualType == type)
-        return 1;
-    return 0;
+    for (i = ((XGL_UPDATE_SAMPLERS*)pUpdateStruct)->index; i < bound; i++) {
+        if (pLayout->pTypes[i] != actualType)
+            return 0;
+    }
+    return 1;
 }
 
 // Verify that update region for this update does not exceed max layout index for this type
@@ -657,19 +748,21 @@
             layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, ds, 0, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", str);
         }
         else {
-            pLayoutCI = (XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO*)pLayout->pCreateInfoList;
-            // Now verify that update is of the right type
-            if (!validateUpdateType(pUpdates, pLayoutCI->descriptorType)) {
-                char str[1024];
-                sprintf(str, "Descriptor update type of %s does not match overlapping layout type of %s!", string_XGL_STRUCTURE_TYPE(pUpdates->sType), string_XGL_DESCRIPTOR_TYPE(pLayoutCI->descriptorType));
-                layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, ds, 0, DRAWSTATE_DESCRIPTOR_TYPE_MISMATCH, "DS", str);
+            // Next verify that update is correct size
+            if (!validateUpdateSize(pUpdates, pLayout->endIndex)) {
+                char str[48*1024]; // TODO : Keep count of layout CI structs and size this string dynamically based on that count
+                char* pDSstr = xgl_print_xgl_descriptor_set_layout_create_info(pLayoutCI, "{DS}    ");
+                pLayoutCI = (XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO*)pLayout->pCreateInfoList;
+                sprintf(str, "Descriptor update type of %s is out of bounds for matching layout w/ CI:\n%s!", string_XGL_STRUCTURE_TYPE(pUpdates->sType), pDSstr);
+                layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, ds, 0, DRAWSTATE_DESCRIPTOR_UPDATE_OUT_OF_BOUNDS, "DS", str);
+                free(pDSstr);
             }
             else { // TODO : should we skip update on a type mismatch or force it?
-                // Next verify that update is correct size
-                if (!validateUpdateSize(pUpdates, pLayout->endIndex)) {
+                // We have the right layout section, now verify that update is of the right type
+                if (!validateUpdateType(pUpdates, pLayout)) {
                     char str[1024];
-                    sprintf(str, "Descriptor update type of %s is out of bounds for matching layout w/ CI:\n%s!", string_XGL_STRUCTURE_TYPE(pUpdates->sType), xgl_print_xgl_descriptor_set_layout_create_info(pLayoutCI, "{DS}    "));
-                    layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, ds, 0, DRAWSTATE_DESCRIPTOR_UPDATE_OUT_OF_BOUNDS, "DS", str);
+                    sprintf(str, "Descriptor update type of %s does not match overlapping layout type!", string_XGL_STRUCTURE_TYPE(pUpdates->sType));
+                    layerCbMsg(XGL_DBG_MSG_ERROR, XGL_VALIDATION_LEVEL_0, ds, 0, DRAWSTATE_DESCRIPTOR_TYPE_MISMATCH, "DS", str);
                 }
                 else {
                     // Finally perform the update
@@ -706,35 +799,102 @@
     }
 }
 // Free a shadowed update node
-static void freeShadowUpdateNode(GENERIC_HEADER* pUpdate)
+static void freeShadowUpdateTree(GENERIC_HEADER* pUpdate)
 {
-    switch (pUpdate->sType)
-    {
-        case XGL_STRUCTURE_TYPE_UPDATE_SAMPLERS:
-            free((XGL_SAMPLER*)((XGL_UPDATE_SAMPLERS*)pUpdate)->pSamplers);
-            free(pUpdate);
-            break;
-        case XGL_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES:
-            for (uint32_t i = 0; i < ((XGL_UPDATE_SAMPLER_TEXTURES*)pUpdate)->count; i++) {
-                free((XGL_IMAGE_VIEW_ATTACH_INFO*)(((XGL_UPDATE_SAMPLER_TEXTURES*)pUpdate)->pSamplerImageViews[i].pImageView));
-            }
-            free((XGL_SAMPLER_IMAGE_VIEW_INFO*)((XGL_UPDATE_SAMPLER_TEXTURES*)pUpdate)->pSamplerImageViews);
-            free(pUpdate);
-            break;
-        case XGL_STRUCTURE_TYPE_UPDATE_IMAGES:
-            free((XGL_IMAGE_VIEW_ATTACH_INFO*)((XGL_UPDATE_IMAGES*)pUpdate)->pImageViews);
-            free(pUpdate);
-            break;
-        case XGL_STRUCTURE_TYPE_UPDATE_BUFFERS:
-            free((XGL_BUFFER_VIEW_ATTACH_INFO*)((XGL_UPDATE_BUFFERS*)pUpdate)->pBufferViews);
-            free(pUpdate);
-            break;
-        case XGL_STRUCTURE_TYPE_UPDATE_AS_COPY:
-            free(pUpdate);
-            break;
-        default:
-            // TODO : Flag specific error for this case
-            break;
+    GENERIC_HEADER* pShadowUpdate = pUpdate;
+    GENERIC_HEADER* pFreeUpdate = pShadowUpdate;
+    while(pShadowUpdate) {
+        pFreeUpdate = pShadowUpdate;
+        pShadowUpdate = (GENERIC_HEADER*)pShadowUpdate->pNext;
+        uint32_t index = 0;
+        XGL_UPDATE_SAMPLERS* pUS = NULL;
+        XGL_UPDATE_SAMPLER_TEXTURES* pUST = NULL;
+        XGL_UPDATE_IMAGES* pUI = NULL;
+        XGL_UPDATE_BUFFERS* pUB = NULL;
+        void** ppToFree = NULL;
+        switch (pFreeUpdate->sType)
+        {
+            case XGL_STRUCTURE_TYPE_UPDATE_SAMPLERS:
+                pUS = (XGL_UPDATE_SAMPLERS*)pFreeUpdate;
+                if (pUS->pSamplers) {
+                    ppToFree = (void**)&pUS->pSamplers;
+                    free(*ppToFree);
+                }
+                break;
+            case XGL_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES:
+                pUST = (XGL_UPDATE_SAMPLER_TEXTURES*)pFreeUpdate;
+                for (index = 0; index < pUST->count; index++) {
+                    if (pUST->pSamplerImageViews[index].pImageView) {
+                        ppToFree = (void**)&pUST->pSamplerImageViews[index].pImageView;
+                        free(*ppToFree);
+                    }
+                }
+                ppToFree = (void**)&pUST->pSamplerImageViews;
+                free(*ppToFree);
+                break;
+            case XGL_STRUCTURE_TYPE_UPDATE_IMAGES:
+                pUI = (XGL_UPDATE_IMAGES*)pFreeUpdate;
+                if (pUI->pImageViews) {
+                    ppToFree = (void**)&pUI->pImageViews;
+                    free(*ppToFree);
+                }
+                break;
+            case XGL_STRUCTURE_TYPE_UPDATE_BUFFERS:
+                pUB = (XGL_UPDATE_BUFFERS*)pFreeUpdate;
+                if (pUB->pBufferViews) {
+                    ppToFree = (void**)&pUB->pBufferViews;
+                    free(*ppToFree);
+                }
+                break;
+            case XGL_STRUCTURE_TYPE_UPDATE_AS_COPY:
+                break;
+            default:
+                assert(0);
+                break;
+        }
+        free(pFreeUpdate);
+    }
+}
+// Free all DS Regions including their Sets & related sub-structs
+static void freeRegions()
+{
+    REGION_NODE* pRegion = g_pRegionHead;
+    REGION_NODE* pFreeMe = pRegion;
+    while (pRegion) {
+        pFreeMe = pRegion;
+        SET_NODE* pSet = pRegion->pSets;
+        SET_NODE* pFreeSet = pSet;
+        while (pSet) {
+            pFreeSet = pSet;
+            pSet = pSet->pNext;
+            // Freeing layouts handled in freeLayouts() function
+            // Free Update shadow struct tree
+            freeShadowUpdateTree(pFreeSet->pUpdateStructs);
+            free(pFreeSet);
+        }
+        pRegion = pRegion->pNext;
+        if (pFreeMe->createInfo.pTypeCount) {
+            void** ppToFree = (void**)&pFreeMe->createInfo.pTypeCount;
+            free(*ppToFree);
+        }
+        free(pFreeMe);
+    }
+}
+// WARN : Once freeLayouts() called, any layout ptrs in Region/Set data structure will be invalid
+static void freeLayouts()
+{
+    LAYOUT_NODE* pLayout = g_pLayoutHead;
+    LAYOUT_NODE* pFreeLayout = pLayout;
+    while (pLayout) {
+        pFreeLayout = pLayout;
+        GENERIC_HEADER* pTrav = (GENERIC_HEADER*)pLayout->pCreateInfoList;
+        while (pTrav) {
+            void* pToFree = (void*)pTrav;
+            pTrav = (GENERIC_HEADER*)pTrav->pNext;
+            free(pToFree);
+        }
+        pLayout = pLayout->pNext;
+        free(pFreeLayout);
     }
 }
 // Currently clearing a set is removing all previous updates to that set
@@ -746,13 +906,7 @@
         // TODO : Return error
     }
     else {
-        GENERIC_HEADER* pUpdate = pSet->pUpdateStructs;
-        GENERIC_HEADER* pFreeMe = pUpdate;
-        while (pUpdate) {
-            pFreeMe = pUpdate;
-            pUpdate = (GENERIC_HEADER*)pUpdate->pNext;
-            freeShadowUpdateNode(pFreeMe);
-        }
+        freeShadowUpdateTree(pSet->pUpdateStructs);
     }
 }
 
@@ -789,7 +943,24 @@
     loader_platform_thread_unlock_mutex(&globalLock);
     return NULL;
 }
-
+// Free all CB Nodes
+static void freeCmdBuffers()
+{
+    GLOBAL_CB_NODE* pCB = g_pCmdBufferHead;
+    GLOBAL_CB_NODE* pFreeMe = pCB;
+    while (pCB) {
+        pFreeMe = pCB;
+        CMD_NODE* pCmd = pCB->pCmds;
+        CMD_NODE* pFreeCmd = pCmd;
+        while (pCmd) {
+            pFreeCmd = pCmd;
+            pCmd = pCmd->pNext;
+            free(pFreeCmd);
+        }
+        pCB = pCB->pNextGlobalCBNode;
+        free(pFreeMe);
+    }
+}
 static void addCmd(GLOBAL_CB_NODE* pCB, const CMD_TYPE cmd)
 {
     CMD_NODE* pCmd = (CMD_NODE*)malloc(sizeof(CMD_NODE));
@@ -876,6 +1047,7 @@
         else {
             char* pipeStr = xgl_print_xgl_graphics_pipeline_create_info(pPipeTrav->pCreateTree, "{DS}");
             layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_NONE, "DS", pipeStr);
+            free(pipeStr);
         }
     }
 }
@@ -889,7 +1061,9 @@
         char tmp_str[1024];
         fprintf(pOutFile, "subgraph cluster_DescriptorRegion\n{\nlabel=\"Descriptor Region\"\n");
         sprintf(tmp_str, "Region (%p)", pRegion->region);
-        fprintf(pOutFile, "%s", xgl_gv_print_xgl_descriptor_region_create_info(&pRegion->createInfo, tmp_str));
+        char* pGVstr = xgl_gv_print_xgl_descriptor_region_create_info(&pRegion->createInfo, tmp_str);
+        fprintf(pOutFile, "%s", pGVstr);
+        free(pGVstr);
         fprintf(pOutFile, "subgraph cluster_DescriptorSet\n{\nlabel=\"Descriptor Set (%p)\"\n", pSet->set);
         sprintf(tmp_str, "Descriptor Set (%p)", pSet->set);
         LAYOUT_NODE* pLayout = pSet->pLayouts;
@@ -897,14 +1071,18 @@
         while (pLayout) {
             ++layout_index;
             sprintf(tmp_str, "LAYOUT%u", layout_index);
-            fprintf(pOutFile, "%s", xgl_gv_print_xgl_descriptor_set_layout_create_info(pLayout->pCreateInfoList, tmp_str));
+            pGVstr = xgl_gv_print_xgl_descriptor_set_layout_create_info(pLayout->pCreateInfoList, tmp_str);
+            fprintf(pOutFile, "%s", pGVstr);
+            free(pGVstr);
             pLayout = pLayout->pNext;
             if (pLayout) {
                 fprintf(pOutFile, "\"%s\" -> \"LAYOUT%u\" [];\n", tmp_str, layout_index+1);
             }
         }
         if (pSet->pUpdateStructs) {
-            fprintf(pOutFile, "%s", dynamic_gv_display(pSet->pUpdateStructs, "Descriptor Updates"));
+            pGVstr = dynamic_gv_display(pSet->pUpdateStructs, "Descriptor Updates");
+            fprintf(pOutFile, "%s", pGVstr);
+            free(pGVstr);
         }
         fprintf(pOutFile, "}\n");
         fprintf(pOutFile, "}\n");
@@ -923,14 +1101,19 @@
             pOutFile = fopen(outFileName, "w");
             fprintf(pOutFile, "digraph g {\ngraph [\nrankdir = \"TB\"\n];\nnode [\nfontsize = \"16\"\nshape = \"plaintext\"\n];\nedge [\n];\n");
             fprintf(pOutFile, "subgraph cluster_dynamicState\n{\nlabel=\"Dynamic State\"\n");
+            char* pGVstr = NULL;
             for (uint32_t i = 0; i < XGL_NUM_STATE_BIND_POINT; i++) {
                 if (pCB->lastBoundDynamicState[i]) {
-                    fprintf(pOutFile, "%s", dynamic_gv_display(pCB->lastBoundDynamicState[i]->pCreateInfo, string_XGL_STATE_BIND_POINT(i)));
+                    pGVstr = dynamic_gv_display(pCB->lastBoundDynamicState[i]->pCreateInfo, string_XGL_STATE_BIND_POINT(i));
+                    fprintf(pOutFile, "%s", pGVstr);
+                    free(pGVstr);
                 }
             }
             fprintf(pOutFile, "}\n"); // close dynamicState subgraph
             fprintf(pOutFile, "subgraph cluster_PipelineStateObject\n{\nlabel=\"Pipeline State Object\"\n");
-            fprintf(pOutFile, "%s", xgl_gv_print_xgl_graphics_pipeline_create_info(pPipeTrav->pCreateTree, "PSO HEAD"));
+            pGVstr = xgl_gv_print_xgl_graphics_pipeline_create_info(pPipeTrav->pCreateTree, "PSO HEAD");
+            fprintf(pOutFile, "%s", pGVstr);
+            free(pGVstr);
             fprintf(pOutFile, "}\n");
             dsDumpDot(cb, pOutFile);
             fprintf(pOutFile, "}\n"); // close main graph "g"
@@ -979,8 +1162,10 @@
         // Print out region details
         sprintf(tmp_str, "Details for region %p.", (void*)pRegion->region);
         layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_NONE, "DS", tmp_str);
-        sprintf(ds_config_str, "%s", xgl_print_xgl_descriptor_region_create_info(&pRegion->createInfo, " "));
+        char* pRegionStr = xgl_print_xgl_descriptor_region_create_info(&pRegion->createInfo, " ");
+        sprintf(ds_config_str, "%s", pRegionStr);
         layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_NONE, "DS", ds_config_str);
+        free(pRegionStr);
         // Print out set details
         char prefix[10];
         uint32_t index = 0;
@@ -992,8 +1177,10 @@
             sprintf(tmp_str, "Layout #%u, (object %p) for DS %p.", index+1, (void*)pLayout->layout, (void*)pSet->set);
             layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_NONE, "DS", tmp_str);
             sprintf(prefix, "  [L%u] ", index);
-            sprintf(ds_config_str, "%s", xgl_print_xgl_descriptor_set_layout_create_info(&pLayout->pCreateInfoList[0], prefix));
+            char* pDSLstr = xgl_print_xgl_descriptor_set_layout_create_info(&pLayout->pCreateInfoList[0], prefix);
+            sprintf(ds_config_str, "%s", pDSLstr);
             layerCbMsg(XGL_DBG_MSG_UNKNOWN, XGL_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_NONE, "DS", ds_config_str);
+            free(pDSLstr);
             pLayout = pLayout->pPriorSetLayout;
             index++;
         }
@@ -1142,6 +1329,17 @@
 
 XGL_LAYER_EXPORT XGL_RESULT XGLAPI xglDestroyDevice(XGL_DEVICE device)
 {
+    // Free all the memory
+    loader_platform_thread_lock_mutex(&globalLock);
+    freePipelines();
+    freeSamplers();
+    freeImages();
+    freeBuffers();
+    freeCmdBuffers();
+    freeDynamicState();
+    freeRegions();
+    freeLayouts();
+    loader_platform_thread_unlock_mutex(&globalLock);
     XGL_RESULT result = nextTable.DestroyDevice(device);
     return result;
 }
@@ -1543,16 +1741,39 @@
         // TODO : API Currently missing a count here that we should multiply by struct size
         pNewNode->pCreateInfoList = (XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO*)malloc(sizeof(XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO));
         memset((void*)pNewNode->pCreateInfoList, 0, sizeof(XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO));
-        if (pSetLayoutInfoList)
+        void* pCITrav = NULL;
+        uint32_t totalCount = 0;
+        if (pSetLayoutInfoList) {
             memcpy((void*)pNewNode->pCreateInfoList, pSetLayoutInfoList, sizeof(XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO));
+            pCITrav = (void*)pSetLayoutInfoList->pNext;
+            totalCount = pSetLayoutInfoList->count;
+        }
+        void** ppNext = (void**)&pNewNode->pCreateInfoList->pNext;
+        while (pCITrav) {
+            totalCount += ((XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO*)pCITrav)->count;
+            *ppNext = (void*)malloc(sizeof(XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO));
+            memcpy((void*)*ppNext, pCITrav, sizeof(XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO));
+            pCITrav = (void*)((XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO*)pCITrav)->pNext;
+            *ppNext = (void*)((XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO*)*ppNext)->pNext;
+        }
+        if (totalCount > 0) {
+            pNewNode->pTypes = (XGL_DESCRIPTOR_TYPE*)malloc(totalCount*sizeof(XGL_DESCRIPTOR_TYPE));
+            XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO* pLCI = (XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO*)pSetLayoutInfoList;
+            while (pLCI) {
+                for (uint32_t i = 0; i < pLCI->count; i++) {
+                    pNewNode->pTypes[i] = pLCI->descriptorType;
+                }
+                pLCI = (XGL_DESCRIPTOR_SET_LAYOUT_CREATE_INFO*)pLCI->pNext;
+            }
+        }
         pNewNode->layout = *pSetLayout;
         pNewNode->stageFlags = stageFlags;
-        uint32_t i = XGL_SHADER_STAGE_COMPUTE;
+        uint32_t i = (XGL_SHADER_STAGE_FLAGS_ALL == stageFlags) ? 0 : XGL_SHADER_STAGE_COMPUTE;
         for (uint32_t stage = XGL_SHADER_STAGE_FLAGS_COMPUTE_BIT; stage > 0; stage >>= 1) {
             assert(i < XGL_NUM_SHADER_STAGE);
             if (stage & stageFlags)
                 pNewNode->shaderStageBindPoints[i] = pSetBindPoints[i];
-            i--;
+            i = (i == 0) ? 0 : (i-1);
         }
         pNewNode->startIndex = 0;
         LAYOUT_NODE* pPriorNode = getLayoutNode(priorSetLayout);
@@ -1566,7 +1787,7 @@
             // Get count for prior layout
             pNewNode->startIndex = pPriorNode->endIndex + 1;
         }
-        pNewNode->endIndex = pNewNode->startIndex + pNewNode->pCreateInfoList[0].count - 1;
+        pNewNode->endIndex = pNewNode->startIndex + totalCount - 1;
         assert(pNewNode->endIndex >= pNewNode->startIndex);
         pNewNode->pPriorSetLayout = pPriorNode;
         // Put new node at Head of global Layer list
@@ -1653,9 +1874,11 @@
             XGL_DESCRIPTOR_REGION_CREATE_INFO* pCI = (XGL_DESCRIPTOR_REGION_CREATE_INFO*)&pNewNode->createInfo;
             memcpy((void*)pCI, pCreateInfo, sizeof(XGL_DESCRIPTOR_REGION_CREATE_INFO));
             size_t typeCountSize = pNewNode->createInfo.count * sizeof(XGL_DESCRIPTOR_TYPE_COUNT);
-            XGL_DESCRIPTOR_TYPE_COUNT** ppTypeCount = (XGL_DESCRIPTOR_TYPE_COUNT**)&pNewNode->createInfo.pTypeCount;
-            *ppTypeCount = (XGL_DESCRIPTOR_TYPE_COUNT*)malloc(typeCountSize);
-            memcpy((void*)*ppTypeCount, pCreateInfo->pTypeCount, typeCountSize);
+            if (typeCountSize) {
+                XGL_DESCRIPTOR_TYPE_COUNT** ppTypeCount = (XGL_DESCRIPTOR_TYPE_COUNT**)&pNewNode->createInfo.pTypeCount;
+                *ppTypeCount = (XGL_DESCRIPTOR_TYPE_COUNT*)malloc(typeCountSize);
+                memcpy((void*)*ppTypeCount, pCreateInfo->pTypeCount, typeCountSize);
+            }
             pNewNode->regionUsage  = regionUsage;
             pNewNode->updateActive = 0;
             pNewNode->maxSets      = maxSets;