diff options
| author | Tobin Ehlis <tobin@lunarg.com> | 2015-06-10 12:57:07 -0600 |
|---|---|---|
| committer | Tobin Ehlis <tobin@lunarg.com> | 2015-06-11 16:28:58 -0600 |
| commit | 89ad7526e020e0c968720c684efb098f568fab42 (patch) | |
| tree | ba54a87e0c6decd4f3e735a4d0c96637a788e408 | |
| parent | 7f82164d8ff6ce7a4813693c88d7686a72754c53 (diff) | |
| download | usermoji-89ad7526e020e0c968720c684efb098f568fab42.tar.xz | |
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.
| -rwxr-xr-x | layers/draw_state.cpp | 89 | ||||
| -rw-r--r-- | layers/draw_state.h | 19 | ||||
| -rwxr-xr-x | vk-layer-generate.py | 57 |
3 files changed, 101 insertions, 64 deletions
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp index 4496765a..64b2c3aa 100755 --- a/layers/draw_state.cpp +++ b/layers/draw_state.cpp @@ -312,7 +312,38 @@ static void updateCBTracking(VkCmdBuffer cb) 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 @@ static void resetCB(const VkCmdBuffer cb) 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 @@ VK_LAYER_EXPORT VkResult VKAPI vkEndCommandBuffer(VkCmdBuffer cmdBuffer) 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 vkCmdBindVertexBuffers( 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 @@ VK_LAYER_EXPORT void VKAPI vkCmdDraw(VkCmdBuffer cmdBuffer, uint32_t firstVertex 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 @@ VK_LAYER_EXPORT void VKAPI vkCmdDrawIndexed(VkCmdBuffer cmdBuffer, uint32_t firs 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 @@ VK_LAYER_EXPORT void VKAPI vkCmdDrawIndirect(VkCmdBuffer cmdBuffer, VkBuffer buf 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 @@ VK_LAYER_EXPORT void VKAPI vkCmdDrawIndexedIndirect(VkCmdBuffer cmdBuffer, VkBuf 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) diff --git a/layers/draw_state.h b/layers/draw_state.h index a7b0a202..a7351bb3 100644 --- a/layers/draw_state.h +++ b/layers/draw_state.h @@ -47,6 +47,10 @@ typedef enum _DRAW_STATE_ERROR DRAWSTATE_INVALID_UPDATE_STRUCT, // Struct in DS Update tree is of invalid type DRAWSTATE_NUM_SAMPLES_MISMATCH, // Number of samples in bound PSO does not match number in FB of current RenderPass DRAWSTATE_NO_END_CMD_BUFFER, // Must call vkEndCommandBuffer() before QueueSubmit on that cmdBuffer + DRAWSTATE_VIEWPORT_NOT_BOUND, // Draw submitted with no viewport state object bound + DRAWSTATE_RASTER_NOT_BOUND, // Draw submitted with no raster state object bound + DRAWSTATE_COLOR_BLEND_NOT_BOUND, // Draw submitted with no color blend state object bound when color write enabled + DRAWSTATE_DEPTH_STENCIL_NOT_BOUND, // Draw submitted with no depth-stencil state object bound when depth write enabled } DRAW_STATE_ERROR; typedef enum _DRAW_TYPE @@ -212,6 +216,18 @@ typedef enum _CB_STATE CB_UPDATE_ACTIVE, // BeginCB has been called on this CB CB_UPDATE_COMPLETE // EndCB has been called on this CB } CB_STATE; +// CB Status -- used to track status of various bindings on cmd buffer objects +typedef VkFlags CBStatusFlags; +typedef enum _CBStatusFlagBits +{ + CBSTATUS_NONE = 0x00000000, // No status is set + CBSTATUS_VIEWPORT_BOUND = 0x00000001, // Viewport state object has been bound + CBSTATUS_RASTER_BOUND = 0x00000002, // Raster state object has been bound + CBSTATUS_COLOR_BLEND_WRITE_ENABLE = 0x00000004, // PSO w/ CB Enable set has been bound + CBSTATUS_COLOR_BLEND_BOUND = 0x00000008, // CB state object has been bound + CBSTATUS_DEPTH_STENCIL_WRITE_ENABLE = 0x00000010, // PSO w/ DS Enable set has been bound + CBSTATUS_DEPTH_STENCIL_BOUND = 0x00000020, // DS state object has been bound +} CBStatusFlagBits; // Cmd Buffer Wrapper Struct typedef struct _GLOBAL_CB_NODE { VkCmdBuffer cmdBuffer; @@ -220,7 +236,8 @@ typedef struct _GLOBAL_CB_NODE { VkFence fence; // fence tracking this cmd buffer uint64_t numCmds; // number of cmds in this CB uint64_t drawCount[NUM_DRAW_TYPES]; // Count of each type of draw in this CB - CB_STATE state; // Track if cmd buffer update status + CB_STATE state; // Track cmd buffer update state + CBStatusFlags status; // Track status of various bindings on cmd buffer vector<CMD_NODE*> pCmds; // Currently storing "lastBound" objects on per-CB basis // long-term may want to create caches of "lastBound" states and could have diff --git a/vk-layer-generate.py b/vk-layer-generate.py index 215b246d..b61890ad 100755 --- a/vk-layer-generate.py +++ b/vk-layer-generate.py @@ -986,28 +986,6 @@ class ObjectTrackerSubcommand(Subcommand): header_txt.append(' }') header_txt.append('}') header_txt.append('') - header_txt.append('// Track selected state for an object node') - header_txt.append('static void track_object_status(VkObject vkObj, VkStateBindPoint stateBindPoint) {') - header_txt.append(' if (objMap.find(vkObj) != objMap.end()) {') - header_txt.append(' OBJTRACK_NODE* pNode = objMap[vkObj];') - header_txt.append(' if (stateBindPoint == VK_STATE_BIND_POINT_VIEWPORT) {') - header_txt.append(' pNode->status |= OBJSTATUS_VIEWPORT_BOUND;') - header_txt.append(' } else if (stateBindPoint == VK_STATE_BIND_POINT_RASTER) {') - header_txt.append(' pNode->status |= OBJSTATUS_RASTER_BOUND;') - header_txt.append(' } else if (stateBindPoint == VK_STATE_BIND_POINT_COLOR_BLEND) {') - header_txt.append(' pNode->status |= OBJSTATUS_COLOR_BLEND_BOUND;') - header_txt.append(' } else if (stateBindPoint == VK_STATE_BIND_POINT_DEPTH_STENCIL) {') - header_txt.append(' pNode->status |= OBJSTATUS_DEPTH_STENCIL_BOUND;') - header_txt.append(' }') - header_txt.append(' }') - header_txt.append(' else {') - header_txt.append(' // If we do not find it print an error') - header_txt.append(' char str[1024];') - header_txt.append(' sprintf(str, "Unable to track status for non-existent Command Buffer object 0x%" PRIxLEAST64, reinterpret_cast<VkUintPtrLeast64>(vkObj));') - header_txt.append(' layerCbMsg(VK_DBG_MSG_ERROR, VK_VALIDATION_LEVEL_0, vkObj, 0, OBJTRACK_UNKNOWN_OBJECT, "OBJTRACK", str);') - header_txt.append(' }') - header_txt.append('}') - header_txt.append('') header_txt.append('// Reset selected flag state for an object node') header_txt.append('static void reset_status(VkObject vkObj, VkObjectType objType, ObjectStatusFlags status_flag) {') header_txt.append(' if (objMap.find(vkObj) != objMap.end()) {') @@ -1070,15 +1048,6 @@ class ObjectTrackerSubcommand(Subcommand): header_txt.append(' }') header_txt.append('}') header_txt.append('') - header_txt.append('static bool32_t validate_draw_state_flags(VkObject vkObj) {') - header_txt.append(' bool32_t result1, result2, result3, result4;') - header_txt.append(' result1 = validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_VIEWPORT_BOUND, OBJSTATUS_VIEWPORT_BOUND, VK_DBG_MSG_ERROR, OBJTRACK_VIEWPORT_NOT_BOUND, "Viewport object not bound to this command buffer");') - header_txt.append(' result2 = validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_RASTER_BOUND, OBJSTATUS_RASTER_BOUND, VK_DBG_MSG_ERROR, OBJTRACK_RASTER_NOT_BOUND, "Raster object not bound to this command buffer");') - header_txt.append(' result3 = validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_COLOR_BLEND_BOUND, OBJSTATUS_COLOR_BLEND_BOUND, VK_DBG_MSG_ERROR, OBJTRACK_COLOR_BLEND_NOT_BOUND, "Color-blend object not bound to this command buffer");') - header_txt.append(' result4 = validate_status(vkObj, VK_OBJECT_TYPE_COMMAND_BUFFER, OBJSTATUS_DEPTH_STENCIL_BOUND, OBJSTATUS_DEPTH_STENCIL_BOUND, VK_DBG_MSG_ERROR, OBJTRACK_DEPTH_STENCIL_NOT_BOUND, "Depth-stencil object not bound to this command buffer");') - header_txt.append(' return ((result1 == VK_TRUE) && (result2 == VK_TRUE) && (result3 == VK_TRUE) && (result4 == VK_TRUE));') - header_txt.append('}') - header_txt.append('') return "\n".join(header_txt) def generate_intercept(self, proto, qual): @@ -1096,7 +1065,6 @@ class ObjectTrackerSubcommand(Subcommand): decl = proto.c_func(prefix="vk", attr="VKAPI") param0_name = proto.params[0].name - p0_type = proto.params[0].ty.strip('*').replace('const ', '') using_line = '' create_line = '' destroy_line = '' @@ -1140,22 +1108,6 @@ class ObjectTrackerSubcommand(Subcommand): using_line += ' validate_status(pFences[i], VK_OBJECT_TYPE_FENCE, OBJSTATUS_FENCE_IS_SUBMITTED, OBJSTATUS_FENCE_IS_SUBMITTED, VK_DBG_MSG_ERROR, OBJTRACK_INVALID_FENCE, "Waiting for Unsubmitted Fence");\n' using_line += ' }\n' mutex_unlock = True - elif 'EndCommandBuffer' in proto.name: - using_line = ' loader_platform_thread_lock_mutex(&objLock);\n' - using_line += ' reset_status(cmdBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER, (OBJSTATUS_VIEWPORT_BOUND |\n' - using_line += ' OBJSTATUS_RASTER_BOUND |\n' - using_line += ' OBJSTATUS_COLOR_BLEND_BOUND |\n' - using_line += ' OBJSTATUS_DEPTH_STENCIL_BOUND));\n' - mutex_unlock = True - elif 'CmdBindDynamicStateObject' in proto.name: - using_line = ' loader_platform_thread_lock_mutex(&objLock);\n' - using_line += ' track_object_status(cmdBuffer, stateBindPoint);\n' - mutex_unlock = True - elif 'CmdDraw' in proto.name: - using_line = ' bool32_t valid;\n' - using_line += ' loader_platform_thread_lock_mutex(&objLock);\n' - using_line += ' valid = validate_draw_state_flags(cmdBuffer);\n' - mutex_unlock = True elif 'MapMemory' in proto.name: using_line = ' loader_platform_thread_lock_mutex(&objLock);\n' using_line += ' set_status(mem, VK_OBJECT_TYPE_DEVICE_MEMORY, OBJSTATUS_GPU_MEM_MAPPED);\n' @@ -1256,15 +1208,6 @@ class ObjectTrackerSubcommand(Subcommand): '%s' '%s' '}' % (qual, decl, self.layer_name, ret_val, proto.c_call(), create_line, destroy_line, gpu_state, stmt)) - elif 'CmdDraw' in proto.name: - funcs.append('%s%s\n' - '{\n' - '%s' - ' if (valid == VK_TRUE) {\n' - ' nextTable.%s;\n' - ' }\n' - '%s' - '}' % (qual, decl, using_line, proto.c_call(), stmt)) else: funcs.append('%s%s\n' '{\n' |
