From 4d43c6ad27495c79dbdde0b3504727a4907ac783 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 19 May 2017 09:49:49 -0700 Subject: [PATCH] layers: Use CB invalidation mechanism for VU135. Makes more sense to use command buffer invalidation to drive this than maintaining parallel logic and only picking this up at draw time. Drops some additional TODOs in around areas that need some more work to make this nice. --- layers/core_validation.cpp | 29 ++++++++++++++--------------- layers/core_validation_types.h | 4 +--- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 172cdbf08a..877c50896b 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 const &cb_nodes, VK_OBJECT obj) { +void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set 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_setstate = 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 16548682b0..0cb6ecee4b 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 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 updateImages; std::unordered_set 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 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 const &cb_nodes, VK_OBJECT obj); +void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set 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);