layers: LX195, Drawstate ignores compute pipelines
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index 02237b5..6c3661c 100644
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -464,13 +464,15 @@
     if (dynViewport) {
         if (pCB->viewports.size() != pPipe->graphicsPipelineCI.pViewportState->viewportCount) {
             result |= log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType) 0, 0, 0, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
-                "Dynamic viewportCount from vkCmdSetViewport() is " PRINTF_SIZE_T_SPECIFIER ", but PSO viewportCount is %u. These counts must match.", pCB->viewports.size(), pPipe->graphicsPipelineCI.pViewportState->viewportCount);
+                "Dynamic viewportCount from vkCmdSetViewport() is " PRINTF_SIZE_T_SPECIFIER ", but PSO viewportCount is %u. These counts must match.",
+                 pCB->viewports.size(), pPipe->graphicsPipelineCI.pViewportState->viewportCount);
         }
     }
     if (dynScissor) {
         if (pCB->scissors.size() != pPipe->graphicsPipelineCI.pViewportState->scissorCount) {
             result |= log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType) 0, 0, 0, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
-                "Dynamic scissorCount from vkCmdSetScissor() is " PRINTF_SIZE_T_SPECIFIER ", but PSO scissorCount is %u. These counts must match.", pCB->scissors.size(), pPipe->graphicsPipelineCI.pViewportState->scissorCount);
+                "Dynamic scissorCount from vkCmdSetScissor() is " PRINTF_SIZE_T_SPECIFIER ", but PSO scissorCount is %u. These counts must match.",
+                pCB->scissors.size(), pPipe->graphicsPipelineCI.pViewportState->scissorCount);
         }
     }
     return result;
@@ -532,13 +534,15 @@
         if (!dynViewport) {
             if (pPipeline->graphicsPipelineCI.pViewportState->viewportCount && !pPipeline->graphicsPipelineCI.pViewportState->pViewports) {
                 skipCall |= log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType) 0, 0, 0, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
-                    "Gfx Pipeline viewportCount is %u, but pViewports is NULL. For non-zero viewportCount, you must either include pViewports data, or include viewport in pDynamicState and set it with vkCmdSetViewport().", pPipeline->graphicsPipelineCI.pViewportState->viewportCount);
+                    "Gfx Pipeline viewportCount is %u, but pViewports is NULL. For non-zero viewportCount, you must either include pViewports data, or "
+                    "include viewport in pDynamicState and set it with vkCmdSetViewport().", pPipeline->graphicsPipelineCI.pViewportState->viewportCount);
             }
         }
         if (!dynScissor) {
             if (pPipeline->graphicsPipelineCI.pViewportState->scissorCount && !pPipeline->graphicsPipelineCI.pViewportState->pScissors) {
                 skipCall |= log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType) 0, 0, 0, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
-                    "Gfx Pipeline scissorCount is %u, but pScissors is NULL. For non-zero scissorCount, you must either include pScissors data, or include scissor in pDynamicState and set it with vkCmdSetScissor().", pPipeline->graphicsPipelineCI.pViewportState->scissorCount);
+                    "Gfx Pipeline scissorCount is %u, but pScissors is NULL. For non-zero scissorCount, you must either include pScissors data, or include "
+                    "scissor in pDynamicState and set it with vkCmdSetScissor().", pPipeline->graphicsPipelineCI.pViewportState->scissorCount);
             }
         }
     }
@@ -547,7 +551,7 @@
 
 // Init the pipeline mapping info based on pipeline create info LL tree
 //  Threading note : Calls to this function should wrapped in mutex
-static PIPELINE_NODE* initPipeline(layer_data* dev_data, const VkGraphicsPipelineCreateInfo* pCreateInfo, PIPELINE_NODE* pBasePipeline)
+static PIPELINE_NODE* initGraphicsPipeline(layer_data* dev_data, const VkGraphicsPipelineCreateInfo* pCreateInfo, PIPELINE_NODE* pBasePipeline)
 {
     PIPELINE_NODE* pPipeline = new PIPELINE_NODE;
     if (pBasePipeline) {
@@ -2247,7 +2251,13 @@
     return result;
 }
 
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines)
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines(
+    VkDevice                            device,
+    VkPipelineCache                     pipelineCache,
+    uint32_t                            count,
+    const VkGraphicsPipelineCreateInfo *pCreateInfos,
+    const VkAllocationCallbacks        *pAllocator,
+    VkPipeline                         *pPipelines)
 {
     VkResult result = VK_SUCCESS;
     //TODO What to do with pipelineCache?
@@ -2259,15 +2269,19 @@
     // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic
     vector<PIPELINE_NODE*> pPipeNode(count);
     layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+
     uint32_t i=0;
     loader_platform_thread_lock_mutex(&globalLock);
+
     for (i=0; i<count; i++) {
-        pPipeNode[i] = initPipeline(dev_data, &pCreateInfos[i], NULL);
+        pPipeNode[i] = initGraphicsPipeline(dev_data, &pCreateInfos[i], NULL);
         skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode[i]);
     }
+
     loader_platform_thread_unlock_mutex(&globalLock);
     if (VK_FALSE == skipCall) {
-        result = dev_data->device_dispatch_table->CreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
+        result = dev_data->device_dispatch_table->CreateGraphicsPipelines(device,
+            pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
         loader_platform_thread_lock_mutex(&globalLock);
         for (i=0; i<count; i++) {
             pPipeNode[i]->pipeline = pPipelines[i];
@@ -2289,6 +2303,56 @@
     return result;
 }
 
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateComputePipelines(
+    VkDevice                            device,
+    VkPipelineCache                     pipelineCache,
+    uint32_t                            count,
+    const VkComputePipelineCreateInfo  *pCreateInfos,
+    const VkAllocationCallbacks        *pAllocator,
+    VkPipeline                         *pPipelines)
+{
+    VkResult result   = VK_SUCCESS;
+    VkBool32 skipCall = VK_FALSE;
+
+    // TODO : Improve this data struct w/ unique_ptrs so cleanup below is automatic
+    vector<PIPELINE_NODE*> pPipeNode(count);
+    layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+
+    uint32_t i=0;
+    loader_platform_thread_lock_mutex(&globalLock);
+    for (i=0; i<count; i++) {
+        // TODO: Verify compute stage bits
+
+        // Create and initialize internal tracking data structure
+        pPipeNode[i] = new PIPELINE_NODE;
+        memset((void*)pPipeNode[i], 0, sizeof(PIPELINE_NODE));
+        memcpy(&pPipeNode[i]->computePipelineCI, (const void*)&pCreateInfos[i], sizeof(VkComputePipelineCreateInfo));
+
+        // TODO: Add Compute Pipeline Verification
+        // skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode[i]);
+    }
+    loader_platform_thread_unlock_mutex(&globalLock);
+
+    if (VK_FALSE == skipCall) {
+        result = dev_data->device_dispatch_table->CreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines);
+        loader_platform_thread_lock_mutex(&globalLock);
+        for (i=0; i<count; i++) {
+            pPipeNode[i]->pipeline = pPipelines[i];
+            dev_data->pipelineMap[pPipeNode[i]->pipeline] = pPipeNode[i];
+        }
+        loader_platform_thread_unlock_mutex(&globalLock);
+    } else {
+        for (i=0; i<count; i++) {
+            if (pPipeNode[i]) {
+                // Clean up any locally allocated data structures
+                delete pPipeNode[i];
+            }
+        }
+        return VK_ERROR_VALIDATION_FAILED;
+    }
+    return result;
+}
+
 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler)
 {
     layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -4599,6 +4663,8 @@
         return (PFN_vkVoidFunction) vkMergePipelineCaches;
     if (!strcmp(funcName, "vkCreateGraphicsPipelines"))
         return (PFN_vkVoidFunction) vkCreateGraphicsPipelines;
+    if (!strcmp(funcName, "vkCreateComputePipelines"))
+        return (PFN_vkVoidFunction) vkCreateComputePipelines;
     if (!strcmp(funcName, "vkCreateSampler"))
         return (PFN_vkVoidFunction) vkCreateSampler;
     if (!strcmp(funcName, "vkCreateDescriptorSetLayout"))