diff options
| author | Tobin Ehlis <tobine@google.com> | 2016-11-21 08:31:01 -0700 |
|---|---|---|
| committer | Tobin Ehlis <tobine@google.com> | 2016-11-21 08:59:44 -0700 |
| commit | 92d20e9c602e6cbb968989d82e8bc677daa1d61c (patch) | |
| tree | 6ed2006445b55f23234c17385b166a8b50a1dc9d | |
| parent | 0c64542997555318f2b54a8661e6ce566e1cf56d (diff) | |
| download | usermoji-92d20e9c602e6cbb968989d82e8bc677daa1d61c.tar.xz | |
layers:Warn on cmd buffer invalidate
From Mikko Strandborg
When a resource gets deleted, any command buffer that references it
gets invalidated, and an error gets thrown whenever that command buffer
is submitted. However, for a developer, it's quite hard to deduce what
exactly caused that to happen. This patch emits a warning whenever a
command buffer that's in CB_RECORDING state (meaning that it has had
its vkBeginCommandBuffer called but not End). This way the developer
can set a breakpoint on that to see exactly what causes the buffer to
be invalidated.
Destroying a resource that's being used in an open command buffer is
almost certainly a bug, but there might still be cases where it might
be valid behavior (for example, when the application decides to abort
an operation), therefore it's not an error but a warning instead.
| -rw-r--r-- | layers/core_validation.cpp | 31 | ||||
| -rw-r--r-- | layers/core_validation_types.h | 2 | ||||
| -rw-r--r-- | layers/descriptor_sets.cpp | 2 |
3 files changed, 20 insertions, 15 deletions
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index e2be92b0..4a081eac 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5181,7 +5181,7 @@ static void PostCallRecordFreeMemory(layer_data *dev_data, VkDeviceMemory mem, D } } // Any bound cmd buffers are now invalid - invalidateCommandBuffers(mem_info->cb_bindings, obj_struct); + invalidateCommandBuffers(dev_data, mem_info->cb_bindings, obj_struct); dev_data->memObjMap.erase(mem); } @@ -5495,7 +5495,7 @@ static bool PreCallValidateDestroyEvent(layer_data *dev_data, VkEvent event, EVE } static void PostCallRecordDestroyEvent(layer_data *dev_data, VkEvent event, EVENT_STATE *event_state, VK_OBJECT obj_struct) { - invalidateCommandBuffers(event_state->cb_bindings, obj_struct); + invalidateCommandBuffers(dev_data, event_state->cb_bindings, obj_struct); dev_data->eventMap.erase(event); } @@ -5523,7 +5523,7 @@ DestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallb VK_OBJECT obj_struct = {reinterpret_cast<uint64_t &>(queryPool), VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT}; skip |= ValidateObjectNotInUse(dev_data, qp_node, obj_struct, VALIDATION_ERROR_01012); // Any bound cmd buffers are now invalid - invalidateCommandBuffers(qp_node->cb_bindings, obj_struct); + invalidateCommandBuffers(dev_data, qp_node->cb_bindings, obj_struct); } if (!skip) { dev_data->queryPoolMap.erase(queryPool); @@ -5771,7 +5771,7 @@ VKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer, auto buffer_state = getBufferState(dev_data, buffer); if (buffer_state) { // Any bound cmd buffers are now invalid - invalidateCommandBuffers(buffer_state->cb_bindings, + invalidateCommandBuffers(dev_data, buffer_state->cb_bindings, {reinterpret_cast<uint64_t &>(buffer_state->buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT}); for (auto mem_binding : buffer_state->GetBoundMemory()) { auto mem_info = getMemObjInfo(dev_data, mem_binding); @@ -5803,7 +5803,7 @@ static bool PreCallValidateDestroyBufferView(layer_data *dev_data, VkBufferView static void PostCallRecordDestroyBufferView(layer_data *dev_data, VkBufferView buffer_view, BUFFER_VIEW_STATE *buffer_view_state, VK_OBJECT obj_struct) { // Any bound cmd buffers are now invalid - invalidateCommandBuffers(buffer_view_state->cb_bindings, obj_struct); + invalidateCommandBuffers(dev_data, buffer_view_state->cb_bindings, obj_struct); dev_data->bufferViewMap.erase(buffer_view); } @@ -5837,7 +5837,7 @@ static bool PreCallValidateDestroyImage(layer_data *dev_data, VkImage image, IMA } static void PostCallRecordDestroyImage(layer_data *dev_data, VkImage image, IMAGE_STATE *image_state, VK_OBJECT obj_struct) { - invalidateCommandBuffers(image_state->cb_bindings, obj_struct); + invalidateCommandBuffers(dev_data, image_state->cb_bindings, obj_struct); // Clean up memory mapping, bindings and range references for image for (auto mem_binding : image_state->GetBoundMemory()) { auto mem_info = getMemObjInfo(dev_data, mem_binding); @@ -6013,7 +6013,7 @@ static bool PreCallValidateDestroyImageView(layer_data *dev_data, VkImageView im static void PostCallRecordDestroyImageView(layer_data *dev_data, VkImageView image_view, IMAGE_VIEW_STATE *image_view_state, VK_OBJECT obj_struct) { // Any bound cmd buffers are now invalid - invalidateCommandBuffers(image_view_state->cb_bindings, obj_struct); + invalidateCommandBuffers(dev_data, image_view_state->cb_bindings, obj_struct); dev_data->imageViewMap.erase(image_view); } @@ -6060,7 +6060,7 @@ static bool PreCallValidateDestroyPipeline(layer_data *dev_data, VkPipeline pipe static void PostCallRecordDestroyPipeline(layer_data *dev_data, VkPipeline pipeline, PIPELINE_STATE *pipeline_state, VK_OBJECT obj_struct) { // Any bound cmd buffers are now invalid - invalidateCommandBuffers(pipeline_state->cb_bindings, obj_struct); + invalidateCommandBuffers(dev_data, pipeline_state->cb_bindings, obj_struct); dev_data->pipelineMap.erase(pipeline); } @@ -6106,7 +6106,7 @@ static void PostCallRecordDestroySampler(layer_data *dev_data, VkSampler sampler VK_OBJECT obj_struct) { // Any bound cmd buffers are now invalid if (sampler_state) - invalidateCommandBuffers(sampler_state->cb_bindings, obj_struct); + invalidateCommandBuffers(dev_data, sampler_state->cb_bindings, obj_struct); dev_data->samplerMap.erase(sampler); } @@ -6148,7 +6148,7 @@ static bool PreCallValidateDestroyDescriptorPool(layer_data *dev_data, VkDescrip static void PostCallRecordDestroyDescriptorPool(layer_data *dev_data, VkDescriptorPool descriptorPool, DESCRIPTOR_POOL_STATE *desc_pool_state, VK_OBJECT obj_struct) { // Any bound cmd buffers are now invalid - invalidateCommandBuffers(desc_pool_state->cb_bindings, obj_struct); + invalidateCommandBuffers(dev_data, desc_pool_state->cb_bindings, obj_struct); // Free sets that were in this pool for (auto ds : desc_pool_state->sets) { freeDescriptorSet(dev_data, ds); @@ -6384,8 +6384,13 @@ VKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, } // For given cb_nodes, invalidate them and track object causing invalidation -void invalidateCommandBuffers(std::unordered_set<GLOBAL_CB_NODE *> cb_nodes, VK_OBJECT obj) { +void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> cb_nodes, VK_OBJECT obj) { 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, + (uint64_t)(cb_node), __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", + "Invalidating a command buffer that's currently being recorded: 0x%" PRIx64 ".", (uint64_t)(cb_node)); + } cb_node->state = CB_INVALID; cb_node->broken_bindings.push_back(obj); } @@ -6406,7 +6411,7 @@ static bool PreCallValidateDestroyFramebuffer(layer_data *dev_data, VkFramebuffe static void PostCallRecordDestroyFramebuffer(layer_data *dev_data, VkFramebuffer framebuffer, FRAMEBUFFER_STATE *framebuffer_state, VK_OBJECT obj_struct) { - invalidateCommandBuffers(framebuffer_state->cb_bindings, obj_struct); + invalidateCommandBuffers(dev_data, framebuffer_state->cb_bindings, obj_struct); dev_data->frameBufferMap.erase(framebuffer); } @@ -6440,7 +6445,7 @@ static bool PreCallValidateDestroyRenderPass(layer_data *dev_data, VkRenderPass static void PostCallRecordDestroyRenderPass(layer_data *dev_data, VkRenderPass render_pass, RENDER_PASS_STATE *rp_state, VK_OBJECT obj_struct) { - invalidateCommandBuffers(rp_state->cb_bindings, obj_struct); + invalidateCommandBuffers(dev_data, rp_state->cb_bindings, obj_struct); dev_data->renderPassMap.erase(render_pass); } diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 44938d03..14ed5e76 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -656,7 +656,7 @@ SAMPLER_STATE *getSamplerState(const layer_data *, VkSampler); IMAGE_VIEW_STATE *getImageViewState(const layer_data *, VkImageView); VkSwapchainKHR getSwapchainFromImage(const layer_data *, VkImage); SWAPCHAIN_NODE *getSwapchainNode(const layer_data *, VkSwapchainKHR); -void invalidateCommandBuffers(std::unordered_set<GLOBAL_CB_NODE *>, VK_OBJECT); +void invalidateCommandBuffers(const layer_data *, std::unordered_set<GLOBAL_CB_NODE *>, VK_OBJECT); bool ValidateMemoryIsBoundToBuffer(const layer_data *, const BUFFER_STATE *, const char *); bool ValidateMemoryIsBoundToImage(const layer_data *, const IMAGE_STATE *, const char *); void AddCommandBufferBindingSampler(GLOBAL_CB_NODE *, SAMPLER_STATE *); diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index f2326dcb..2a6b73e1 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -541,7 +541,7 @@ uint32_t cvdescriptorset::DescriptorSet::GetStorageUpdates(const std::map<uint32 } // Set is being deleted or updates so invalidate all bound cmd buffers void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers() { - core_validation::invalidateCommandBuffers(cb_bindings, + core_validation::invalidateCommandBuffers(device_data_, cb_bindings, {reinterpret_cast<uint64_t &>(set_), VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT}); } // Perform write update in given update struct |
