layers: Migrate dynamic state checks to DrawState from ObjectTracker

Needed to improve the CB and DS state checks to cross-verify with PSO state. Since that state is already tracked in DrawState makes sense to move these checks over.
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index 4496765..64b2c3a 100755
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -312,7 +312,38 @@
     g_lastTouchedCBIndex = g_lastTouchedCBIndex % NUM_COMMAND_BUFFERS_TO_DISPLAY;
     loader_platform_thread_unlock_mutex(&globalLock);
 }
-
+// Check object status for selected flag state
+static bool32_t validate_status(VkCmdBuffer cb, CBStatusFlags enable_mask, CBStatusFlags status_mask, CBStatusFlags status_flag, VK_DBG_MSG_TYPE error_level, DRAW_STATE_ERROR error_code, const char* fail_msg) {
+    if (cmdBufferMap.find(cb) != cmdBufferMap.end()) {
+        GLOBAL_CB_NODE* pNode = cmdBufferMap[cb];
+        // If non-zero enable mask is present, check it against status but if enable_mask
+        //  is 0 then no enable required so we should always just check status
+        if ((!enable_mask) || (enable_mask & pNode->status)) {
+            if ((pNode->status & status_mask) != status_flag) {
+                char str[1024];
+                sprintf(str, "CB object 0x%" PRIxLEAST64 ": %s", reinterpret_cast<VkUintPtrLeast64>(cb), fail_msg);
+                layerCbMsg(error_level, VK_VALIDATION_LEVEL_0, cb, 0, error_code, "DS", str);
+                return VK_FALSE;
+            }
+        }
+        return VK_TRUE;
+    }
+    else {
+        // If we do not find it print an error
+        char str[1024];
+        sprintf(str, "Unable to obtain status for non-existent CB object 0x%" PRIxLEAST64, reinterpret_cast<VkUintPtrLeast64>(cb));
+        layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, cb, 0, DRAWSTATE_INVALID_CMD_BUFFER, "DS", str);
+        return VK_FALSE;
+    }
+}
+static bool32_t validate_draw_state_flags(VkCmdBuffer cb) {
+    bool32_t result1, result2, result3, result4;
+    result1 = validate_status(cb, CBSTATUS_NONE, CBSTATUS_VIEWPORT_BOUND, CBSTATUS_VIEWPORT_BOUND, VK_DBG_MSG_ERROR, DRAWSTATE_VIEWPORT_NOT_BOUND, "Viewport object not bound to this command buffer");
+    result2 = validate_status(cb, CBSTATUS_NONE, CBSTATUS_RASTER_BOUND,   CBSTATUS_RASTER_BOUND,   VK_DBG_MSG_ERROR, DRAWSTATE_RASTER_NOT_BOUND,   "Raster object not bound to this command buffer");
+    result3 = validate_status(cb, CBSTATUS_COLOR_BLEND_WRITE_ENABLE, CBSTATUS_COLOR_BLEND_BOUND,   CBSTATUS_COLOR_BLEND_BOUND,   VK_DBG_MSG_ERROR,  DRAWSTATE_COLOR_BLEND_NOT_BOUND,   "Color-blend object not bound to this command buffer");
+    result4 = validate_status(cb, CBSTATUS_DEPTH_STENCIL_WRITE_ENABLE, CBSTATUS_DEPTH_STENCIL_BOUND, CBSTATUS_DEPTH_STENCIL_BOUND, VK_DBG_MSG_ERROR,  DRAWSTATE_DEPTH_STENCIL_NOT_BOUND, "Depth-stencil object not bound to this command buffer");
+    return ((result1 == VK_TRUE) && (result2 == VK_TRUE) && (result3 == VK_TRUE) && (result4 == VK_TRUE));
+}
 // Print the last bound dynamic state
 static void printDynamicState(const VkCmdBuffer cb)
 {
@@ -983,14 +1014,38 @@
         pCB->lastVtxBinding = MAX_BINDING;
     }
 }
+// Set PSO-related status bits for CB
+static void set_cb_pso_status(GLOBAL_CB_NODE* pCB, const PIPELINE_NODE* pPipe)
+{
+    for (uint32_t i = 0; i < pPipe->cbStateCI.attachmentCount; i++) {
+        if (0 != pPipe->pAttachments[i].channelWriteMask) {
+            pCB->status |= CBSTATUS_COLOR_BLEND_WRITE_ENABLE;
+        }
+    }
+    if (pPipe->dsStateCI.depthWriteEnable) {
+        pCB->status |= CBSTATUS_DEPTH_STENCIL_WRITE_ENABLE;
+    }
+}
+// Set dyn-state related status bits for an object node
+static void set_cb_dyn_status(GLOBAL_CB_NODE* pNode, VkStateBindPoint stateBindPoint) {
+    if (stateBindPoint == VK_STATE_BIND_POINT_VIEWPORT) {
+        pNode->status |= CBSTATUS_VIEWPORT_BOUND;
+    } else if (stateBindPoint == VK_STATE_BIND_POINT_RASTER) {
+        pNode->status |= CBSTATUS_RASTER_BOUND;
+    } else if (stateBindPoint == VK_STATE_BIND_POINT_COLOR_BLEND) {
+        pNode->status |= CBSTATUS_COLOR_BLEND_BOUND;
+    } else if (stateBindPoint == VK_STATE_BIND_POINT_DEPTH_STENCIL) {
+        pNode->status |= CBSTATUS_DEPTH_STENCIL_BOUND;
+    }
+}
 // Set the last bound dynamic state of given type
-// TODO : Need to track this per cmdBuffer and correlate cmdBuffer for Draw w/ last bound for that cmdBuffer?
 static void setLastBoundDynamicState(const VkCmdBuffer cmdBuffer, const VkDynamicStateObject state, const VkStateBindPoint sType)
 {
     GLOBAL_CB_NODE* pCB = getCBNode(cmdBuffer);
     if (pCB) {
         updateCBTracking(cmdBuffer);
         loader_platform_thread_lock_mutex(&globalLock);
+        set_cb_dyn_status(pCB, sType);
         addCmd(pCB, CMD_BINDDYNAMICSTATEOBJECT);
         if (dynamicStateMap.find(state) == dynamicStateMap.end()) {
             char str[1024];
@@ -1872,6 +1927,8 @@
         GLOBAL_CB_NODE* pCB = getCBNode(cmdBuffer);
         if (pCB) {
             pCB->state = CB_UPDATE_COMPLETE;
+            // Reset CB status flags
+            pCB->status = 0;
             printCB(cmdBuffer);
         }
         else {
@@ -2006,10 +2063,14 @@
 VK_LAYER_EXPORT void VKAPI vkCmdDraw(VkCmdBuffer cmdBuffer, uint32_t firstVertex, uint32_t vertexCount, uint32_t firstInstance, uint32_t instanceCount)
 {
     GLOBAL_CB_NODE* pCB = getCBNode(cmdBuffer);
+    bool32_t valid = VK_FALSE;
     if (pCB) {
         updateCBTracking(cmdBuffer);
         addCmd(pCB, CMD_DRAW);
         pCB->drawCount[DRAW]++;
+        loader_platform_thread_lock_mutex(&globalLock);
+        valid = validate_draw_state_flags(cmdBuffer);
+        loader_platform_thread_unlock_mutex(&globalLock);
         char str[1024];
         sprintf(str, "vkCmdDraw() call #%lu, reporting DS state:", g_drawCount[DRAW]++);
         layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, cmdBuffer, 0, DRAWSTATE_NONE, "DS", str);
@@ -2020,16 +2081,21 @@
         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.CmdDraw(cmdBuffer, firstVertex, vertexCount, firstInstance, instanceCount);
+    if (valid)
+        nextTable.CmdDraw(cmdBuffer, firstVertex, vertexCount, firstInstance, instanceCount);
 }
 
 VK_LAYER_EXPORT void VKAPI vkCmdDrawIndexed(VkCmdBuffer cmdBuffer, uint32_t firstIndex, uint32_t indexCount, int32_t vertexOffset, uint32_t firstInstance, uint32_t instanceCount)
 {
     GLOBAL_CB_NODE* pCB = getCBNode(cmdBuffer);
+    bool32_t valid = VK_FALSE;
     if (pCB) {
         updateCBTracking(cmdBuffer);
         addCmd(pCB, CMD_DRAWINDEXED);
         pCB->drawCount[DRAW_INDEXED]++;
+        loader_platform_thread_lock_mutex(&globalLock);
+        valid = validate_draw_state_flags(cmdBuffer);
+        loader_platform_thread_unlock_mutex(&globalLock);
         char str[1024];
         sprintf(str, "vkCmdDrawIndexed() call #%lu, reporting DS state:", g_drawCount[DRAW_INDEXED]++);
         layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, cmdBuffer, 0, DRAWSTATE_NONE, "DS", str);
@@ -2040,16 +2106,21 @@
         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.CmdDrawIndexed(cmdBuffer, firstIndex, indexCount, vertexOffset, firstInstance, instanceCount);
+    if (valid)
+        nextTable.CmdDrawIndexed(cmdBuffer, firstIndex, indexCount, vertexOffset, firstInstance, instanceCount);
 }
 
 VK_LAYER_EXPORT void VKAPI vkCmdDrawIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride)
 {
     GLOBAL_CB_NODE* pCB = getCBNode(cmdBuffer);
+    bool32_t valid = VK_FALSE;
     if (pCB) {
         updateCBTracking(cmdBuffer);
         addCmd(pCB, CMD_DRAWINDIRECT);
         pCB->drawCount[DRAW_INDIRECT]++;
+        loader_platform_thread_lock_mutex(&globalLock);
+        valid = validate_draw_state_flags(cmdBuffer);
+        loader_platform_thread_unlock_mutex(&globalLock);
         char str[1024];
         sprintf(str, "vkCmdDrawIndirect() call #%lu, reporting DS state:", g_drawCount[DRAW_INDIRECT]++);
         layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, cmdBuffer, 0, DRAWSTATE_NONE, "DS", str);
@@ -2060,16 +2131,21 @@
         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.CmdDrawIndirect(cmdBuffer, buffer, offset, count, stride);
+    if (valid)
+        nextTable.CmdDrawIndirect(cmdBuffer, buffer, offset, count, stride);
 }
 
 VK_LAYER_EXPORT void VKAPI vkCmdDrawIndexedIndirect(VkCmdBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride)
 {
     GLOBAL_CB_NODE* pCB = getCBNode(cmdBuffer);
+    bool32_t valid = VK_FALSE;
     if (pCB) {
         updateCBTracking(cmdBuffer);
         addCmd(pCB, CMD_DRAWINDEXEDINDIRECT);
         pCB->drawCount[DRAW_INDEXED_INDIRECT]++;
+        loader_platform_thread_lock_mutex(&globalLock);
+        valid = validate_draw_state_flags(cmdBuffer);
+        loader_platform_thread_unlock_mutex(&globalLock);
         char str[1024];
         sprintf(str, "vkCmdDrawIndexedIndirect() call #%lu, reporting DS state:", g_drawCount[DRAW_INDEXED_INDIRECT]++);
         layerCbMsg(VK_DBG_MSG_UNKNOWN, VK_VALIDATION_LEVEL_0, cmdBuffer, 0, DRAWSTATE_NONE, "DS", str);
@@ -2080,7 +2156,8 @@
         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.CmdDrawIndexedIndirect(cmdBuffer, buffer, offset, count, stride);
+    if (valid)
+        nextTable.CmdDrawIndexedIndirect(cmdBuffer, buffer, offset, count, stride);
 }
 
 VK_LAYER_EXPORT void VKAPI vkCmdDispatch(VkCmdBuffer cmdBuffer, uint32_t x, uint32_t y, uint32_t z)