layers: Improved DrawState Descriptor Update validation
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index fa9c198..20ccd70 100755
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -524,7 +524,7 @@
             VkFramebufferCreateInfo* pFBCI = frameBufferMap[pCB->framebuffer];
             if ((psoNumSamples != pFBCI->sampleCount) || (psoNumSamples != pRPCI->sampleCount)) {
                 char str[1024];
-                sprintf(str, "Num samples mismatche! Binding PSO (%p) with %u samples while current RenderPass (%p) w/ %u samples uses FB (%p) with %u samples!", (void*)pipeline, psoNumSamples, (void*)pCB->activeRenderPass, pRPCI->sampleCount, (void*)pCB->framebuffer, pFBCI->sampleCount);
+                sprintf(str, "Num samples mismatch! Binding PSO (%p) with %u samples while current RenderPass (%p) w/ %u samples uses FB (%p) with %u samples!", (void*)pipeline, psoNumSamples, (void*)pCB->activeRenderPass, pRPCI->sampleCount, (void*)pCB->framebuffer, pFBCI->sampleCount);
                 layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, pipeline, 0, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", str);
             }
         } else {
@@ -585,10 +585,28 @@
     loader_platform_thread_unlock_mutex(&globalLock);
     return layoutMap[layout];
 }
-
+// Return 1 if update struct is of valid type, 0 otherwise
+static bool32_t validUpdateStruct(const GENERIC_HEADER* pUpdateStruct)
+{
+    char str[1024];
+    switch (pUpdateStruct->sType)
+    {
+        case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
+        case VK_STRUCTURE_TYPE_UPDATE_SAMPLER_TEXTURES:
+        case VK_STRUCTURE_TYPE_UPDATE_IMAGES:
+        case VK_STRUCTURE_TYPE_UPDATE_BUFFERS:
+        case VK_STRUCTURE_TYPE_UPDATE_AS_COPY:
+            return 1;
+        default:
+            sprintf(str, "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
+            layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_INVALID_UPDATE_STRUCT, "DS", str);
+            return 0;
+    }
+}
 // For given update struct, return binding
 static uint32_t getUpdateBinding(const GENERIC_HEADER* pUpdateStruct)
 {
+    char str[1024];
     switch (pUpdateStruct->sType)
     {
         case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
@@ -602,14 +620,15 @@
         case VK_STRUCTURE_TYPE_UPDATE_AS_COPY:
             return ((VkUpdateAsCopy*)pUpdateStruct)->binding;
         default:
-            // TODO : Flag specific error for this case
-            assert(0);
-            return 0;
+            sprintf(str, "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
+            layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_INVALID_UPDATE_STRUCT, "DS", str);
+            return 0xFFFFFFFF;
     }
 }
 // Return count for given update struct
 static uint32_t getUpdateArrayIndex(const GENERIC_HEADER* pUpdateStruct)
 {
+    char str[1024];
     switch (pUpdateStruct->sType)
     {
         case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
@@ -624,14 +643,15 @@
             // TODO : Need to understand this case better and make sure code is correct
             return (((VkUpdateAsCopy*)pUpdateStruct)->arrayElement);
         default:
-            // TODO : Flag specific error for this case
-            assert(0);
+            sprintf(str, "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
+            layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_INVALID_UPDATE_STRUCT, "DS", str);
             return 0;
     }
 }
 // Return count for given update struct
 static uint32_t getUpdateCount(const GENERIC_HEADER* pUpdateStruct)
 {
+    char str[1024];
     switch (pUpdateStruct->sType)
     {
         case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
@@ -646,8 +666,8 @@
             // TODO : Need to understand this case better and make sure code is correct
             return (((VkUpdateAsCopy*)pUpdateStruct)->count);
         default:
-            // TODO : Flag specific error for this case
-            assert(0);
+            sprintf(str, "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
+            layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_INVALID_UPDATE_STRUCT, "DS", str);
             return 0;
     }
 }
@@ -685,6 +705,7 @@
     // First get actual type of update
     VkDescriptorType actualType;
     uint32_t i = 0;
+    char str[1024];
     switch (pUpdateStruct->sType)
     {
         case VK_STRUCTURE_TYPE_UPDATE_SAMPLERS:
@@ -703,7 +724,8 @@
             actualType = ((VkUpdateAsCopy*)pUpdateStruct)->descriptorType;
             break;
         default:
-            // TODO : Flag specific error for this case
+            sprintf(str, "Unexpected UPDATE struct of type %s (value %u) in vkUpdateDescriptors() struct tree", string_VkStructureType(pUpdateStruct->sType), pUpdateStruct->sType);
+            layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_INVALID_UPDATE_STRUCT, "DS", str);
             return 0;
     }
     for (i = getUpdateStartIndex(pLayout, pUpdateStruct); i <= getUpdateEndIndex(pLayout, pUpdateStruct); i++) {
@@ -784,8 +806,9 @@
     return pNewNode;
 }
 // For given ds, update its mapping based on ppUpdateArray
-static void dsUpdate(VkDescriptorSet ds, uint32_t updateCount, const void** ppUpdateArray)
+static bool32_t dsUpdate(VkDescriptorSet ds, uint32_t updateCount, const void** ppUpdateArray)
 {
+    bool32_t result = 1;
     SET_NODE* pSet = getSetNode(ds);
     loader_platform_thread_lock_mutex(&globalLock);
     g_lastBoundDescriptorSet = pSet->set;
@@ -796,11 +819,17 @@
     for (uint32_t i = 0; i < updateCount; i++) {
         GENERIC_HEADER* pUpdate = (GENERIC_HEADER*)ppUpdateArray[i];
         pLayout = pSet->pLayout;
+        // First verify valid update struct
+        if (!validUpdateStruct(pUpdate)) {
+            result = 0;
+            break;
+        }
         // Make sure that binding is within bounds
         if (pLayout->createInfo.count < getUpdateBinding(pUpdate)) {
             char str[1024];
             sprintf(str, "Descriptor Set %p does not have binding to match update binding %u for update type %s!", ds, getUpdateBinding(pUpdate), string_VkStructureType(pUpdate->sType));
             layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, ds, 0, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", str);
+            result = 0;
         }
         else {
             // Next verify that update falls within size of given binding
@@ -810,6 +839,7 @@
                 string DSstr = vk_print_vkdescriptorsetlayoutcreateinfo(pLayoutCI, "{DS}    ");
                 sprintf(str, "Descriptor update type of %s is out of bounds for matching binding %u in Layout w/ CI:\n%s!", string_VkStructureType(pUpdate->sType), getUpdateBinding(pUpdate), DSstr.c_str());
                 layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, ds, 0, DRAWSTATE_DESCRIPTOR_UPDATE_OUT_OF_BOUNDS, "DS", str);
+                result = 0;
             }
             else { // TODO : should we skip update on a type mismatch or force it?
                 // Layout bindings match w/ update ok, now verify that update is of the right type
@@ -817,6 +847,7 @@
                     char str[1024];
                     sprintf(str, "Descriptor update type of %s does not match overlapping binding type!", string_VkStructureType(pUpdate->sType));
                     layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, ds, 0, DRAWSTATE_DESCRIPTOR_TYPE_MISMATCH, "DS", str);
+                    result = 0;
                 }
                 else {
                     // Save the update info
@@ -827,6 +858,7 @@
                         char str[1024];
                         sprintf(str, "Out of memory while attempting to allocate UPDATE struct in vkUpdateDescriptors()");
                         layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, ds, 0, DRAWSTATE_OUT_OF_MEMORY, "DS", str);
+                        result = 0;
                     }
                     else {
                         // Insert shadow node into LL of updates for this set
@@ -843,6 +875,7 @@
         }
     }
     loader_platform_thread_unlock_mutex(&globalLock);
+    return result;
 }
 // Free the shadowed update node for this Set
 // NOTE : Calls to this function should be wrapped in mutex
@@ -1310,7 +1343,7 @@
     }
 }
 // Verify bound Pipeline State Object
-static void validateBoundPipeline(const VkCmdBuffer cb)
+static bool validateBoundPipeline(const VkCmdBuffer cb)
 {
     GLOBAL_CB_NODE* pCB = getCBNode(cb);
     if (pCB && pCB->lastBoundPipeline) {
@@ -1320,6 +1353,7 @@
         if (!pPipeTrav) {
             sprintf(str, "Can't find last bound Pipeline %p!", (void*)pCB->lastBoundPipeline);
             layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_NO_PIPELINE_BOUND, "DS", str);
+            return false;
         }
         else {
             // Verify Vtx binding
@@ -1328,10 +1362,12 @@
                     if (0 == pPipeTrav->vtxBindingCount) {
                         sprintf(str, "Vtx Buffer Index %u was bound, but no vtx buffers are attached to PSO.", pCB->lastVtxBinding);
                         layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", str);
+                        return false;
                     }
                     else {
                         sprintf(str, "Vtx binding Index of %u exceeds PSO pVertexBindingDescriptions max array index of %u.", pCB->lastVtxBinding, (pPipeTrav->vtxBindingCount - 1));
                         layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, NULL, 0, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", str);
+                        return false;
                     }
                 }
                 else {
@@ -1340,7 +1376,9 @@
                 }
             }
         }
+        return true;
     }
+    return false;
 }
 // Print details of DS config to stdout
 static void printDSConfig(const VkCmdBuffer cb)
@@ -1903,11 +1941,11 @@
         layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, descriptorSet, 0, DRAWSTATE_UPDATE_WITHOUT_BEGIN, "DS", str);
     }
     else {
-        // pUpdateChain is a Linked-list of VK_UPDATE_* structures defining the mappings for the descriptors
-        dsUpdate(descriptorSet, updateCount, ppUpdateArray);
+        // pUpdateChain is an array of VK_UPDATE_* struct ptrs defining the mappings for the descriptors
+        if (dsUpdate(descriptorSet, updateCount, ppUpdateArray)) {
+            nextTable.UpdateDescriptors(device, descriptorSet, updateCount, ppUpdateArray);
+        }
     }
-
-    nextTable.UpdateDescriptors(device, descriptorSet, updateCount, ppUpdateArray);
 }
 
 VK_LAYER_EXPORT VkResult VKAPI vkCreateDynamicViewportState(VkDevice device, const VkDynamicVpStateCreateInfo* pCreateInfo, VkDynamicVpState* pState)
@@ -2052,23 +2090,26 @@
     if (pCB) {
         updateCBTracking(cmdBuffer);
         addCmd(pCB, CMD_BINDDESCRIPTORSETS);
-        for (uint32_t i=0; i<setCount; i++) {
-            if (getSetNode(pDescriptorSets[i])) {
-                loader_platform_thread_lock_mutex(&globalLock);
-                pCB->lastBoundDescriptorSet = pDescriptorSets[i];
-                pCB->boundDescriptorSets.push_back(pDescriptorSets[i]);
-                g_lastBoundDescriptorSet = pDescriptorSets[i];
-                loader_platform_thread_unlock_mutex(&globalLock);
-                char str[1024];
-                sprintf(str, "DS %p bound on pipeline %s", (void*)pDescriptorSets[i], string_VkPipelineBindPoint(pipelineBindPoint));
-                layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, pDescriptorSets[i], 0, DRAWSTATE_NONE, "DS", str);
-                synchAndPrintDSConfig(cmdBuffer);
+        if (validateBoundPipeline(cmdBuffer)) {
+            for (uint32_t i=0; i<setCount; i++) {
+                if (getSetNode(pDescriptorSets[i])) {
+                    loader_platform_thread_lock_mutex(&globalLock);
+                    pCB->lastBoundDescriptorSet = pDescriptorSets[i];
+                    pCB->boundDescriptorSets.push_back(pDescriptorSets[i]);
+                    g_lastBoundDescriptorSet = pDescriptorSets[i];
+                    loader_platform_thread_unlock_mutex(&globalLock);
+                    char str[1024];
+                    sprintf(str, "DS %p bound on pipeline %s", (void*)pDescriptorSets[i], string_VkPipelineBindPoint(pipelineBindPoint));
+                    layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, pDescriptorSets[i], 0, DRAWSTATE_NONE, "DS", str);
+                    synchAndPrintDSConfig(cmdBuffer);
+                }
+                else {
+                    char str[1024];
+                    sprintf(str, "Attempt to bind DS %p that doesn't exist!", (void*)pDescriptorSets[i]);
+                    layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, pDescriptorSets[i], 0, DRAWSTATE_INVALID_SET, "DS", str);
+                }
             }
-            else {
-                char str[1024];
-                sprintf(str, "Attempt to bind DS %p that doesn't exist!", (void*)pDescriptorSets[i]);
-                layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, pDescriptorSets[i], 0, DRAWSTATE_INVALID_SET, "DS", str);
-            }
+            nextTable.CmdBindDescriptorSets(cmdBuffer, pipelineBindPoint, firstSet, setCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
         }
     }
     else {
@@ -2076,7 +2117,6 @@
         sprintf(str, "Attempt to use CmdBuffer %p that doesn't exist!", (void*)cmdBuffer);
         layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, cmdBuffer, 0, DRAWSTATE_INVALID_CMD_BUFFER, "DS", str);
     }
-    nextTable.CmdBindDescriptorSets(cmdBuffer, pipelineBindPoint, firstSet, setCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
 }
 
 VK_LAYER_EXPORT void VKAPI vkCmdBindIndexBuffer(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType)
@@ -2108,13 +2148,14 @@
         updateCBTracking(cmdBuffer);
         addCmd(pCB, CMD_BINDVERTEXBUFFER);
         pCB->lastVtxBinding = startBinding + bindingCount -1;
-        validateBoundPipeline(cmdBuffer);
+        if (validateBoundPipeline(cmdBuffer)) {
+            nextTable.CmdBindVertexBuffers(cmdBuffer, startBinding, bindingCount, pBuffers, pOffsets);
+        }
     } else {
         char str[1024];
         sprintf(str, "Attempt to use CmdBuffer %p that doesn't exist!", (void*)cmdBuffer);
         layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, cmdBuffer, 0, DRAWSTATE_INVALID_CMD_BUFFER, "DS", str);
     }
-    nextTable.CmdBindVertexBuffers(cmdBuffer, startBinding, bindingCount, pBuffers, pOffsets);
 }
 
 VK_LAYER_EXPORT void VKAPI vkCmdDraw(VkCmdBuffer cmdBuffer, uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount)