vulkan.h: V104 -- Unify compute/graphics pipeline shader passing semantics, Bug# 13800
diff --git a/include/vulkan.h b/include/vulkan.h
index 417ca94..cdea6f3 100644
--- a/include/vulkan.h
+++ b/include/vulkan.h
@@ -33,7 +33,7 @@
 #include "vk_platform.h"
 
 // Vulkan API version supported by this file
-#define VK_API_VERSION VK_MAKE_VERSION(0, 103, 0)
+#define VK_API_VERSION VK_MAKE_VERSION(0, 104, 0)
 
 #ifdef __cplusplus
 extern "C"
@@ -810,7 +810,7 @@
     VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO                = 23,
     VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO     = 24,
     VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO         = 25,
-    VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO     = 26,
+    VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 26,
     VK_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO         = 27,
     VK_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO       = 28,
     VK_STRUCTURE_TYPE_PIPELINE_VP_STATE_CREATE_INFO         = 29,
@@ -1688,20 +1688,22 @@
     const void*                                 pData;
 } VkSpecializationInfo;
 
-typedef struct VkPipelineShader_
+typedef struct VkPipelineShaderStageCreateInfo_
 {
+    VkStructureType                             sType;          // Must be VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO
+    const void*                                 pNext;          // Pointer to next structure
     VkShaderStage                               stage;
     VkShader                                    shader;
     uint32_t                                    linkConstBufferCount;
     const VkLinkConstBuffer*                    pLinkConstBufferInfo;
     const VkSpecializationInfo*                 pSpecializationInfo;
-} VkPipelineShader;
+} VkPipelineShaderStageCreateInfo;
 
 typedef struct VkComputePipelineCreateInfo_
 {
     VkStructureType                             sType;          // Must be VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO
     const void*                                 pNext;          // Pointer to next structure
-    VkPipelineShader                            cs;
+    VkPipelineShaderStageCreateInfo             cs;
     VkPipelineCreateFlags                       flags;          // Pipeline creation flags
     VkPipelineLayout                            layout;         // Interface layout of the pipeline
 } VkComputePipelineCreateInfo;
@@ -1724,9 +1726,9 @@
     uint32_t                                    offsetInBytes;  // Offset of first element in bytes from base of vertex
 } VkVertexInputAttributeDescription;
 
-typedef struct VkPipelineVertexInputCreateInfo_
+typedef struct VkPipelineVertexInputStateCreateInfo_
 {
-    VkStructureType                             sType;          // Should be VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO
+    VkStructureType                             sType;          // Should be VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO
     const void*                                 pNext;          // Pointer to next structure
 
     uint32_t                                    bindingCount;   // number of bindings
@@ -1734,7 +1736,7 @@
 
     uint32_t                                    attributeCount; // number of attributes
     const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
-} VkPipelineVertexInputCreateInfo;
+} VkPipelineVertexInputStateCreateInfo;
 
 typedef struct VkPipelineIaStateCreateInfo_
 {
@@ -1832,17 +1834,20 @@
     VkStencilOpState                            back;
 } VkPipelineDsStateCreateInfo;
 
-typedef struct VkPipelineShaderStageCreateInfo_
-{
-    VkStructureType                             sType;      // Must be VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO
-    const void*                                 pNext;      // Pointer to next structure
-    VkPipelineShader                            shader;
-} VkPipelineShaderStageCreateInfo;
-
 typedef struct VkGraphicsPipelineCreateInfo_
 {
     VkStructureType                             sType;      // Must be VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO
     const void*                                 pNext;      // Pointer to next structure
+    uint32_t                                    stageCount;
+    const VkPipelineShaderStageCreateInfo*      pStages;    // One entry for each active shader stage
+    const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
+    const VkPipelineIaStateCreateInfo*          pIaState;
+    const VkPipelineTessStateCreateInfo*        pTessState;
+    const VkPipelineVpStateCreateInfo*          pVpState;
+    const VkPipelineRsStateCreateInfo*          pRsState;
+    const VkPipelineMsStateCreateInfo*          pMsState;
+    const VkPipelineDsStateCreateInfo*          pDsState;
+    const VkPipelineCbStateCreateInfo*          pCbState;
     VkPipelineCreateFlags                       flags;      // Pipeline creation flags
     VkPipelineLayout                            layout;     // Interface layout of the pipeline
 } VkGraphicsPipelineCreateInfo;
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index a74af76..992c85d 100644
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -487,135 +487,122 @@
     } else {
         memset((void*)pPipeline, 0, sizeof(PIPELINE_NODE));
     }
-    // First init create info, we'll shadow the structs as we go down the tree
+    // First init create info
     // TODO : Validate that no create info is incorrectly replicated
     memcpy(&pPipeline->graphicsPipelineCI, pCreateInfo, sizeof(VkGraphicsPipelineCreateInfo));
-    GENERIC_HEADER* pTrav = (GENERIC_HEADER*)pCreateInfo->pNext;
-    GENERIC_HEADER* pPrev = (GENERIC_HEADER*)&pPipeline->graphicsPipelineCI; // Hold prev ptr to tie chain of structs together
+
     size_t bufferSize = 0;
-    VkPipelineVertexInputCreateInfo* pVICI = NULL;
-    VkPipelineCbStateCreateInfo*     pCBCI = NULL;
-    VkPipelineShaderStageCreateInfo* pTmpPSSCI = NULL;
-    while (pTrav) {
-        switch (pTrav->sType) {
-            case VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO:
-                pTmpPSSCI = (VkPipelineShaderStageCreateInfo*)pTrav;
-                switch (pTmpPSSCI->shader.stage) {
-                    case VK_SHADER_STAGE_VERTEX:
-                        pPrev->pNext = &pPipeline->vsCI;
-                        pPrev = (GENERIC_HEADER*)&pPipeline->vsCI;
-                        memcpy(&pPipeline->vsCI, pTmpPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
-                        pPipeline->active_shaders |= VK_SHADER_STAGE_VERTEX_BIT;
-                        break;
-                    case VK_SHADER_STAGE_TESS_CONTROL:
-                        pPrev->pNext = &pPipeline->tcsCI;
-                        pPrev = (GENERIC_HEADER*)&pPipeline->tcsCI;
-                        memcpy(&pPipeline->tcsCI, pTmpPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
-                        pPipeline->active_shaders |= VK_SHADER_STAGE_TESS_CONTROL_BIT;
-                        break;
-                    case VK_SHADER_STAGE_TESS_EVALUATION:
-                        pPrev->pNext = &pPipeline->tesCI;
-                        pPrev = (GENERIC_HEADER*)&pPipeline->tesCI;
-                        memcpy(&pPipeline->tesCI, pTmpPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
-                        pPipeline->active_shaders |= VK_SHADER_STAGE_TESS_EVALUATION_BIT;
-                        break;
-                    case VK_SHADER_STAGE_GEOMETRY:
-                        pPrev->pNext = &pPipeline->gsCI;
-                        pPrev = (GENERIC_HEADER*)&pPipeline->gsCI;
-                        memcpy(&pPipeline->gsCI, pTmpPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
-                        pPipeline->active_shaders |= VK_SHADER_STAGE_GEOMETRY_BIT;
-                        break;
-                    case VK_SHADER_STAGE_FRAGMENT:
-                        pPrev->pNext = &pPipeline->fsCI;
-                        pPrev = (GENERIC_HEADER*)&pPipeline->fsCI;
-                        memcpy(&pPipeline->fsCI, pTmpPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
-                        pPipeline->active_shaders |= VK_SHADER_STAGE_FRAGMENT_BIT;
-                        break;
-                    case VK_SHADER_STAGE_COMPUTE:
-                        // TODO : Flag error, CS is specified through VkComputePipelineCreateInfo
-                        pPipeline->active_shaders |= VK_SHADER_STAGE_COMPUTE_BIT;
-                        break;
-                    default:
-                        // TODO : Flag error
-                        break;
-                }
+    const VkPipelineVertexInputStateCreateInfo* pVICI = NULL;
+    const VkPipelineCbStateCreateInfo*          pCBCI = NULL;
+
+    for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) {
+        const VkPipelineShaderStageCreateInfo *pPSSCI = &pCreateInfo->pStages[i];
+
+        switch (pPSSCI->stage) {
+            case VK_SHADER_STAGE_VERTEX:
+                memcpy(&pPipeline->vsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
+                pPipeline->active_shaders |= VK_SHADER_STAGE_VERTEX_BIT;
                 break;
-            case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO:
-                pPrev->pNext = &pPipeline->vertexInputCI;
-                pPrev = (GENERIC_HEADER*)&pPipeline->vertexInputCI;
-                memcpy((void*)&pPipeline->vertexInputCI, pTrav, sizeof(VkPipelineVertexInputCreateInfo));
-                // Copy embedded ptrs
-                pVICI = (VkPipelineVertexInputCreateInfo*)pTrav;
-                pPipeline->vtxBindingCount = pVICI->bindingCount;
-                if (pPipeline->vtxBindingCount) {
-                    pPipeline->pVertexBindingDescriptions = new VkVertexInputBindingDescription[pPipeline->vtxBindingCount];
-                    bufferSize = pPipeline->vtxBindingCount * sizeof(VkVertexInputBindingDescription);
-                    memcpy((void*)pPipeline->pVertexBindingDescriptions, ((VkPipelineVertexInputCreateInfo*)pTrav)->pVertexBindingDescriptions, bufferSize);
-                }
-                pPipeline->vtxAttributeCount = pVICI->attributeCount;
-                if (pPipeline->vtxAttributeCount) {
-                    pPipeline->pVertexAttributeDescriptions = new VkVertexInputAttributeDescription[pPipeline->vtxAttributeCount];
-                    bufferSize = pPipeline->vtxAttributeCount * sizeof(VkVertexInputAttributeDescription);
-                    memcpy((void*)pPipeline->pVertexAttributeDescriptions, ((VkPipelineVertexInputCreateInfo*)pTrav)->pVertexAttributeDescriptions, bufferSize);
-                }
+            case VK_SHADER_STAGE_TESS_CONTROL:
+                memcpy(&pPipeline->tcsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
+                pPipeline->active_shaders |= VK_SHADER_STAGE_TESS_CONTROL_BIT;
                 break;
-            case VK_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO:
-                pPrev->pNext = &pPipeline->iaStateCI;
-                pPrev = (GENERIC_HEADER*)&pPipeline->iaStateCI;
-                memcpy((void*)&pPipeline->iaStateCI, pTrav, sizeof(VkPipelineIaStateCreateInfo));
+            case VK_SHADER_STAGE_TESS_EVALUATION:
+                memcpy(&pPipeline->tesCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
+                pPipeline->active_shaders |= VK_SHADER_STAGE_TESS_EVALUATION_BIT;
                 break;
-            case VK_STRUCTURE_TYPE_PIPELINE_TESS_STATE_CREATE_INFO:
-                pPrev->pNext = &pPipeline->tessStateCI;
-                pPrev = (GENERIC_HEADER*)&pPipeline->tessStateCI;
-                memcpy((void*)&pPipeline->tessStateCI, pTrav, sizeof(VkPipelineTessStateCreateInfo));
+            case VK_SHADER_STAGE_GEOMETRY:
+                memcpy(&pPipeline->gsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
+                pPipeline->active_shaders |= VK_SHADER_STAGE_GEOMETRY_BIT;
                 break;
-            case VK_STRUCTURE_TYPE_PIPELINE_VP_STATE_CREATE_INFO:
-                pPrev->pNext = &pPipeline->vpStateCI;
-                pPrev = (GENERIC_HEADER*)&pPipeline->vpStateCI;
-                memcpy((void*)&pPipeline->vpStateCI, pTrav, sizeof(VkPipelineVpStateCreateInfo));
+            case VK_SHADER_STAGE_FRAGMENT:
+                memcpy(&pPipeline->fsCI, pPSSCI, sizeof(VkPipelineShaderStageCreateInfo));
+                pPipeline->active_shaders |= VK_SHADER_STAGE_FRAGMENT_BIT;
                 break;
-            case VK_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO:
-                pPrev->pNext = &pPipeline->rsStateCI;
-                pPrev = (GENERIC_HEADER*)&pPipeline->rsStateCI;
-                memcpy((void*)&pPipeline->rsStateCI, pTrav, sizeof(VkPipelineRsStateCreateInfo));
-                break;
-            case VK_STRUCTURE_TYPE_PIPELINE_MS_STATE_CREATE_INFO:
-                pPrev->pNext = &pPipeline->msStateCI;
-                pPrev = (GENERIC_HEADER*)&pPipeline->msStateCI;
-                memcpy((void*)&pPipeline->msStateCI, pTrav, sizeof(VkPipelineMsStateCreateInfo));
-                break;
-            case VK_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO:
-                pPrev->pNext = &pPipeline->cbStateCI;
-                pPrev = (GENERIC_HEADER*)&pPipeline->cbStateCI;
-                memcpy((void*)&pPipeline->cbStateCI, pTrav, sizeof(VkPipelineCbStateCreateInfo));
-                // Copy embedded ptrs
-                pCBCI = (VkPipelineCbStateCreateInfo*)pTrav;
-                pPipeline->attachmentCount = pCBCI->attachmentCount;
-                if (pPipeline->attachmentCount) {
-                    pPipeline->pAttachments = new VkPipelineCbAttachmentState[pPipeline->attachmentCount];
-                    bufferSize = pPipeline->attachmentCount * sizeof(VkPipelineCbAttachmentState);
-                    memcpy((void*)pPipeline->pAttachments, ((VkPipelineCbStateCreateInfo*)pTrav)->pAttachments, bufferSize);
-                }
-                break;
-            case VK_STRUCTURE_TYPE_PIPELINE_DS_STATE_CREATE_INFO:
-                pPrev->pNext = &pPipeline->dsStateCI;
-                pPrev = (GENERIC_HEADER*)&pPipeline->dsStateCI;
-                memcpy((void*)&pPipeline->dsStateCI, pTrav, sizeof(VkPipelineDsStateCreateInfo));
+            case VK_SHADER_STAGE_COMPUTE:
+                // TODO : Flag error, CS is specified through VkComputePipelineCreateInfo
+                pPipeline->active_shaders |= VK_SHADER_STAGE_COMPUTE_BIT;
                 break;
             default:
-                assert(0);
+                // TODO : Flag error
                 break;
         }
-        pTrav = (GENERIC_HEADER*)pTrav->pNext;
     }
+
+    if (pCreateInfo->pVertexInputState != NULL) {
+        memcpy((void*)&pPipeline->vertexInputCI, pCreateInfo->pVertexInputState , sizeof(VkPipelineVertexInputStateCreateInfo));
+        // Copy embedded ptrs
+        pVICI = pCreateInfo->pVertexInputState;
+        pPipeline->vtxBindingCount = pVICI->bindingCount;
+        if (pPipeline->vtxBindingCount) {
+            pPipeline->pVertexBindingDescriptions = new VkVertexInputBindingDescription[pPipeline->vtxBindingCount];
+            bufferSize = pPipeline->vtxBindingCount * sizeof(VkVertexInputBindingDescription);
+            memcpy((void*)pPipeline->pVertexBindingDescriptions, pVICI->pVertexBindingDescriptions, bufferSize);
+        }
+        pPipeline->vtxAttributeCount = pVICI->attributeCount;
+        if (pPipeline->vtxAttributeCount) {
+            pPipeline->pVertexAttributeDescriptions = new VkVertexInputAttributeDescription[pPipeline->vtxAttributeCount];
+            bufferSize = pPipeline->vtxAttributeCount * sizeof(VkVertexInputAttributeDescription);
+            memcpy((void*)pPipeline->pVertexAttributeDescriptions, pVICI->pVertexAttributeDescriptions, bufferSize);
+        }
+        pPipeline->graphicsPipelineCI.pVertexInputState = &pPipeline->vertexInputCI;
+    }
+    if (pCreateInfo->pIaState != NULL) {
+        memcpy((void*)&pPipeline->iaStateCI, pCreateInfo->pIaState, sizeof(VkPipelineIaStateCreateInfo));
+        pPipeline->graphicsPipelineCI.pIaState = &pPipeline->iaStateCI;
+    }
+    if (pCreateInfo->pTessState != NULL) {
+        memcpy((void*)&pPipeline->tessStateCI, pCreateInfo->pTessState, sizeof(VkPipelineTessStateCreateInfo));
+        pPipeline->graphicsPipelineCI.pTessState = &pPipeline->tessStateCI;
+    }
+    if (pCreateInfo->pVpState != NULL) {
+        memcpy((void*)&pPipeline->vpStateCI, pCreateInfo->pVpState, sizeof(VkPipelineVpStateCreateInfo));
+        pPipeline->graphicsPipelineCI.pVpState = &pPipeline->vpStateCI;
+    }
+    if (pCreateInfo->pRsState != NULL) {
+        memcpy((void*)&pPipeline->rsStateCI, pCreateInfo->pRsState, sizeof(VkPipelineRsStateCreateInfo));
+        pPipeline->graphicsPipelineCI.pRsState = &pPipeline->rsStateCI;
+    }
+    if (pCreateInfo->pMsState != NULL) {
+        memcpy((void*)&pPipeline->msStateCI, pCreateInfo->pMsState, sizeof(VkPipelineMsStateCreateInfo));
+        pPipeline->graphicsPipelineCI.pMsState = &pPipeline->msStateCI;
+    }
+    if (pCreateInfo->pCbState != NULL) {
+        memcpy((void*)&pPipeline->cbStateCI, pCreateInfo->pCbState, sizeof(VkPipelineCbStateCreateInfo));
+        // Copy embedded ptrs
+        pCBCI = pCreateInfo->pCbState;
+        pPipeline->attachmentCount = pCBCI->attachmentCount;
+        if (pPipeline->attachmentCount) {
+            pPipeline->pAttachments = new VkPipelineCbAttachmentState[pPipeline->attachmentCount];
+            bufferSize = pPipeline->attachmentCount * sizeof(VkPipelineCbAttachmentState);
+            memcpy((void*)pPipeline->pAttachments, pCBCI->pAttachments, bufferSize);
+        }
+        pPipeline->graphicsPipelineCI.pCbState = &pPipeline->cbStateCI;
+    }
+    if (pCreateInfo->pDsState != NULL) {
+        memcpy((void*)&pPipeline->dsStateCI, pCreateInfo->pDsState, sizeof(VkPipelineDsStateCreateInfo));
+        pPipeline->graphicsPipelineCI.pDsState = &pPipeline->dsStateCI;
+    }
+
+    // Copy over GraphicsPipelineCreateInfo structure embedded pointers
+    if (pCreateInfo->stageCount != 0) {
+        pPipeline->graphicsPipelineCI.pStages = new VkPipelineShaderStageCreateInfo[pCreateInfo->stageCount];
+        bufferSize =  pCreateInfo->stageCount * sizeof(VkPipelineShaderStageCreateInfo);
+        memcpy((void*)pPipeline->graphicsPipelineCI.pStages, pCreateInfo->pStages, bufferSize); 
+    }
+
     return pPipeline;
 }
+
 // Free the Pipeline nodes
 static void deletePipelines()
 {
     if (pipelineMap.size() <= 0)
         return;
     for (unordered_map<VkPipeline, PIPELINE_NODE*>::iterator ii=pipelineMap.begin(); ii!=pipelineMap.end(); ++ii) {
+        if ((*ii).second->graphicsPipelineCI.stageCount != 0) {
+            delete[] (*ii).second->graphicsPipelineCI.pStages;
+        }
         if ((*ii).second->pVertexBindingDescriptions) {
             delete[] (*ii).second->pVertexBindingDescriptions;
         }
diff --git a/layers/draw_state.h b/layers/draw_state.h
index 668d644..40f7f9d 100644
--- a/layers/draw_state.h
+++ b/layers/draw_state.h
@@ -79,33 +79,33 @@
 } GENERIC_HEADER;
 
 typedef struct _PIPELINE_NODE {
-    VkPipeline           pipeline;
-    VkGraphicsPipelineCreateInfo    graphicsPipelineCI;
-    VkPipelineVertexInputCreateInfo vertexInputCI;
-    VkPipelineIaStateCreateInfo     iaStateCI;
-    VkPipelineTessStateCreateInfo   tessStateCI;
-    VkPipelineVpStateCreateInfo     vpStateCI;
-    VkPipelineRsStateCreateInfo     rsStateCI;
-    VkPipelineMsStateCreateInfo     msStateCI;
-    VkPipelineCbStateCreateInfo     cbStateCI;
-    VkPipelineDsStateCreateInfo     dsStateCI;
-    VkPipelineShaderStageCreateInfo vsCI;
-    VkPipelineShaderStageCreateInfo tcsCI;
-    VkPipelineShaderStageCreateInfo tesCI;
-    VkPipelineShaderStageCreateInfo gsCI;
-    VkPipelineShaderStageCreateInfo fsCI;
+    VkPipeline                           pipeline;
+    VkGraphicsPipelineCreateInfo         graphicsPipelineCI;
+    VkPipelineVertexInputStateCreateInfo vertexInputCI;
+    VkPipelineIaStateCreateInfo          iaStateCI;
+    VkPipelineTessStateCreateInfo        tessStateCI;
+    VkPipelineVpStateCreateInfo          vpStateCI;
+    VkPipelineRsStateCreateInfo          rsStateCI;
+    VkPipelineMsStateCreateInfo          msStateCI;
+    VkPipelineCbStateCreateInfo          cbStateCI;
+    VkPipelineDsStateCreateInfo          dsStateCI;
+    VkPipelineShaderStageCreateInfo      vsCI;
+    VkPipelineShaderStageCreateInfo      tcsCI;
+    VkPipelineShaderStageCreateInfo      tesCI;
+    VkPipelineShaderStageCreateInfo      gsCI;
+    VkPipelineShaderStageCreateInfo      fsCI;
     // Compute shader is include in VkComputePipelineCreateInfo
-    VkComputePipelineCreateInfo     computePipelineCI;
+    VkComputePipelineCreateInfo          computePipelineCI;
     // Flag of which shader stages are active for this pipeline
-    uint32_t                        active_shaders;
-    VkGraphicsPipelineCreateInfo*      pCreateTree; // Ptr to shadow of data in create tree
+    uint32_t                             active_shaders;
+    VkGraphicsPipelineCreateInfo*        pCreateTree;       // Ptr to shadow of data in create tree
     // Vtx input info (if any)
-    uint32_t                           vtxBindingCount;   // number of bindings
-    VkVertexInputBindingDescription*   pVertexBindingDescriptions;
-    uint32_t                           vtxAttributeCount; // number of attributes
-    VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
-    uint32_t                           attachmentCount;   // number of CB attachments
-    VkPipelineCbAttachmentState*       pAttachments;
+    uint32_t                             vtxBindingCount;   // number of bindings
+    VkVertexInputBindingDescription*     pVertexBindingDescriptions;
+    uint32_t                             vtxAttributeCount; // number of attributes
+    VkVertexInputAttributeDescription*   pVertexAttributeDescriptions;
+    uint32_t                             attachmentCount;   // number of CB attachments
+    VkPipelineCbAttachmentState*         pAttachments;
 } PIPELINE_NODE;
 
 typedef struct _SAMPLER_NODE {
diff --git a/layers/shader_checker.cpp b/layers/shader_checker.cpp
index e0ab544..4ab46c3 100644
--- a/layers/shader_checker.cpp
+++ b/layers/shader_checker.cpp
@@ -628,7 +628,7 @@
 
 
 static bool
-validate_vi_consistency(VkPipelineVertexInputCreateInfo const *vi)
+validate_vi_consistency(VkPipelineVertexInputStateCreateInfo const *vi)
 {
     /* walk the binding descriptions, which describe the step rate and stride of each vertex buffer.
      * each binding should be specified only once.
@@ -655,7 +655,7 @@
 
 
 static bool
-validate_vi_against_vs_inputs(VkPipelineVertexInputCreateInfo const *vi, shader_source const *vs)
+validate_vi_against_vs_inputs(VkPipelineVertexInputStateCreateInfo const *vi, shader_source const *vs)
 {
     std::map<uint32_t, interface_var> inputs;
     /* we collect builtin inputs, but they will never appear in the VI state --
@@ -819,32 +819,29 @@
     shader_source const *shaders[VK_SHADER_STAGE_FRAGMENT + 1];  /* exclude CS */
     memset(shaders, 0, sizeof(shaders));
     VkPipelineCbStateCreateInfo const *cb = 0;
-    VkPipelineVertexInputCreateInfo const *vi = 0;
+    VkPipelineVertexInputStateCreateInfo const *vi = 0;
     char str[1024];
     bool pass = true;
 
     loader_platform_thread_lock_mutex(&globalLock);
 
-    for (auto stage = pCreateInfo; stage; stage = (decltype(stage))stage->pNext) {
-        if (stage->sType == VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO) {
-            auto shader_stage = (VkPipelineShaderStageCreateInfo const *)stage;
+    for (auto i = 0; i < pCreateInfo->stageCount; i++) {
+        VkPipelineShaderStageCreateInfo const *pStage = &pCreateInfo->pStages[i];
+        if (pStage->sType == VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO) {
 
-            if (shader_stage->shader.stage < VK_SHADER_STAGE_VERTEX || shader_stage->shader.stage > VK_SHADER_STAGE_FRAGMENT) {
-                sprintf(str, "Unknown shader stage %d\n", shader_stage->shader.stage);
+            if (pStage->stage < VK_SHADER_STAGE_VERTEX || pStage->stage > VK_SHADER_STAGE_FRAGMENT) {
+                sprintf(str, "Unknown shader stage %d\n", pStage->stage);
                 layerCbMsg(VK_DBG_REPORT_WARN_BIT, (VkObjectType) 0, NULL, 0, SHADER_CHECKER_UNKNOWN_STAGE, "SC", str);
             }
             else {
-                shaders[shader_stage->shader.stage] = shader_map[(void *)(shader_stage->shader.shader)];
+                shaders[pStage->stage] = shader_map[(void *)(pStage->shader)];
             }
         }
-        else if (stage->sType == VK_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO) {
-            cb = (VkPipelineCbStateCreateInfo const *)stage;
-        }
-        else if (stage->sType == VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO) {
-            vi = (VkPipelineVertexInputCreateInfo const *)stage;
-        }
     }
 
+    cb = pCreateInfo->pCbState;
+    vi = pCreateInfo->pVertexInputState;
+
     if (vi) {
         pass = validate_vi_consistency(vi) && pass;
     }
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 8218a0d..a93d8f9 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -1052,23 +1052,30 @@
     err = vkCreateShader(m_device->device(), &vs_ci, &vs);
     ASSERT_VK_SUCCESS(err);
 
-    const VkPipelineShader vs_pipe_shader = {
+    const VkPipelineShaderStageCreateInfo pipe_vs_ci = {
+        .sType                = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+        .pNext                = NULL,
         .stage                = VK_SHADER_STAGE_VERTEX,
         .shader               = vs,
         .linkConstBufferCount = 0,
         .pLinkConstBufferInfo = NULL,
         .pSpecializationInfo  = NULL,
     };
-    const VkPipelineShaderStageCreateInfo pipe_vs_ci = {
-        .sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
-        .pNext  = NULL,
-        .shader = vs_pipe_shader,
-    };
     const VkGraphicsPipelineCreateInfo gp_ci = {
-        .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
-        .pNext = &pipe_vs_ci,
-        .flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT,
-        .layout = pipeline_layout,
+        .sType             = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+        .pNext             = NULL,
+        .stageCount        = 1,
+        .pStages           = &pipe_vs_ci,
+        .pVertexInputState = NULL,
+        .pIaState          = NULL,
+        .pTessState        = NULL,
+        .pVpState          = NULL,
+        .pRsState          = NULL,
+        .pMsState          = NULL,
+        .pDsState          = NULL,
+        .pCbState          = NULL,
+        .flags             = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT,
+        .layout            = pipeline_layout,
     };
 
     VkPipeline pipeline;
@@ -1174,23 +1181,30 @@
     VkShader vs;
     err = vkCreateShader(m_device->device(), &vs_ci, &vs);
 
-    const VkPipelineShader vs_pipe_shader = {
+    const VkPipelineShaderStageCreateInfo pipe_vs_ci = {
+        .sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+        .pNext  = NULL,
         .stage                = VK_SHADER_STAGE_VERTEX,
         .shader               = vs,
         .linkConstBufferCount = 0,
         .pLinkConstBufferInfo = NULL,
         .pSpecializationInfo  = NULL,
     };
-    const VkPipelineShaderStageCreateInfo pipe_vs_ci = {
-        .sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
-        .pNext  = NULL,
-        .shader = vs_pipe_shader,
-    };
     const VkGraphicsPipelineCreateInfo gp_ci = {
-        .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
-        .pNext = &pipe_vs_ci,
-        .flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT,
-        .layout = pipeline_layout,
+        .sType             = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+        .pNext             = NULL,
+        .stageCount        = 1,
+        .pStages           = &pipe_vs_ci,
+        .pVertexInputState = NULL,
+        .pIaState          = NULL,
+        .pTessState        = NULL,
+        .pVpState          = NULL,
+        .pRsState          = NULL,
+        .pMsState          = NULL,
+        .pDsState          = NULL,
+        .pCbState          = NULL,
+        .flags             = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT,
+        .layout            = pipeline_layout,
     };
 
     VkPipeline pipeline;
@@ -1651,23 +1665,30 @@
     err = vkCreateShader(m_device->device(), &vs_ci, &vs);
     ASSERT_VK_SUCCESS(err);
 
-    const VkPipelineShader vs_pipe_shader = {
+    const VkPipelineShaderStageCreateInfo pipe_vs_ci = {
+        .sType                = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+        .pNext                = NULL,
         .stage                = VK_SHADER_STAGE_VERTEX,
         .shader               = vs,
         .linkConstBufferCount = 0,
         .pLinkConstBufferInfo = NULL,
         .pSpecializationInfo  = NULL,
     };
-    const VkPipelineShaderStageCreateInfo pipe_vs_ci = {
-        .sType  = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
-        .pNext  = &pipe_ms_state_ci,
-        .shader = vs_pipe_shader,
-    };
     const VkGraphicsPipelineCreateInfo gp_ci = {
-        .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
-        .pNext = &pipe_vs_ci,
-        .flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT,
-        .layout = pipeline_layout,
+        .sType             = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+        .pNext             = NULL,
+        .stageCount        = 1,
+        .pStages           = &pipe_vs_ci,
+        .pVertexInputState = NULL,
+        .pIaState          = NULL,
+        .pTessState        = NULL,
+        .pVpState          = NULL,
+        .pRsState          = NULL,
+        .pMsState          = &pipe_ms_state_ci,
+        .pDsState          = NULL,
+        .pCbState          = NULL,
+        .flags             = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT,
+        .layout            = pipeline_layout,
     };
 
     VkPipeline pipeline;
diff --git a/tests/vkrenderframework.cpp b/tests/vkrenderframework.cpp
index 6d9e999..b598be7 100644
--- a/tests/vkrenderframework.cpp
+++ b/tests/vkrenderframework.cpp
@@ -304,7 +304,7 @@
 
     for (i = 0; i < targets; i++) {
         VkImageObj *img = new VkImageObj(m_device);
- 
+
         VkFormatProperties props;
         size_t size = sizeof(props);
         VkResult err;
@@ -325,7 +325,7 @@
         else {
             FAIL() << "Neither Linear nor Optimal allowed for render target";
         }
-        
+
         m_renderTargets.push_back(img);
         m_colorBindings[i].view  = img->targetView();
         m_colorBindings[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
@@ -1024,11 +1024,11 @@
 VkPipelineShaderStageCreateInfo* VkShaderObj::GetStageCreateInfo()
 {
     VkPipelineShaderStageCreateInfo *stageInfo = (VkPipelineShaderStageCreateInfo*) calloc( 1,sizeof(VkPipelineShaderStageCreateInfo) );
-    stageInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
-    stageInfo->shader.stage = m_stage;
-    stageInfo->shader.shader = obj();
-    stageInfo->shader.linkConstBufferCount = 0;
-    stageInfo->shader.pLinkConstBufferInfo = VK_NULL_HANDLE;
+    stageInfo->sType                = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+    stageInfo->stage                = m_stage;
+    stageInfo->shader               = obj();
+    stageInfo->linkConstBufferCount = 0;
+    stageInfo->pLinkConstBufferInfo = VK_NULL_HANDLE;
 
     return stageInfo;
 }
@@ -1076,7 +1076,13 @@
 VkPipelineObj::VkPipelineObj(VkDeviceObj *device)
 {
     m_device = device;
-    m_vi_state.attributeCount = m_vi_state.bindingCount = 0;
+
+    m_vi_state.pNext                        = VK_NULL_HANDLE;
+    m_vi_state.bindingCount                 = 0;
+    m_vi_state.pVertexBindingDescriptions   = VK_NULL_HANDLE;
+    m_vi_state.attributeCount               = 0;
+    m_vi_state.pVertexAttributeDescriptions = VK_NULL_HANDLE;
+
     m_vertexBufferCount = 0;
 
     m_ia_state.sType = VK_STRUCTURE_TYPE_PIPELINE_IA_STATE_CREATE_INFO;
@@ -1087,7 +1093,7 @@
     m_ia_state.primitiveRestartIndex = 0;
 
     m_rs_state.sType = VK_STRUCTURE_TYPE_PIPELINE_RS_STATE_CREATE_INFO;
-    m_rs_state.pNext = &m_ia_state;
+    m_rs_state.pNext = VK_NULL_HANDLE;
     m_rs_state.depthClipEnable = VK_FALSE;
     m_rs_state.rasterizerDiscardEnable = VK_FALSE;
     m_rs_state.pointOrigin = VK_COORDINATE_ORIGIN_UPPER_LEFT;
@@ -1098,11 +1104,11 @@
 
     memset(&m_cb_state,0,sizeof(m_cb_state));
     m_cb_state.sType = VK_STRUCTURE_TYPE_PIPELINE_CB_STATE_CREATE_INFO;
-    m_cb_state.pNext = &m_rs_state;
+    m_cb_state.pNext = VK_NULL_HANDLE;
     m_cb_state.alphaToCoverageEnable = VK_FALSE;
     m_cb_state.logicOp = VK_LOGIC_OP_COPY;
 
-    m_ms_state.pNext = &m_cb_state;
+    m_ms_state.pNext = VK_NULL_HANDLE;
     m_ms_state.sType = VK_STRUCTURE_TYPE_PIPELINE_MS_STATE_CREATE_INFO;
     m_ms_state.multisampleEnable = VK_FALSE;
     m_ms_state.sampleMask = 1;                // Do we have to specify MSAA even just to disable it?
@@ -1111,13 +1117,13 @@
     m_ms_state.sampleShadingEnable = 0;
 
     m_vp_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VP_STATE_CREATE_INFO;
-    m_vp_state.pNext = &m_ms_state;
+    m_vp_state.pNext = VK_NULL_HANDLE;
     m_vp_state.viewportCount = 1;
     m_vp_state.depthMode = VK_DEPTH_MODE_ZERO_TO_ONE;
     m_vp_state.clipOrigin = VK_COORDINATE_ORIGIN_UPPER_LEFT;
 
     m_ds_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DS_STATE_CREATE_INFO;
-    m_ds_state.pNext = &m_vp_state,
+    m_ds_state.pNext = VK_NULL_HANDLE,
     m_ds_state.format = VK_FORMAT_D32_SFLOAT;
     m_ds_state.depthTestEnable      = VK_FALSE;
     m_ds_state.depthWriteEnable     = VK_FALSE;
@@ -1185,33 +1191,41 @@
 
 VkResult VkPipelineObj::CreateVKPipeline(VkDescriptorSetObj &descriptorSet)
 {
-    void* head_ptr = &m_ds_state;
     VkGraphicsPipelineCreateInfo info = {};
 
     VkPipelineShaderStageCreateInfo* shaderCreateInfo;
 
+    info.stageCount = m_shaderObjs.size();
+    info.pStages = new VkPipelineShaderStageCreateInfo[info.stageCount];
+
     for (int i=0; i<m_shaderObjs.size(); i++)
     {
         shaderCreateInfo = m_shaderObjs[i]->GetStageCreateInfo();
-        shaderCreateInfo->pNext = head_ptr;
-        head_ptr = shaderCreateInfo;
+        memcpy((void*)&info.pStages[i], shaderCreateInfo, sizeof(VkPipelineShaderStageCreateInfo));
     }
 
     if (m_vi_state.attributeCount && m_vi_state.bindingCount)
     {
-        m_vi_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_CREATE_INFO;
-        m_vi_state.pNext = head_ptr;
-        head_ptr = &m_vi_state;
+        m_vi_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
     }
 
     info.sType  = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
-    info.pNext  = head_ptr;
+    info.pNext  = NULL;
     info.flags  = 0;
     info.layout = descriptorSet.GetPipelineLayout();
 
     m_cb_state.attachmentCount = m_colorAttachments.size();
     m_cb_state.pAttachments = &m_colorAttachments[0];
 
+    info.pTessState        = NULL;
+    info.pVertexInputState = &m_vi_state;
+    info.pIaState          = &m_ia_state;
+    info.pVpState          = &m_vp_state;
+    info.pRsState          = &m_rs_state;
+    info.pMsState          = &m_ms_state;
+    info.pDsState          = &m_ds_state;
+    info.pCbState          = &m_cb_state;
+
     return init_try(*m_device, info);
 }
 
diff --git a/tests/vkrenderframework.h b/tests/vkrenderframework.h
index 58f229f..03bc031 100644
--- a/tests/vkrenderframework.h
+++ b/tests/vkrenderframework.h
@@ -410,20 +410,19 @@
     VkResult CreateVKPipeline(VkDescriptorSetObj &descriptorSet);
 
 protected:
-    VkPipelineVertexInputCreateInfo     m_vi_state;
-    VkPipelineIaStateCreateInfo         m_ia_state;
-    VkPipelineRsStateCreateInfo         m_rs_state;
-    VkPipelineCbStateCreateInfo         m_cb_state;
-    VkPipelineDsStateCreateInfo         m_ds_state;
-    VkPipelineVpStateCreateInfo         m_vp_state;
-    VkPipelineMsStateCreateInfo         m_ms_state;
-    VkDeviceObj                        *m_device;
-    vector<VkShaderObj*>                m_shaderObjs;
-    vector<VkConstantBufferObj*>        m_vertexBufferObjs;
-    vector<int>                         m_vertexBufferBindings;
-    vector<VkPipelineCbAttachmentState> m_colorAttachments;
-    int                                 m_vertexBufferCount;
-
+    VkPipelineVertexInputStateCreateInfo m_vi_state;
+    VkPipelineIaStateCreateInfo          m_ia_state;
+    VkPipelineRsStateCreateInfo          m_rs_state;
+    VkPipelineCbStateCreateInfo          m_cb_state;
+    VkPipelineDsStateCreateInfo          m_ds_state;
+    VkPipelineVpStateCreateInfo          m_vp_state;
+    VkPipelineMsStateCreateInfo          m_ms_state;
+    VkDeviceObj                         *m_device;
+    vector<VkShaderObj*>                 m_shaderObjs;
+    vector<VkConstantBufferObj*>         m_vertexBufferObjs;
+    vector<int>                          m_vertexBufferBindings;
+    vector<VkPipelineCbAttachmentState>  m_colorAttachments;
+    int                                  m_vertexBufferCount;
 };
 
 #endif // VKRENDERFRAMEWORK_H
diff --git a/tests/vktestbinding.cpp b/tests/vktestbinding.cpp
index 42da8c0..00f8462 100644
--- a/tests/vktestbinding.cpp
+++ b/tests/vktestbinding.cpp
@@ -186,18 +186,12 @@
 
 uint32_t Object::memory_allocation_count() const
 {
-    /// LUGMAL return get_info<uint32_t>(dev_->obj(), type(), obj(), VK_OBJECT_INFO_TYPE_MEMORY_ALLOCATION_COUNT, 1)[0];
     return 1;
 }
 
 std::vector<VkMemoryRequirements> Object::memory_requirements() const
 {
-    //// VkResult err;
     uint32_t num_allocations = 1;
-    //// size_t num_alloc_size = sizeof(num_allocations);
-    //// err = vkGetObjectInfo(dev_->obj(), type(), obj(), VK_OBJECT_INFO_TYPE_MEMORY_ALLOCATION_COUNT,
-    ////                        &num_alloc_size, &num_allocations);
-    //// EXPECT(err == VK_SUCCESS && num_alloc_size == sizeof(num_allocations));
     std::vector<VkMemoryRequirements> info =
         get_info<VkMemoryRequirements>(dev_->obj(), type(), obj(), VK_OBJECT_INFO_TYPE_MEMORY_REQUIREMENTS, 0);
     EXPECT(info.size() == num_allocations);