diff options
Diffstat (limited to 'layers/core_validation.cpp')
| -rw-r--r-- | layers/core_validation.cpp | 96 |
1 files changed, 73 insertions, 23 deletions
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index c655fda6..828aef1f 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3055,8 +3055,11 @@ static bool ValidatePipelineDrawtimeState(layer_data const *my_data, LAST_BOUND_ } // Validate overall state at the time of a draw call -static bool ValidateAndUpdateDrawState(layer_data *my_data, GLOBAL_CB_NODE *cb_node, const bool indexedDraw, - const VkPipelineBindPoint bindPoint, const char *function) { +static bool ValidateDrawState( + layer_data *my_data, GLOBAL_CB_NODE *cb_node, const bool indexedDraw, const VkPipelineBindPoint bindPoint, + vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>> + *activeSetBindingsPairs, + std::unordered_set<uint32_t> *active_bindings, const char *function) { bool result = false; auto const &state = cb_node->lastBound[bindPoint]; PIPELINE_STATE *pPipe = state.pipeline_state; @@ -3078,9 +3081,6 @@ static bool ValidateAndUpdateDrawState(layer_data *my_data, GLOBAL_CB_NODE *cb_n string errorString; auto pipeline_layout = pPipe->pipeline_layout; - // Need a vector (vs. std::set) of active Sets for dynamicOffset validation in case same set bound w/ different offsets - vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>> - activeSetBindingsPairs; for (auto & setBindingPair : pPipe->active_slots) { uint32_t setIndex = setBindingPair.first; // If valid set is not bound throw an error @@ -3104,18 +3104,15 @@ static bool ValidateAndUpdateDrawState(layer_data *my_data, GLOBAL_CB_NODE *cb_n // Pull the set node cvdescriptorset::DescriptorSet *pSet = state.boundDescriptorSets[setIndex]; // Gather active bindings - std::unordered_set<uint32_t> bindings; for (auto binding : setBindingPair.second) { - bindings.insert(binding.first); + active_bindings->insert(binding.first); } - // Bind this set and its active descriptor resources to the command buffer - pSet->BindCommandBuffer(cb_node, bindings); // Save vector of all active sets to verify dynamicOffsets below - activeSetBindingsPairs.push_back(std::make_tuple(pSet, setBindingPair.second, &state.dynamicOffsets[setIndex])); + activeSetBindingsPairs->push_back(std::make_tuple(pSet, setBindingPair.second, &state.dynamicOffsets[setIndex])); // Make sure set has been updated if it has no immutable samplers // If it has immutable samplers, we'll flag error later as needed depending on binding if (!pSet->IsUpdated()) { - for (auto binding : bindings) { + for (auto binding : *active_bindings) { if (!pSet->GetImmutableSamplerPtrFromBinding(binding)) { result |= log_msg( my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, @@ -3128,9 +3125,8 @@ static bool ValidateAndUpdateDrawState(layer_data *my_data, GLOBAL_CB_NODE *cb_n } } } - // For given active slots, verify any dynamic descriptors and record updated images & buffers - result |= ValidateDrawtimeDescriptorState(my_data, cb_node, activeSetBindingsPairs, function); - UpdateDrawtimeDescriptorState(my_data, cb_node, activeSetBindingsPairs); + // For given active slots verify any dynamic descriptors + result |= ValidateDrawtimeDescriptorState(my_data, cb_node, *activeSetBindingsPairs, function); } // Check general pipeline state that needs to be validated at drawtime @@ -3140,6 +3136,26 @@ static bool ValidateAndUpdateDrawState(layer_data *my_data, GLOBAL_CB_NODE *cb_n return result; } +static void UpdateDrawState( + layer_data *my_data, GLOBAL_CB_NODE *cb_state, const VkPipelineBindPoint bindPoint, + vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>> + *active_set_binding_pairs, + std::unordered_set<uint32_t> *active_bindings) { + auto const &state = cb_state->lastBound[bindPoint]; + PIPELINE_STATE *pPipe = state.pipeline_state; + if (VK_NULL_HANDLE != state.pipeline_layout.layout) { + for (const auto &setBindingPair : pPipe->active_slots) { + uint32_t setIndex = setBindingPair.first; + // Pull the set node + cvdescriptorset::DescriptorSet *pSet = state.boundDescriptorSets[setIndex]; + // Bind this set and its active descriptor resources to the command buffer + pSet->BindCommandBuffer(cb_state, active_bindings); + } + // For given active slots record updated images & buffers + UpdateDrawtimeDescriptorState(my_data, cb_state, *active_set_binding_pairs); + } +} + // Validate HW line width capabilities prior to setting requested line width. static bool verifyLineWidth(layer_data *my_data, DRAW_STATE_ERROR dsError, const uint64_t &target, float lineWidth) { bool skip_call = false; @@ -8038,9 +8054,14 @@ static void MarkStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_N } } -static void PostCallRecordCmdDraw(layer_data *dev_data, GLOBAL_CB_NODE *cb_state) { +static void PostCallRecordCmdDraw( + layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point, + vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>> + *active_set_bindings_pairs, + std::unordered_set<uint32_t> *active_bindings) { MarkStoreImagesAndBuffersAsWritten(dev_data, cb_state); updateResourceTrackingOnDraw(cb_state); + UpdateDrawState(dev_data, cb_state, bind_point, active_set_bindings_pairs, active_bindings); UpdateCmdBufferLastCmd(dev_data, cb_state, CMD_DRAW); cb_state->drawCount[DRAW]++; } @@ -8049,13 +8070,18 @@ VKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t verte uint32_t firstVertex, uint32_t firstInstance) { bool skip_call = false; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); + // Need a vector (vs. std::set) of active Sets for dynamicOffset validation in case same set bound w/ different offsets + vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>> + active_set_bindings_pairs; + std::unordered_set<uint32_t> active_bindings; std::unique_lock<std::mutex> lock(global_lock); GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); if (pCB) { skip_call |= ValidateCmd(dev_data, pCB, CMD_DRAW, "vkCmdDraw()"); // TODO : Split this into validate/state update. Also at state update time, set bool to note if/when // vtx buffers are consumed and only flag perf warning if bound vtx buffers have not been consumed - skip_call |= ValidateAndUpdateDrawState(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDraw"); + skip_call |= ValidateDrawState(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, + &active_bindings, "vkCmdDraw"); // TODO : Do we need to do this anymore? skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, @@ -8069,7 +8095,7 @@ VKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t verte if (!skip_call) { dev_data->dispatch_table.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance); lock.lock(); - PostCallRecordCmdDraw(dev_data, pCB); + PostCallRecordCmdDraw(dev_data, pCB, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, &active_bindings); lock.unlock(); } } @@ -8078,6 +8104,9 @@ VKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_ uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) { layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); + vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>> + active_set_bindings_pairs; + std::unordered_set<uint32_t> active_bindings; bool skip_call = false; std::unique_lock<std::mutex> lock(global_lock); GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); @@ -8085,7 +8114,9 @@ VKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_ skip_call |= ValidateCmd(dev_data, pCB, CMD_DRAWINDEXED, "vkCmdDrawIndexed()"); UpdateCmdBufferLastCmd(dev_data, pCB, CMD_DRAWINDEXED); pCB->drawCount[DRAW_INDEXED]++; - skip_call |= ValidateAndUpdateDrawState(dev_data, pCB, true, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDrawIndexed"); + skip_call |= ValidateDrawState(dev_data, pCB, true, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, + &active_bindings, "vkCmdDrawIndexed"); + UpdateDrawState(dev_data, pCB, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, &active_bindings); MarkStoreImagesAndBuffersAsWritten(dev_data, pCB); skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, @@ -8105,6 +8136,9 @@ VKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_ VKAPI_ATTR void VKAPI_CALL CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) { layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); + vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>> + active_set_bindings_pairs; + std::unordered_set<uint32_t> active_bindings; bool skip_call = false; std::unique_lock<std::mutex> lock(global_lock); @@ -8116,7 +8150,9 @@ CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize off skip_call |= ValidateCmd(dev_data, cb_node, CMD_DRAWINDIRECT, "vkCmdDrawIndirect()"); UpdateCmdBufferLastCmd(dev_data, cb_node, CMD_DRAWINDIRECT); cb_node->drawCount[DRAW_INDIRECT]++; - skip_call |= ValidateAndUpdateDrawState(dev_data, cb_node, false, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDrawIndirect"); + skip_call |= ValidateDrawState(dev_data, cb_node, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, + &active_bindings, "vkCmdDrawIndirect"); + UpdateDrawState(dev_data, cb_node, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, &active_bindings); MarkStoreImagesAndBuffersAsWritten(dev_data, cb_node); skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, @@ -8139,6 +8175,9 @@ VKAPI_ATTR void VKAPI_CALL CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) { bool skip_call = false; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); + vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>> + active_set_bindings_pairs; + std::unordered_set<uint32_t> active_bindings; std::unique_lock<std::mutex> lock(global_lock); auto cb_node = getCBNode(dev_data, commandBuffer); @@ -8149,8 +8188,9 @@ CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceS skip_call |= ValidateCmd(dev_data, cb_node, CMD_DRAWINDEXEDINDIRECT, "vkCmdDrawIndexedIndirect()"); UpdateCmdBufferLastCmd(dev_data, cb_node, CMD_DRAWINDEXEDINDIRECT); cb_node->drawCount[DRAW_INDEXED_INDIRECT]++; - skip_call |= - ValidateAndUpdateDrawState(dev_data, cb_node, true, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDrawIndexedIndirect"); + skip_call |= ValidateDrawState(dev_data, cb_node, true, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, + &active_bindings, "vkCmdDrawIndexedIndirect"); + UpdateDrawState(dev_data, cb_node, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, &active_bindings); MarkStoreImagesAndBuffersAsWritten(dev_data, cb_node); skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer), __LINE__, @@ -8172,10 +8212,15 @@ CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceS VKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) { bool skip_call = false; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); + vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>> + active_set_bindings_pairs; + std::unordered_set<uint32_t> active_bindings; std::unique_lock<std::mutex> lock(global_lock); GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); if (pCB) { - skip_call |= ValidateAndUpdateDrawState(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_COMPUTE, "vkCmdDispatch"); + skip_call |= ValidateDrawState(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_COMPUTE, &active_set_bindings_pairs, + &active_bindings, "vkCmdDispatch"); + UpdateDrawState(dev_data, pCB, VK_PIPELINE_BIND_POINT_COMPUTE, &active_set_bindings_pairs, &active_bindings); MarkStoreImagesAndBuffersAsWritten(dev_data, pCB); skip_call |= ValidateCmd(dev_data, pCB, CMD_DISPATCH, "vkCmdDispatch()"); UpdateCmdBufferLastCmd(dev_data, pCB, CMD_DISPATCH); @@ -8190,6 +8235,9 @@ VKAPI_ATTR void VKAPI_CALL CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) { bool skip_call = false; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); + vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>> + active_set_bindings_pairs; + std::unordered_set<uint32_t> active_bindings; std::unique_lock<std::mutex> lock(global_lock); auto cb_node = getCBNode(dev_data, commandBuffer); @@ -8197,7 +8245,9 @@ CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize if (cb_node && buffer_state) { skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdDispatchIndirect()"); AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_state); - skip_call |= ValidateAndUpdateDrawState(dev_data, cb_node, false, VK_PIPELINE_BIND_POINT_COMPUTE, "vkCmdDispatchIndirect"); + skip_call |= ValidateDrawState(dev_data, cb_node, false, VK_PIPELINE_BIND_POINT_COMPUTE, &active_set_bindings_pairs, + &active_bindings, "vkCmdDispatchIndirect"); + UpdateDrawState(dev_data, cb_node, VK_PIPELINE_BIND_POINT_COMPUTE, &active_set_bindings_pairs, &active_bindings); MarkStoreImagesAndBuffersAsWritten(dev_data, cb_node); skip_call |= ValidateCmd(dev_data, cb_node, CMD_DISPATCHINDIRECT, "vkCmdDispatchIndirect()"); UpdateCmdBufferLastCmd(dev_data, cb_node, CMD_DISPATCHINDIRECT); |
