layers: Add DrawState check to warn on Clears prior to Draw cmds
If a CmdClear*Attachment for Color or DS is added to CmdBuffer and no Draw cmds have yet been issued, a warning is issued as LOAD_OP_CLEAR is preferred method for clearing these attachments prior to a Draw.
Added a test to verify that this case is correctly flagged.
Updated viewMap to contain create info for Color and DS as well as generic Images.
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index 1f8b405..79c1773 100644
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -62,7 +62,7 @@
static instance_table_map draw_state_instance_table_map;
unordered_map<VkSampler, SAMPLER_NODE*> sampleMap;
-unordered_map<VkImageView, IMAGE_NODE*> imageMap;
+unordered_map<VkNonDispatchable, IMAGE_NODE*> viewCreateInfoMap;
unordered_map<VkBufferView, BUFFER_NODE*> bufferMap;
unordered_map<VkDynamicStateObject, DYNAMIC_STATE_NODE*> dynamicStateMap;
unordered_map<VkPipeline, PIPELINE_NODE*> pipelineMap;
@@ -173,10 +173,12 @@
return "CMD_FILLBUFFER";
case CMD_CLEARCOLORIMAGE:
return "CMD_CLEARCOLORIMAGE";
- case CMD_CLEARCOLORIMAGERAW:
- return "CMD_CLEARCOLORIMAGERAW";
- case CMD_CLEARDEPTHSTENCIL:
- return "CMD_CLEARDEPTHSTENCIL";
+ case CMD_CLEARCOLORATTACHMENT:
+ return "CMD_CLEARCOLORATTACHMENT";
+ case CMD_CLEARDEPTHSTENCILIMAGE:
+ return "CMD_CLEARDEPTHSTENCILIMAGE";
+ case CMD_CLEARDEPTHSTENCILATTACHMENT:
+ return "CMD_CLEARDEPTHSTENCILATTACHMENT";
case CMD_RESOLVEIMAGE:
return "CMD_RESOLVEIMAGE";
case CMD_SETEVENT:
@@ -301,23 +303,23 @@
static VkImageViewCreateInfo* getImageViewCreateInfo(VkImageView view)
{
loader_platform_thread_lock_mutex(&globalLock);
- if (imageMap.find(view) == imageMap.end()) {
+ if (viewCreateInfoMap.find(view) == viewCreateInfoMap.end()) {
loader_platform_thread_unlock_mutex(&globalLock);
return NULL;
} else {
loader_platform_thread_unlock_mutex(&globalLock);
- return &imageMap[view]->createInfo;
+ return &viewCreateInfoMap[view]->createInfo.ivci;
}
}
// Free all image nodes
static void deleteImages()
{
- if (imageMap.size() <= 0)
+ if (viewCreateInfoMap.size() <= 0)
return;
- for (unordered_map<VkImageView, IMAGE_NODE*>::iterator ii=imageMap.begin(); ii!=imageMap.end(); ++ii) {
+ for (auto ii=viewCreateInfoMap.begin(); ii!=viewCreateInfoMap.end(); ++ii) {
delete (*ii).second;
}
- imageMap.clear();
+ viewCreateInfoMap.clear();
}
static VkBufferViewCreateInfo* getBufferViewCreateInfo(VkBufferView view)
{
@@ -341,7 +343,7 @@
bufferMap.clear();
}
static GLOBAL_CB_NODE* getCBNode(VkCmdBuffer cb);
-
+// Update global ptrs to reflect that specified cmdBuffer has been used
static void updateCBTracking(VkCmdBuffer cb)
{
g_lastCmdBuffer[getTIDIndex()] = cb;
@@ -359,6 +361,14 @@
g_lastTouchedCBIndex = g_lastTouchedCBIndex % NUM_COMMAND_BUFFERS_TO_DISPLAY;
loader_platform_thread_unlock_mutex(&globalLock);
}
+static bool32_t hasDrawCmd(GLOBAL_CB_NODE* pCB)
+{
+ for (uint32_t i=0; i<NUM_DRAW_TYPES; i++) {
+ if (pCB->drawCount[i])
+ return VK_TRUE;
+ }
+ return VK_FALSE;
+}
// Check object status for selected flag state
static bool32_t validate_status(GLOBAL_CB_NODE* pNode, CBStatusFlags enable_mask, CBStatusFlags status_mask, CBStatusFlags status_flag, VkFlags msg_flags, DRAW_STATE_ERROR error_code, const char* fail_msg)
{
@@ -1489,9 +1499,34 @@
if (VK_SUCCESS == result) {
loader_platform_thread_lock_mutex(&globalLock);
IMAGE_NODE *pNewNode = new IMAGE_NODE;
- pNewNode->image = *pView;
- pNewNode->createInfo = *pCreateInfo;
- imageMap[*pView] = pNewNode;
+ pNewNode->createInfo.ivci = *pCreateInfo;
+ viewCreateInfoMap[*pView] = pNewNode;
+ loader_platform_thread_unlock_mutex(&globalLock);
+ }
+ return result;
+}
+
+VK_LAYER_EXPORT VkResult VKAPI vkCreateColorAttachmentView(VkDevice device, const VkColorAttachmentViewCreateInfo* pCreateInfo, VkColorAttachmentView* pView)
+{
+ VkResult result = get_dispatch_table(draw_state_device_table_map, device)->CreateColorAttachmentView(device, pCreateInfo, pView);
+ if (VK_SUCCESS == result) {
+ loader_platform_thread_lock_mutex(&globalLock);
+ IMAGE_NODE *pNewNode = new IMAGE_NODE;
+ pNewNode->createInfo.cvci = *pCreateInfo;
+ viewCreateInfoMap[*pView] = pNewNode;
+ loader_platform_thread_unlock_mutex(&globalLock);
+ }
+ return result;
+}
+
+VK_LAYER_EXPORT VkResult VKAPI vkCreateDepthStencilView(VkDevice device, const VkDepthStencilViewCreateInfo* pCreateInfo, VkDepthStencilView* pView)
+{
+ VkResult result = get_dispatch_table(draw_state_device_table_map, device)->CreateDepthStencilView(device, pCreateInfo, pView);
+ if (VK_SUCCESS == result) {
+ loader_platform_thread_lock_mutex(&globalLock);
+ IMAGE_NODE *pNewNode = new IMAGE_NODE;
+ pNewNode->createInfo.dsvci = *pCreateInfo;
+ viewCreateInfoMap[*pView] = pNewNode;
loader_platform_thread_unlock_mutex(&globalLock);
}
return result;
@@ -2222,6 +2257,59 @@
}
}
+VK_LAYER_EXPORT void VKAPI vkCmdClearColorAttachment(
+ VkCmdBuffer cmdBuffer,
+ uint32_t colorAttachment,
+ VkImageLayout imageLayout,
+ const VkClearColorValue* pColor,
+ uint32_t rectCount,
+ const VkRect3D* pRects)
+{
+ GLOBAL_CB_NODE* pCB = getCBNode(cmdBuffer);
+ if (pCB) {
+ if (pCB->state == CB_UPDATE_ACTIVE) {
+ // Warn if this is issued prior to Draw Cmd
+ if (!hasDrawCmd(pCB)) {
+ log_msg(mdd(cmdBuffer), VK_DBG_REPORT_WARN_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, cmdBuffer, 0, DRAWSTATE_CLEAR_CMD_BEFORE_DRAW, "DS",
+ "vkCmdClearColorAttachment() issued on CB object 0x%" PRIxLEAST64 " prior to any Draw Cmds."
+ " It is recommended you use RenderPass LOAD_OP_CLEAR on Color Attachments prior to any Draw.", reinterpret_cast<VkUintPtrLeast64>(cmdBuffer));
+ }
+ updateCBTracking(cmdBuffer);
+ addCmd(pCB, CMD_CLEARCOLORATTACHMENT);
+ get_dispatch_table(draw_state_device_table_map, cmdBuffer)->CmdClearColorAttachment(cmdBuffer, colorAttachment, imageLayout, pColor, rectCount, pRects);
+ } else {
+ report_error_no_cb_begin(cmdBuffer, "vkCmdBindIndexBuffer()");
+ }
+ }
+}
+
+VK_LAYER_EXPORT void VKAPI vkCmdClearDepthStencilAttachment(
+ VkCmdBuffer cmdBuffer,
+ VkImageAspectFlags imageAspectMask,
+ VkImageLayout imageLayout,
+ float depth,
+ uint32_t stencil,
+ uint32_t rectCount,
+ const VkRect3D* pRects)
+{
+ GLOBAL_CB_NODE* pCB = getCBNode(cmdBuffer);
+ if (pCB) {
+ if (pCB->state == CB_UPDATE_ACTIVE) {
+ // Warn if this is issued prior to Draw Cmd
+ if (!hasDrawCmd(pCB)) {
+ log_msg(mdd(cmdBuffer), VK_DBG_REPORT_WARN_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, cmdBuffer, 0, DRAWSTATE_CLEAR_CMD_BEFORE_DRAW, "DS",
+ "vkCmdClearDepthStencilAttachment() issued on CB object 0x%" PRIxLEAST64 " prior to any Draw Cmds."
+ " It is recommended you use RenderPass LOAD_OP_CLEAR on DS Attachment prior to any Draw.", reinterpret_cast<VkUintPtrLeast64>(cmdBuffer));
+ }
+ updateCBTracking(cmdBuffer);
+ addCmd(pCB, CMD_CLEARDEPTHSTENCILATTACHMENT);
+ get_dispatch_table(draw_state_device_table_map, cmdBuffer)->CmdClearDepthStencilAttachment(cmdBuffer, imageAspectMask, imageLayout, depth, stencil, rectCount, pRects);
+ } else {
+ report_error_no_cb_begin(cmdBuffer, "vkCmdBindIndexBuffer()");
+ }
+ }
+}
+
VK_LAYER_EXPORT void VKAPI vkCmdClearColorImage(
VkCmdBuffer cmdBuffer,
VkImage image, VkImageLayout imageLayout,
@@ -2249,7 +2337,7 @@
if (pCB) {
if (pCB->state == CB_UPDATE_ACTIVE) {
updateCBTracking(cmdBuffer);
- addCmd(pCB, CMD_CLEARDEPTHSTENCIL);
+ addCmd(pCB, CMD_CLEARDEPTHSTENCILIMAGE);
get_dispatch_table(draw_state_device_table_map, cmdBuffer)->CmdClearDepthStencilImage(cmdBuffer, image, imageLayout, depth, stencil, rangeCount, pRanges);
} else {
report_error_no_cb_begin(cmdBuffer, "vkCmdBindIndexBuffer()");
@@ -2590,6 +2678,10 @@
return (void*) vkCreateBufferView;
if (!strcmp(funcName, "vkCreateImageView"))
return (void*) vkCreateImageView;
+ if (!strcmp(funcName, "vkCreateColorAttachmentView"))
+ return (void*) vkCreateColorAttachmentView;
+ if (!strcmp(funcName, "vkCreateDepthStencilView"))
+ return (void*) vkCreateDepthStencilView;
if (!strcmp(funcName, "vkCreateGraphicsPipeline"))
return (void*) vkCreateGraphicsPipeline;
if (!strcmp(funcName, "vkCreateGraphicsPipelineDerivative"))
@@ -2662,6 +2754,10 @@
return (void*) vkCmdClearColorImage;
if (!strcmp(funcName, "vkCmdClearDepthStencilImage"))
return (void*) vkCmdClearDepthStencilImage;
+ if (!strcmp(funcName, "vkCmdClearColorAttachment"))
+ return (void*) vkCmdClearColorAttachment;
+ if (!strcmp(funcName, "vkCmdClearDepthStencilAttachment"))
+ return (void*) vkCmdClearDepthStencilAttachment;
if (!strcmp(funcName, "vkCmdResolveImage"))
return (void*) vkCmdResolveImage;
if (!strcmp(funcName, "vkCmdSetEvent"))