diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 172cdbf08a6ccdc2d8969ada8f03054d57621830..877c50896baeeb7bc40b8786b2b1465fb211d4c3 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -1736,7 +1736,6 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { pCB->drawData.clear(); pCB->currentDrawData.buffers.clear(); pCB->vertex_buffer_used = false; - pCB->primaryCommandBuffer = VK_NULL_HANDLE; // If secondary, invalidate any primary command buffer that may call us. if (pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) { invalidateCommandBuffers(dev_data, @@ -2509,6 +2508,8 @@ static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NO // Track in-use for resources off of primary and any secondary CBs bool skip = false; + // TODO: inline this function into sole caller + // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing // on device skip |= validateCommandBufferSimultaneousUse(dev_data, pCB, current_submit_count); @@ -2517,16 +2518,6 @@ static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NO for (auto pSubCB : pCB->linkedCommandBuffers) { skip |= validateResources(dev_data, pSubCB); - // TODO: replace with invalidateCommandBuffers() at recording. - if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) && - !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { - log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, - __LINE__, VALIDATION_ERROR_31a00092, "DS", - "Commandbuffer 0x%p was submitted with secondary buffer 0x%p but that buffer has subsequently been bound to " - "primary cmd buffer 0x%p and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. %s", - pCB->commandBuffer, pSubCB->commandBuffer, pSubCB->primaryCommandBuffer, - validation_error_map[VALIDATION_ERROR_31a00092]); - } } skip |= validateCommandBufferState(dev_data, pCB, "vkQueueSubmit()", current_submit_count, VALIDATION_ERROR_31a00090); @@ -4109,7 +4100,7 @@ VKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, } // For given cb_nodes, invalidate them and track object causing invalidation -void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj) { +void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj, bool track_invalidator) { for (auto cb_node : cb_nodes) { if (cb_node->state == CB_RECORDING) { log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, @@ -4120,11 +4111,13 @@ void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLO else { cb_node->state = CB_INVALID_COMPLETE; } - cb_node->broken_bindings.push_back(obj); + if (track_invalidator) { + cb_node->broken_bindings.push_back(obj); + } // if secondary, then propagate the invalidation to the primaries that will call us. if (cb_node->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) { - invalidateCommandBuffers(dev_data, cb_node->linkedCommandBuffers, obj); + invalidateCommandBuffers(dev_data, cb_node->linkedCommandBuffers, obj, track_invalidator); } } } @@ -8320,6 +8313,13 @@ VKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uin pCommandBuffers[i], pCB->commandBuffer); pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; } + if (pSubCB->linkedCommandBuffers.size()) { + // TODO: adjust message support so we can report an accurate error message for this. + invalidateCommandBuffers(dev_data, pSubCB->linkedCommandBuffers, + {HandleToUint64(pCommandBuffers[i]), kVulkanObjectTypeCommandBuffer}, + false /* don't track invalidator. we've already complained. */); + // TODO: consistent strategy for removing links. + } } if (!pCB->activeQueries.empty() && !dev_data->enabled_features.inheritedQueries) { skip |= @@ -8336,7 +8336,6 @@ VKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uin for (auto ilm_entry : pSubCB->imageLayoutMap) { SetLayout(dev_data, pCB, ilm_entry.first, ilm_entry.second); } - pSubCB->primaryCommandBuffer = pCB->commandBuffer; pCB->linkedCommandBuffers.insert(pSubCB); pSubCB->linkedCommandBuffers.insert(pCB); for (auto &function : pSubCB->queryUpdates) { diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 16548682b0f0dc786c994b4444a111abdbf61089..0cb6ecee4bbfd96917480721049564aebfe39be1 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -671,7 +671,6 @@ struct GLOBAL_CB_NODE : public BASE_NODE { std::vector<DRAW_DATA> drawData; DRAW_DATA currentDrawData; bool vertex_buffer_used; // Track for perf warning to make sure any bound vtx buffer used - VkCommandBuffer primaryCommandBuffer; // Track images and buffers that are updated by this CB at the point of a draw std::unordered_set<VkImageView> updateImages; std::unordered_set<VkBuffer> updateBuffers; @@ -787,7 +786,6 @@ const PHYS_DEV_PROPERTIES_NODE *GetPhysDevProperties(const layer_data *device_da const VkPhysicalDeviceFeatures *GetEnabledFeatures(const layer_data *device_data); const DeviceExtensions *GetEnabledExtensions(const layer_data *device_data); -void invalidateCommandBuffers(const layer_data *, std::unordered_set<GLOBAL_CB_NODE *> const &, VK_OBJECT); bool ValidateMemoryIsBoundToBuffer(const layer_data *, const BUFFER_STATE *, const char *, UNIQUE_VALIDATION_ERROR_CODE); bool ValidateMemoryIsBoundToImage(const layer_data *, const IMAGE_STATE *, const char *, UNIQUE_VALIDATION_ERROR_CODE); void AddCommandBufferBindingSampler(GLOBAL_CB_NODE *, SAMPLER_STATE *); @@ -796,7 +794,7 @@ void AddCommandBufferBindingImageView(const layer_data *, GLOBAL_CB_NODE *, IMAG void AddCommandBufferBindingBuffer(const layer_data *, GLOBAL_CB_NODE *, BUFFER_STATE *); void AddCommandBufferBindingBufferView(const layer_data *, GLOBAL_CB_NODE *, BUFFER_VIEW_STATE *); bool ValidateObjectNotInUse(const layer_data *dev_data, BASE_NODE *obj_node, VK_OBJECT obj_struct, UNIQUE_VALIDATION_ERROR_CODE error_code); -void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj); +void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj, bool track_invalidator=true); void RemoveImageMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info); void RemoveBufferMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info); bool ClearMemoryObjectBindings(layer_data *dev_data, uint64_t handle, VulkanObjectType type);