From fc39c5b846aecadfc7134ebeb8a26d4a16556f26 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Mon, 16 May 2016 11:23:01 -0600 Subject: layers: GH544 Allow INVALID cmd buffers to be reset BeginCommandBuffer performs an implicit reset of a command buffer. This allows command buffers in the INVALID state to undergo this implicit reset. In order to make sure that an invalid command buffer in the INVALID state has had EndCommandBuffer called, this commit adds a CMD_END command that's inserted at the end of a command. If a command buffer in the INVALID state has had EndCommandBuffer called and it is now having BeginCommandBuffer called, it's ok to implicitly reset the command buffer. buffer's vector of commands. --- layers/core_validation.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 51aaf88d..ebaa6b0d 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3658,6 +3658,7 @@ static bool addCmd(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const CMD_TYP case CMD_UPDATEBUFFER: case CMD_PIPELINEBARRIER: case CMD_EXECUTECOMMANDS: + case CMD_END: break; default: break; @@ -3665,6 +3666,7 @@ static bool addCmd(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const CMD_TYP } if (pCB->state != CB_RECORDING) { skipCall |= report_error_no_cb_begin(my_data, pCB->commandBuffer, caller_name); + } else { skipCall |= validateCmdsInCmdBuffer(my_data, pCB, cmd); CMD_NODE cmdNode = {}; // init cmd node and append to end of cmd LL @@ -6197,7 +6199,7 @@ BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo "vkBeginCommandBuffer(): Cannot call Begin on CB (0x%" PRIxLEAST64 ") in the RECORDING state. Must first call vkEndCommandBuffer().", (uint64_t)commandBuffer); - } else if (CB_RECORDED == pCB->state) { + } else if (CB_RECORDED == pCB->state || (CB_INVALID == pCB->state && CMD_END == pCB->cmds.back().type)) { VkCommandPool cmdPool = pCB->createInfo.commandPool; if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & dev_data->commandPoolMap[cmdPool].createFlags)) { skipCall |= @@ -6251,9 +6253,7 @@ VKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) { // https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/pull/516#discussion_r63013756 skipCall |= insideRenderPass(dev_data, pCB, "vkEndCommandBuffer"); } - if (pCB->state != CB_RECORDING) { - skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkEndCommandBuffer()"); - } + skipCall |= addCmd(dev_data, pCB, CMD_END, "vkEndCommandBuffer()"); for (auto query : pCB->activeQueries) { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_QUERY, "DS", -- cgit v1.2.3 From 42da1651be40dccc49027381acc809fe48d12240 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Tue, 17 May 2016 14:50:07 -0600 Subject: layers: Update cmds allowed in 2nd CB subpass If subpassContents are of type VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS then CmdNextSubpass and CmdEndRenderPass are accepatable cmds to be added to the secondary cmd buffer. Spec language is from section 7.4 Render Pass Commands: If contents is VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS, the contents are recorded in secondary command buffers that will be called from the primary command buffer, and vkCmdExecuteCommands is the only valid command on the command buffer until vkCmdNextSubpass or vkCmdEndRenderPass. --- layers/core_validation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index ebaa6b0d..f81a0c37 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3563,7 +3563,8 @@ bool validateCmdsInCmdBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *p if (!pCB->activeRenderPass) return false; bool skip_call = false; - if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS && cmd_type != CMD_EXECUTECOMMANDS) { + if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS && + (cmd_type != CMD_EXECUTECOMMANDS && cmd_type != CMD_NEXTSUBPASS && cmd_type != CMD_ENDRENDERPASS)) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_COMMAND_BUFFER, "DS", "Commands cannot be called in a subpass using secondary command buffers."); -- cgit v1.2.3 From 7ec3f530a68ce4ecedac6c17ba015f79b3b4a15e Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Tue, 17 May 2016 08:31:46 -0600 Subject: layers: Refactor DescriptorSet Update code This migrates code for DescriptorSet in_use and flagging bound command buffers as invalid from core_validation.cpp into DescriptorSet class. --- layers/core_validation.cpp | 96 ++++++++++++++++++++++++---------------------- layers/descriptor_sets.cpp | 33 ++++++++++++++-- layers/descriptor_sets.h | 17 +++++--- 3 files changed, 91 insertions(+), 55 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index f81a0c37..98c45c03 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3381,61 +3381,67 @@ static bool validateIdleDescriptorSet(const layer_data *my_data, VkDescriptorSet } static void invalidateBoundCmdBuffers(layer_data *dev_data, const cvdescriptorset::DescriptorSet *pSet) { // Flag any CBs this set is bound to as INVALID - for (auto cb : pSet->GetBoundCmdBuffers()) { - auto cb_node = dev_data->commandBufferMap.find(cb); - if (cb_node != dev_data->commandBufferMap.end()) { - cb_node->second->state = CB_INVALID; - } + for (auto cb_node : pSet->GetBoundCmdBuffers()) { + cb_node->state = CB_INVALID; } } // update DS mappings based on write and copy update arrays static bool dsUpdate(layer_data *my_data, VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pWDS, uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pCDS) { - bool skipCall = false; + bool skip_call = false; // Validate Write updates uint32_t i = 0; for (i = 0; i < descriptorWriteCount; i++) { - VkDescriptorSet ds = pWDS[i].dstSet; - cvdescriptorset::DescriptorSet *pSet = my_data->setMap[ds]; - // Set being updated cannot be in-flight - if ((skipCall = validateIdleDescriptorSet(my_data, ds, "VkUpdateDescriptorSets")) == true) - return skipCall; - // If set is bound to any cmdBuffers, mark them invalid - invalidateBoundCmdBuffers(my_data, pSet); - GENERIC_HEADER *pUpdate = (GENERIC_HEADER *)&pWDS[i]; - // First verify valid update struct - if ((skipCall = validUpdateStruct(my_data, device, pUpdate)) == true) { - break; - } - string error_str; - if (!pSet->WriteUpdate(my_data->report_data, &pWDS[i], &error_str)) { - skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - (uint64_t)(ds), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", - "vkUpdateDescriptorsSets() failed write update for Descriptor Set 0x%" PRIx64 " with error: %s", - reinterpret_cast(ds), error_str.c_str()); + auto dest_set = pWDS[i].dstSet; + auto set_pair = my_data->setMap.find(dest_set); + if (set_pair == my_data->setMap.end()) { + skip_call |= + log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, + reinterpret_cast(dest_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", + "Cannot call vkUpdateDescriptorSets() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", + reinterpret_cast(dest_set)); + } else { + string error_str; + if (!set_pair->second->WriteUpdate(my_data->report_data, &pWDS[i], &error_str)) { + skip_call |= + log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, + reinterpret_cast(dest_set), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", + "vkUpdateDescriptorsSets() failed write update for Descriptor Set 0x%" PRIx64 " with error: %s", + reinterpret_cast(dest_set), error_str.c_str()); + } } } // Now validate copy updates for (i = 0; i < descriptorCopyCount; ++i) { - cvdescriptorset::DescriptorSet *pSrcSet = NULL, *pDstSet = NULL; - // For each copy make sure that update falls within given layout and that types match - pSrcSet = my_data->setMap[pCDS[i].srcSet]; - pDstSet = my_data->setMap[pCDS[i].dstSet]; - // Set being updated cannot be in-flight - if ((skipCall = validateIdleDescriptorSet(my_data, pDstSet->GetSet(), "VkUpdateDescriptorSets")) == true) - return skipCall; - invalidateBoundCmdBuffers(my_data, pDstSet); - std::string error_str; - if (!pDstSet->CopyUpdate(my_data->report_data, &pCDS[i], pSrcSet, &error_str)) { - skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - reinterpret_cast(pCDS[i].dstSet), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", - "vkUpdateDescriptorsSets() failed copy update from Descriptor Set 0x%" PRIx64 - " to Descriptor Set 0x%" PRIx64 " with error: %s", - reinterpret_cast(pCDS[i].srcSet), - reinterpret_cast(pCDS[i].dstSet), error_str.c_str()); + auto dst_set = pCDS[i].dstSet; + auto src_set = pCDS[i].srcSet; + auto src_pair = my_data->setMap.find(src_set); + auto dst_pair = my_data->setMap.find(dst_set); + if (src_pair == my_data->setMap.end()) { + skip_call |= log_msg( + my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, + reinterpret_cast(src_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", + "Cannot call vkUpdateDescriptorSets() to copy from descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", + reinterpret_cast(src_set)); + } else if (dst_pair == my_data->setMap.end()) { + skip_call |= log_msg( + my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, + reinterpret_cast(dst_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", + "Cannot call vkUpdateDescriptorSets() to copy to descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", + reinterpret_cast(dst_set)); + } else { + std::string error_str; + if (!dst_pair->second->CopyUpdate(my_data->report_data, &pCDS[i], src_pair->second, &error_str)) { + skip_call |= + log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, + reinterpret_cast(dst_set), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", + "vkUpdateDescriptorsSets() failed copy update from Descriptor Set 0x%" PRIx64 + " to Descriptor Set 0x%" PRIx64 " with error: %s", + reinterpret_cast(src_set), reinterpret_cast(dst_set), error_str.c_str()); + } } } - return skipCall; + return skip_call; } // Verify that given pool has descriptors that are being requested for allocation. @@ -3701,7 +3707,7 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { for (auto set : pCB->lastBound[i].uniqueBoundSets) { auto set_node = dev_data->setMap.find(set); if (set_node != dev_data->setMap.end()) { - set_node->second->RemoveBoundCommandBuffer(pCB->commandBuffer); + set_node->second->RemoveBoundCommandBuffer(pCB); } } pCB->lastBound[i].reset(); @@ -5995,8 +6001,8 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo } // Create new DescriptorSet instance and add to the pool's unordered_set of DescriptorSets cvdescriptorset::DescriptorSet *pNewNode = new cvdescriptorset::DescriptorSet( - pDescriptorSets[i], layout_pair->second, &dev_data->bufferMap, &dev_data->memObjMap, &dev_data->bufferViewMap, - &dev_data->samplerMap, &dev_data->imageViewMap, &dev_data->imageMap, + pDescriptorSets[i], layout_pair->second, dev_data->report_data, &dev_data->bufferMap, &dev_data->memObjMap, + &dev_data->bufferViewMap, &dev_data->samplerMap, &dev_data->imageViewMap, &dev_data->imageMap, &dev_data->device_extensions.imageToSwapchainMap, &dev_data->device_extensions.swapchainMap); if (NULL == pNewNode) { if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, @@ -6509,7 +6515,7 @@ CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelin cvdescriptorset::DescriptorSet *pSet = getSetNode(dev_data, pDescriptorSets[i]); if (pSet) { pCB->lastBound[pipelineBindPoint].uniqueBoundSets.insert(pDescriptorSets[i]); - pSet->BindCommandBuffer(commandBuffer); + pSet->BindCommandBuffer(pCB); pCB->lastBound[pipelineBindPoint].pipelineLayout = layout; pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i + firstSet] = pDescriptorSets[i]; skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 89c44c68..437dcdc3 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -260,6 +260,7 @@ bool cvdescriptorset::DescriptorSetLayout::VerifyUpdateConsistency(uint32_t curr } cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout, + const debug_report_data *debug_report_data, const std::unordered_map *buffer_map, const std::unordered_map *memory_map, const std::unordered_map *buffer_view_map, @@ -268,9 +269,9 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D const std::unordered_map *image_map, const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map) - : some_update_(false), set_(set), p_layout_(layout), buffer_map_(buffer_map), memory_map_(memory_map), - buffer_view_map_(buffer_view_map), sampler_map_(sampler_map), image_view_map_(image_view_map), image_map_(image_map), - image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { + : some_update_(false), set_(set), p_layout_(layout), report_data_(debug_report_data), buffer_map_(buffer_map), + memory_map_(memory_map), buffer_view_map_(buffer_view_map), sampler_map_(sampler_map), image_view_map_(image_view_map), + image_map_(image_map), image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { // Foreach binding, create default descriptors of given type for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) { auto type = p_layout_->GetTypeFromIndex(i); @@ -456,6 +457,14 @@ uint32_t cvdescriptorset::DescriptorSet::GetAllStorageUpdates(std::unordered_set bool cvdescriptorset::DescriptorSet::WriteUpdate(debug_report_data *report_data, const VkWriteDescriptorSet *update, std::string *error_msg) { auto num_updates = 0; + // Verify idle ds + if (in_use.load()) { + std::stringstream error_str; + error_str << "Cannot call vkUpdateDescriptorSets() to perform write update on descriptor set " << set_ + << " that is in use by a command buffer."; + *error_msg = error_str.str(); + return false; + } // Verify dst binding exists if (!p_layout_->HasBinding(update->dstBinding)) { std::stringstream error_str; @@ -505,12 +514,24 @@ bool cvdescriptorset::DescriptorSet::WriteUpdate(debug_report_data *report_data, if (num_updates != 0) { some_update_ = true; } + // Invalidate any bound command buffers + for (auto cb_node : bound_cmd_buffers_) { + cb_node->state = CB_INVALID; + } return true; } // Copy update bool cvdescriptorset::DescriptorSet::CopyUpdate(debug_report_data *report_data, const VkCopyDescriptorSet *update, const DescriptorSet *src_set, std::string *error) { auto num_updates = 0; + // Verify idle ds + if (in_use.load()) { + std::stringstream error_str; + error_str << "Cannot call vkUpdateDescriptorSets() to perform copy update on descriptor set " << set_ + << " that is in use by a command buffer."; + *error = error_str.str(); + return false; + } if (!p_layout_->HasBinding(update->dstBinding)) { std::stringstream error_str; error_str << "DescriptorSet " << set_ << " does not have copy update dest binding of " << update->dstBinding << "."; @@ -574,6 +595,10 @@ bool cvdescriptorset::DescriptorSet::CopyUpdate(debug_report_data *report_data, if (num_updates != 0) { some_update_ = true; } + // Invalidate any bound command buffers + for (auto cb_node : bound_cmd_buffers_) { + cb_node->state = CB_INVALID; + } return true; } cvdescriptorset::SamplerDescriptor::SamplerDescriptor( @@ -974,4 +999,4 @@ bool cvdescriptorset::TexelDescriptor::CopyUpdate(const Descriptor *src, std::st updated = true; buffer_view_ = buffer_view; return true; -} \ No newline at end of file +} diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 92fda958..5b358d63 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -259,6 +259,9 @@ class BufferDescriptor : public Descriptor { VkDeviceSize range_; const std::unordered_map *buffer_map_; }; +// Helper function for Updating descriptor sets since it crosses multiple sets +void UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites, + uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies); /* * DescriptorSet class * @@ -279,8 +282,9 @@ class BufferDescriptor : public Descriptor { */ class DescriptorSet : public BASE_NODE { public: - DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const std::unordered_map *, - const std::unordered_map *, + using BASE_NODE::in_use; + DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const debug_report_data *, + const std::unordered_map *, const std::unordered_map *, const std::unordered_map *, const std::unordered_map> *, const std::unordered_map *, const std::unordered_map *, @@ -327,11 +331,11 @@ class DescriptorSet : public BASE_NODE { const DescriptorSetLayout *GetLayout() const { return p_layout_; }; VkDescriptorSet GetSet() const { return set_; }; // Return unordered_set of all command buffers that this set is bound to - std::unordered_set GetBoundCmdBuffers() const { return bound_cmd_buffers_; } + std::unordered_set GetBoundCmdBuffers() const { return bound_cmd_buffers_; } // Bind given cmd_buffer to this descriptor set - void BindCommandBuffer(const VkCommandBuffer cmd_buffer) { bound_cmd_buffers_.insert(cmd_buffer); } + void BindCommandBuffer(GLOBAL_CB_NODE *cb_node) { bound_cmd_buffers_.insert(cb_node); } // If given cmd_buffer is in the bound_cmd_buffers_ set, remove it - void RemoveBoundCommandBuffer(const VkCommandBuffer cmd_buffer) { bound_cmd_buffers_.erase(cmd_buffer); } + void RemoveBoundCommandBuffer(GLOBAL_CB_NODE *cb_node) { bound_cmd_buffers_.erase(cb_node); } VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t index) const { return p_layout_->GetImmutableSamplerPtrFromBinding(index); }; @@ -351,8 +355,9 @@ class DescriptorSet : public BASE_NODE { VkDescriptorSet set_; uint32_t descriptor_count_; // Count of all descriptors in this set const DescriptorSetLayout *p_layout_; - std::unordered_set bound_cmd_buffers_; + std::unordered_set bound_cmd_buffers_; std::vector> descriptors_; + const debug_report_data *report_data_; // Ptrs to object containers to verify bound data const std::unordered_map *buffer_map_; const std::unordered_map *memory_map_; -- cgit v1.2.3 From d21e9eb3754861ae1fed39fe8a6d825e11e30b47 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Tue, 17 May 2016 10:41:55 -0600 Subject: layers: Reduce DescriptorSet map look-ups Migrate some data structures to refer to DescriptorSet class instead of raw VkDescriptorSet. This saves map look-ups. --- layers/core_validation.cpp | 64 ++++++++++++++++++++++-------------------- layers/core_validation_types.h | 59 +++++++++++++++++++------------------- 2 files changed, 63 insertions(+), 60 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 98c45c03..780d27de 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -70,6 +70,17 @@ using namespace std; +// TODO : CB really needs it's own class and files so this is just temp code until that happens +GLOBAL_CB_NODE::~GLOBAL_CB_NODE() { + for (uint32_t i=0; iRemoveBoundCommandBuffer(this); + } + lastBound[i].reset(); + } +} + namespace core_validation { using std::unordered_map; @@ -2612,14 +2623,11 @@ static bool validate_and_update_drawtime_descriptor_state( // When validate_and_update_draw_state() handles compute shaders so that active_slots is correct for compute pipelines, this // function can be killed and validate_and_update_draw_state() used instead static void update_shader_storage_images_and_buffers(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { - cvdescriptorset::DescriptorSet *pSet = nullptr; // For the bound descriptor sets, pull off any storage images and buffers // This may be more than are actually updated depending on which are active, but for now this is a stop-gap for compute // pipelines for (auto set : pCB->lastBound[VK_PIPELINE_BIND_POINT_COMPUTE].uniqueBoundSets) { - // Get the set node - pSet = getSetNode(dev_data, set); - pSet->GetAllStorageUpdates(&pCB->updateBuffers, &pCB->updateImages); + set->GetAllStorageUpdates(&pCB->updateBuffers, &pCB->updateImages); } } @@ -2749,10 +2757,10 @@ static bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE * DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS", "VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.", (uint64_t)pPipe->pipeline, setIndex); - } else if (!verify_set_layout_compatibility(my_data, my_data->setMap[state.boundDescriptorSets[setIndex]], + } else if (!verify_set_layout_compatibility(my_data, state.boundDescriptorSets[setIndex], pPipe->graphicsPipelineCI.layout, setIndex, errorString)) { // Set is bound but not compatible w/ overlapping pipelineLayout from PSO - VkDescriptorSet setHandle = my_data->setMap[state.boundDescriptorSets[setIndex]]->GetSet(); + VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet(); result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)setHandle, __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS", @@ -2761,7 +2769,7 @@ static bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE * (uint64_t)setHandle, setIndex, (uint64_t)pPipe->graphicsPipelineCI.layout, errorString.c_str()); } else { // Valid set is bound and layout compatible, validate that it's updated // Pull the set node - cvdescriptorset::DescriptorSet *pSet = my_data->setMap[state.boundDescriptorSets[setIndex]]; + cvdescriptorset::DescriptorSet *pSet = state.boundDescriptorSets[setIndex]; // Save vector of all active sets to verify dynamicOffsets below activeSetBindingsPairs.push_back(std::make_tuple(pSet, setBindingPair.second, &state.dynamicOffsets[setIndex])); @@ -3379,10 +3387,13 @@ static bool validateIdleDescriptorSet(const layer_data *my_data, VkDescriptorSet } return skip_call; } -static void invalidateBoundCmdBuffers(layer_data *dev_data, const cvdescriptorset::DescriptorSet *pSet) { - // Flag any CBs this set is bound to as INVALID +static void invalidateBoundCmdBuffers(layer_data *dev_data, cvdescriptorset::DescriptorSet *pSet) { + // Flag any CBs this set is bound to as INVALID and remove set binding for (auto cb_node : pSet->GetBoundCmdBuffers()) { cb_node->state = CB_INVALID; + for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { + cb_node->lastBound[i].uniqueBoundSets.erase(pSet); + } } } // update DS mappings based on write and copy update arrays @@ -3546,7 +3557,6 @@ static GLOBAL_CB_NODE *getCBNode(layer_data const *my_data, const VkCommandBuffe } return it->second; } - // Free all CB Nodes // NOTE : Calls to this function should be wrapped in mutex static void deleteCommandBuffers(layer_data *my_data) { @@ -3705,10 +3715,7 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { // Before clearing lastBoundState, remove any CB bindings from all uniqueBoundSets for (auto set : pCB->lastBound[i].uniqueBoundSets) { - auto set_node = dev_data->setMap.find(set); - if (set_node != dev_data->setMap.end()) { - set_node->second->RemoveBoundCommandBuffer(pCB); - } + set->RemoveBoundCommandBuffer(pCB); } pCB->lastBound[i].reset(); } @@ -4146,14 +4153,13 @@ static bool validateAndIncrementResources(layer_data *my_data, GLOBAL_CB_NODE *p } for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { for (auto set : pCB->lastBound[i].uniqueBoundSets) { - auto setNode = my_data->setMap.find(set); - if (setNode == my_data->setMap.end()) { + if (!my_data->setMap.count(set->GetSet())) { skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)(set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS", "Cannot submit cmd buffer using deleted descriptor set 0x%" PRIx64 ".", (uint64_t)(set)); } else { - setNode->second->in_use.fetch_add(1); + set->in_use.fetch_add(1); } } } @@ -4224,10 +4230,7 @@ static void decrementResources(layer_data *my_data, VkCommandBuffer cmdBuffer) { } for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { for (auto set : pCB->lastBound[i].uniqueBoundSets) { - auto setNode = my_data->setMap.find(set); - if (setNode != my_data->setMap.end()) { - setNode->second->in_use.fetch_sub(1); - } + set->in_use.fetch_sub(1); } } for (auto semaphore : pCB->semaphores) { @@ -6510,14 +6513,14 @@ CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelin pCB->lastBound[pipelineBindPoint].boundDescriptorSets.resize(lastSetIndex + 1); pCB->lastBound[pipelineBindPoint].dynamicOffsets.resize(lastSetIndex + 1); } - VkDescriptorSet oldFinalBoundSet = pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex]; + auto oldFinalBoundSet = pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex]; for (uint32_t i = 0; i < setCount; i++) { cvdescriptorset::DescriptorSet *pSet = getSetNode(dev_data, pDescriptorSets[i]); if (pSet) { - pCB->lastBound[pipelineBindPoint].uniqueBoundSets.insert(pDescriptorSets[i]); + pCB->lastBound[pipelineBindPoint].uniqueBoundSets.insert(pSet); pSet->BindCommandBuffer(pCB); pCB->lastBound[pipelineBindPoint].pipelineLayout = layout; - pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i + firstSet] = pDescriptorSets[i]; + pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i + firstSet] = pSet; skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS", "DS 0x%" PRIxLEAST64 " bound on pipeline %s", @@ -6610,9 +6613,8 @@ CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelin if (firstSet > 0) { // Check set #s below the first bound set for (uint32_t i = 0; i < firstSet; ++i) { if (pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i] && - !verify_set_layout_compatibility( - dev_data, dev_data->setMap[pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i]], layout, i, - errorString)) { + !verify_set_layout_compatibility(dev_data, pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i], + layout, i, errorString)) { skipCall |= log_msg( dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, @@ -6627,16 +6629,16 @@ CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelin // Check if newly last bound set invalidates any remaining bound sets if ((pCB->lastBound[pipelineBindPoint].boundDescriptorSets.size() - 1) > (lastSetIndex)) { if (oldFinalBoundSet && - !verify_set_layout_compatibility(dev_data, dev_data->setMap[oldFinalBoundSet], layout, lastSetIndex, - errorString)) { + !verify_set_layout_compatibility(dev_data, oldFinalBoundSet, layout, lastSetIndex, errorString)) { + auto old_set = oldFinalBoundSet->GetSet(); skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)oldFinalBoundSet, __LINE__, + VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast(old_set), __LINE__, DRAWSTATE_NONE, "DS", "DescriptorSetDS 0x%" PRIxLEAST64 " previously bound as set #%u is incompatible with set 0x%" PRIxLEAST64 " newly bound as set #%u so set #%u and any subsequent sets were " "disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")", - (uint64_t)oldFinalBoundSet, lastSetIndex, + reinterpret_cast(old_set), lastSetIndex, (uint64_t)pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex], lastSetIndex, lastSetIndex + 1, (uint64_t)layout); pCB->lastBound[pipelineBindPoint].boundDescriptorSets.resize(lastSetIndex + 1); diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index ff3a781c..6269f146 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -52,6 +52,11 @@ #include #include +// Fwd declarations +namespace cvdescriptorset { +class DescriptorSet; +}; + class BASE_NODE { public: std::atomic_int in_use; @@ -302,27 +307,6 @@ typedef enum _CBStatusFlagBits { // clang-format on } CBStatusFlagBits; -// Track last states that are bound per pipeline bind point (Gfx & Compute) -struct LAST_BOUND_STATE { - VkPipeline pipeline; - VkPipelineLayout pipelineLayout; - // Track each set that has been bound - // TODO : can unique be global per CB? (do we care about Gfx vs. Compute?) - std::unordered_set uniqueBoundSets; - // Ordered bound set tracking where index is set# that given set is bound to - std::vector boundDescriptorSets; - // one dynamic offset per dynamic descriptor bound to this CB - std::vector> dynamicOffsets; - - void reset() { - pipeline = VK_NULL_HANDLE; - pipelineLayout = VK_NULL_HANDLE; - uniqueBoundSets.clear(); - boundDescriptorSets.clear(); - dynamicOffsets.clear(); - } -}; - struct QueryObject { VkQueryPool pool; uint32_t index; @@ -369,7 +353,27 @@ template <> struct hash { } }; } -// Cmd Buffer Wrapper Struct +// Track last states that are bound per pipeline bind point (Gfx & Compute) +struct LAST_BOUND_STATE { + VkPipeline pipeline; + VkPipelineLayout pipelineLayout; + // Track each set that has been bound + // TODO : can unique be global per CB? (do we care about Gfx vs. Compute?) + std::unordered_set uniqueBoundSets; + // Ordered bound set tracking where index is set# that given set is bound to + std::vector boundDescriptorSets; + // one dynamic offset per dynamic descriptor bound to this CB + std::vector> dynamicOffsets; + + void reset() { + pipeline = VK_NULL_HANDLE; + pipelineLayout = VK_NULL_HANDLE; + uniqueBoundSets.clear(); + boundDescriptorSets.clear(); + dynamicOffsets.clear(); + } +}; +// Cmd Buffer Wrapper Struct - TODO : This desperately needs its own class struct GLOBAL_CB_NODE : public BASE_NODE { VkCommandBuffer commandBuffer; VkCommandBufferAllocateInfo createInfo; @@ -386,11 +390,6 @@ struct GLOBAL_CB_NODE : public BASE_NODE { // Currently storing "lastBound" objects on per-CB basis // long-term may want to create caches of "lastBound" states and could have // each individual CMD_NODE referencing its own "lastBound" state - // VkPipeline lastBoundPipeline; - // VkPipelineLayout lastBoundPipelineLayout; - // // Capture unique std::set of descriptorSets that are bound to this CB. - // std::set uniqueBoundSets; - // vector boundDescriptorSets; // Index is set# that given set is bound to // Store last bound state for Gfx & Compute pipeline bind points LAST_BOUND_STATE lastBound[VK_PIPELINE_BIND_POINT_RANGE_SIZE]; @@ -409,8 +408,8 @@ struct GLOBAL_CB_NODE : public BASE_NODE { // TODO : These data structures relate to tracking resources that invalidate // a cmd buffer that references them. Need to unify how we handle these // cases so we don't have different tracking data for each type. - std::unordered_set destroyedSets; - std::unordered_set updatedSets; + std::unordered_set destroyedSets; + std::unordered_set updatedSets; std::unordered_set destroyedFramebuffers; std::vector waitedEvents; std::vector semaphores; @@ -435,6 +434,8 @@ struct GLOBAL_CB_NODE : public BASE_NODE { std::vector> validate_functions; std::unordered_set memObjs; std::vector> eventUpdates; + + ~GLOBAL_CB_NODE(); }; #endif // CORE_VALIDATION_TYPES_H_ \ No newline at end of file -- cgit v1.2.3 From 8bfe8f2c5538e99939a8c5bccf7c1c59d69635ad Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Tue, 17 May 2016 14:23:46 -0600 Subject: layers: Improve DescriptorSet cleanup Create private helper function InvalidateBoundCmdBuffers() within the DescriptorSet class to unify invalidate cases due to set being updated or freed. Add a destructor for DescriptorSet to make sure that no bound cmd buffers hang on to deleted set references. --- layers/core_validation.cpp | 10 ---------- layers/descriptor_sets.cpp | 25 +++++++++++++++++-------- layers/descriptor_sets.h | 4 +++- 3 files changed, 20 insertions(+), 19 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 780d27de..3e5360ba 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3387,15 +3387,6 @@ static bool validateIdleDescriptorSet(const layer_data *my_data, VkDescriptorSet } return skip_call; } -static void invalidateBoundCmdBuffers(layer_data *dev_data, cvdescriptorset::DescriptorSet *pSet) { - // Flag any CBs this set is bound to as INVALID and remove set binding - for (auto cb_node : pSet->GetBoundCmdBuffers()) { - cb_node->state = CB_INVALID; - for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) { - cb_node->lastBound[i].uniqueBoundSets.erase(pSet); - } - } -} // update DS mappings based on write and copy update arrays static bool dsUpdate(layer_data *my_data, VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pWDS, uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pCDS) { @@ -3505,7 +3496,6 @@ static bool validate_descriptor_availability_in_pool(layer_data *dev_data, DESCR // Free the descriptor set, remove it from setMap and invalidate any cmd buffers that it was bound to static void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) { - invalidateBoundCmdBuffers(dev_data, descriptor_set); dev_data->setMap.erase(descriptor_set->GetSet()); delete descriptor_set; } diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 437dcdc3..1d9eed64 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -324,6 +324,15 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D } } } +cvdescriptorset::DescriptorSet::~DescriptorSet() { + InvalidateBoundCmdBuffers(); + // Remove link to any cmd buffers + for (auto cb : bound_cmd_buffers_) { + for (uint32_t i=0; ilastBound[i].uniqueBoundSets.erase(this); + } + } +} // Is this sets underlying layout compatible with passed in layout according to "Pipeline Layout Compatibility" in spec? bool cvdescriptorset::DescriptorSet::IsCompatible(const DescriptorSetLayout *layout, std::string *error) const { return layout->IsCompatible(p_layout_, error); @@ -452,6 +461,12 @@ uint32_t cvdescriptorset::DescriptorSet::GetAllStorageUpdates(std::unordered_set p_layout_->FillBindingSet(&binding_set); return GetStorageUpdates(binding_set, buffer_set, image_set); } +// Set is being deleted or updates so invalidate all bound cmd buffers +void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers() { + for (auto cb_node : bound_cmd_buffers_) { + cb_node->state = CB_INVALID; + } +} // Perform write update in given update struct // If an error occurs, return false and fill in details in error_msg string bool cvdescriptorset::DescriptorSet::WriteUpdate(debug_report_data *report_data, const VkWriteDescriptorSet *update, @@ -514,10 +529,7 @@ bool cvdescriptorset::DescriptorSet::WriteUpdate(debug_report_data *report_data, if (num_updates != 0) { some_update_ = true; } - // Invalidate any bound command buffers - for (auto cb_node : bound_cmd_buffers_) { - cb_node->state = CB_INVALID; - } + InvalidateBoundCmdBuffers(); return true; } // Copy update @@ -595,10 +607,7 @@ bool cvdescriptorset::DescriptorSet::CopyUpdate(debug_report_data *report_data, if (num_updates != 0) { some_update_ = true; } - // Invalidate any bound command buffers - for (auto cb_node : bound_cmd_buffers_) { - cb_node->state = CB_INVALID; - } + InvalidateBoundCmdBuffers(); return true; } cvdescriptorset::SamplerDescriptor::SamplerDescriptor( diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 5b358d63..5abe45fc 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -290,7 +290,7 @@ class DescriptorSet : public BASE_NODE { const std::unordered_map *, const std::unordered_map *, const std::unordered_map *, const std::unordered_map *); - ~DescriptorSet(){}; + ~DescriptorSet(); // A number of common Get* functions that return data based on layout from which this set was created uint32_t GetTotalDescriptorCount() const { return p_layout_ ? p_layout_->GetTotalDescriptorCount() : 0; }; uint32_t GetDynamicDescriptorCount() const { return p_layout_ ? p_layout_->GetDynamicDescriptorCount() : 0; }; @@ -351,6 +351,8 @@ class DescriptorSet : public BASE_NODE { private: bool ValidateUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) const; + // Private helper to set all bound cmd buffers to INVALID state + void InvalidateBoundCmdBuffers(); bool some_update_; // has any part of the set ever been updated? VkDescriptorSet set_; uint32_t descriptor_count_; // Count of all descriptors in this set -- cgit v1.2.3 From d72b9acd6d857ee6e3e46f92f5f48c24b278923a Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 19 May 2016 06:58:13 -0600 Subject: layers: Remove lastBound state reset in destructor No need to reset this state right before GLOBAL_CB_NODE is destroyed. --- layers/core_validation.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 3e5360ba..934a2288 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -77,7 +77,6 @@ GLOBAL_CB_NODE::~GLOBAL_CB_NODE() { for (auto set : lastBound[i].uniqueBoundSets) { set->RemoveBoundCommandBuffer(this); } - lastBound[i].reset(); } } -- cgit v1.2.3 From 818c4b85891f8bded09b4d1178e508d39cb89bac Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 17 May 2016 11:02:24 +1200 Subject: layers: Unify cb lookup in CmdBeginRenderPass We already have a GLOBAL_CB_NODE ptr here, and we know it's not null. Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 934a2288..0715fda1 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -8857,40 +8857,31 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p if (pass_data != dev_data->renderPassMap.end()) { RENDER_PASS_NODE* pRPNode = pass_data->second; pCB->activeFramebuffer = pRenderPassBegin->framebuffer; - auto cb_data = dev_data->commandBufferMap.find(commandBuffer); for (size_t i = 0; i < pRPNode->attachments.size(); ++i) { MT_FB_ATTACHMENT_INFO &fb_info = dev_data->frameBufferMap[pRenderPassBegin->framebuffer].attachments[i]; if (pRPNode->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { - if (cb_data != dev_data->commandBufferMap.end()) { - std::function function = [=]() { - set_memory_valid(dev_data, fb_info.mem, true, fb_info.image); - return false; - }; - cb_data->second->validate_functions.push_back(function); - } + std::function function = [=]() { + set_memory_valid(dev_data, fb_info.mem, true, fb_info.image); + return false; + }; + pCB->validate_functions.push_back(function); } else if (pRPNode->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_DONT_CARE) { - if (cb_data != dev_data->commandBufferMap.end()) { - std::function function = [=]() { - set_memory_valid(dev_data, fb_info.mem, false, fb_info.image); - return false; - }; - cb_data->second->validate_functions.push_back(function); - } + std::function function = [=]() { + set_memory_valid(dev_data, fb_info.mem, false, fb_info.image); + return false; + }; + pCB->validate_functions.push_back(function); } else if (pRPNode->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_LOAD) { - if (cb_data != dev_data->commandBufferMap.end()) { - std::function function = [=]() { - return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image); - }; - cb_data->second->validate_functions.push_back(function); - } + std::function function = [=]() { + return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image); + }; + pCB->validate_functions.push_back(function); } if (pRPNode->attachment_first_read[pRPNode->attachments[i].attachment]) { - if (cb_data != dev_data->commandBufferMap.end()) { - std::function function = [=]() { - return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image); - }; - cb_data->second->validate_functions.push_back(function); - } + std::function function = [=]() { + return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image); + }; + pCB->validate_functions.push_back(function); } } } -- cgit v1.2.3 From ae80a25e48e78ef39e439c9399fed27614d6bba4 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 17 May 2016 11:36:23 +1200 Subject: layers: Add getRenderPass helper Various similar functions exist, but this one was missing. Returns the RENDER_PASS_NODE ptr if it exists, or nullptr otherwise. Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 161 +++++++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 80 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 0715fda1..6a4e3576 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -1965,7 +1965,7 @@ static bool validate_status(layer_data *my_data, GLOBAL_CB_NODE *pNode, CBStatus } // Retrieve pipeline node ptr for given pipeline object -static PIPELINE_NODE *getPipeline(layer_data const *my_data, const VkPipeline pipeline) { +static PIPELINE_NODE *getPipeline(layer_data const *my_data, VkPipeline pipeline) { auto it = my_data->pipelineMap.find(pipeline); if (it == my_data->pipelineMap.end()) { return nullptr; @@ -1973,6 +1973,14 @@ static PIPELINE_NODE *getPipeline(layer_data const *my_data, const VkPipeline pi return it->second; } +static RENDER_PASS_NODE *getRenderPass(layer_data const *my_data, VkRenderPass renderpass) { + auto it = my_data->renderPassMap.find(renderpass); + if (it == my_data->renderPassMap.end()) { + return nullptr; + } + return it->second; +} + // Return true if for a given PSO, the given state enum is dynamic, else return false static bool isDynamic(const PIPELINE_NODE *pPipeline, const VkDynamicState state) { if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) { @@ -2057,12 +2065,17 @@ static bool attachment_references_compatible(const uint32_t index, const VkAttac // For give primary and secondary RenderPass objects, verify that they're compatible static bool verify_renderpass_compatibility(layer_data *my_data, const VkRenderPass primaryRP, const VkRenderPass secondaryRP, string &errorMsg) { - if (my_data->renderPassMap.find(primaryRP) == my_data->renderPassMap.end()) { + auto primary_render_pass = getRenderPass(my_data, primaryRP); + auto secondary_render_pass = getRenderPass(my_data, secondaryRP); + + if (!primary_render_pass) { stringstream errorStr; errorStr << "invalid VkRenderPass (" << primaryRP << ")"; errorMsg = errorStr.str(); return false; - } else if (my_data->renderPassMap.find(secondaryRP) == my_data->renderPassMap.end()) { + } + + if (!secondary_render_pass) { stringstream errorStr; errorStr << "invalid VkRenderPass (" << secondaryRP << ")"; errorMsg = errorStr.str(); @@ -2072,8 +2085,8 @@ static bool verify_renderpass_compatibility(layer_data *my_data, const VkRenderP if (primaryRP == secondaryRP) { return true; } - const VkRenderPassCreateInfo *primaryRPCI = my_data->renderPassMap[primaryRP]->pCreateInfo; - const VkRenderPassCreateInfo *secondaryRPCI = my_data->renderPassMap[secondaryRP]->pCreateInfo; + const VkRenderPassCreateInfo *primaryRPCI = primary_render_pass->pCreateInfo; + const VkRenderPassCreateInfo *secondaryRPCI = secondary_render_pass->pCreateInfo; if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) { stringstream errorStr; errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount @@ -2951,13 +2964,13 @@ static bool verifyPipelineCreateState(layer_data *my_data, const VkDevice device // Ensure the subpass index is valid. If not, then validate_and_capture_pipeline_shader_state // produces nonsense errors that confuse users. Other layers should already // emit errors for renderpass being invalid. - auto rp_data = my_data->renderPassMap.find(pPipeline->graphicsPipelineCI.renderPass); - if (rp_data != my_data->renderPassMap.end() && - pPipeline->graphicsPipelineCI.subpass >= rp_data->second->pCreateInfo->subpassCount) { + auto renderPass = getRenderPass(my_data, pPipeline->graphicsPipelineCI.renderPass); + if (renderPass && + pPipeline->graphicsPipelineCI.subpass >= renderPass->pCreateInfo->subpassCount) { skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: Subpass index %u " "is out of range for this renderpass (0..%u)", - pPipeline->graphicsPipelineCI.subpass, rp_data->second->pCreateInfo->subpassCount - 1); + pPipeline->graphicsPipelineCI.subpass, renderPass->pCreateInfo->subpassCount - 1); } if (!validate_and_capture_pipeline_shader_state(my_data->report_data, pPipeline, &my_data->phys_dev_properties.features, @@ -5672,11 +5685,7 @@ CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t for (i = 0; i < count; i++) { pPipeNode[i] = new PIPELINE_NODE; pPipeNode[i]->initGraphicsPipeline(&pCreateInfos[i]); - - auto renderpass_it = dev_data->renderPassMap.find(pCreateInfos[i].renderPass); - if (renderpass_it != dev_data->renderPassMap.end()) { - pPipeNode[i]->renderPass = renderpass_it->second; - } + pPipeNode[i]->renderPass = getRenderPass(dev_data, pCreateInfos[i].renderPass); auto pipeline_layout_it = dev_data->pipelineLayoutMap.find(pCreateInfos[i].layout); if (pipeline_layout_it != dev_data->pipelineLayoutMap.end()) { @@ -6178,15 +6187,15 @@ BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo } } if (pInfo && pInfo->renderPass != VK_NULL_HANDLE) { - auto rp_data = dev_data->renderPassMap.find(pInfo->renderPass); - if (rp_data != dev_data->renderPassMap.end() && rp_data->second && rp_data->second->pCreateInfo) { - if (pInfo->subpass >= rp_data->second->pCreateInfo->subpassCount) { + auto renderPass = getRenderPass(dev_data, pInfo->renderPass); + if (renderPass) { + if (pInfo->subpass >= renderPass->pCreateInfo->subpassCount) { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__, DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS", "vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must has a subpass index (%d) " "that is less than the number of subpasses (%d).", - (void *)commandBuffer, pInfo->subpass, rp_data->second->pCreateInfo->subpassCount); + (void *)commandBuffer, pInfo->subpass, renderPass->pCreateInfo->subpassCount); } } } @@ -6220,8 +6229,7 @@ BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo // If we are a secondary command-buffer and inheriting. Update the items we should inherit. if ((pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) && (pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) { - auto inherited_render_pass_it = dev_data->renderPassMap.find(pCB->beginInfo.pInheritanceInfo->renderPass); - pCB->activeRenderPass = inherited_render_pass_it != dev_data->renderPassMap.end() ? inherited_render_pass_it->second : nullptr; + pCB->activeRenderPass = getRenderPass(dev_data, pCB->beginInfo.pInheritanceInfo->renderPass); pCB->activeSubpass = pCB->beginInfo.pInheritanceInfo->subpass; pCB->framebuffers.insert(pCB->beginInfo.pInheritanceInfo->framebuffer); } @@ -8251,10 +8259,11 @@ bool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange } static bool ValidateDependencies(const layer_data *my_data, const VkRenderPassBeginInfo *pRenderPassBegin, - const std::vector &subpass_to_node) { + RENDER_PASS_NODE const * renderPass) { bool skip_call = false; const VkFramebufferCreateInfo *pFramebufferInfo = &my_data->frameBufferMap.at(pRenderPassBegin->framebuffer).createInfo; - const VkRenderPassCreateInfo *pCreateInfo = my_data->renderPassMap.at(pRenderPassBegin->renderPass)->pCreateInfo; + const VkRenderPassCreateInfo *pCreateInfo = renderPass->pCreateInfo; + auto const & subpass_to_node = renderPass->subpassToNode; std::vector> output_attachment_to_subpass(pCreateInfo->attachmentCount); std::vector> input_attachment_to_subpass(pCreateInfo->attachmentCount); std::vector> overlapping_attachments(pCreateInfo->attachmentCount); @@ -8771,17 +8780,16 @@ static void TransitionSubpassLayouts(VkCommandBuffer cmdBuffer, const VkRenderPa const int subpass_index) { layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer); - auto render_pass_data = dev_data->renderPassMap.find(pRenderPassBegin->renderPass); - if (render_pass_data == dev_data->renderPassMap.end()) { + auto renderPass = getRenderPass(dev_data, pRenderPassBegin->renderPass); + if (!renderPass) return; - } - const VkRenderPassCreateInfo *pRenderPassInfo = render_pass_data->second->pCreateInfo; + auto framebuffer_data = dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer); if (framebuffer_data == dev_data->frameBufferMap.end()) { return; } const VkFramebufferCreateInfo framebufferInfo = framebuffer_data->second.createInfo; - const VkSubpassDescription &subpass = pRenderPassInfo->pSubpasses[subpass_index]; + const VkSubpassDescription &subpass = renderPass->pCreateInfo->pSubpasses[subpass_index]; for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { const VkImageView &image_view = framebufferInfo.pAttachments[subpass.pInputAttachments[j].attachment]; SetLayout(dev_data, pCB, image_view, subpass.pInputAttachments[j].layout); @@ -8809,11 +8817,11 @@ static bool validatePrimaryCommandBuffer(const layer_data *my_data, const GLOBAL static void TransitionFinalSubpassLayouts(VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo *pRenderPassBegin) { layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer); - auto render_pass_data = dev_data->renderPassMap.find(pRenderPassBegin->renderPass); - if (render_pass_data == dev_data->renderPassMap.end()) { + auto renderPass = getRenderPass(dev_data, pRenderPassBegin->renderPass); + if (!renderPass) return; - } - const VkRenderPassCreateInfo *pRenderPassInfo = render_pass_data->second->pCreateInfo; + + const VkRenderPassCreateInfo *pRenderPassInfo = renderPass->pCreateInfo; auto framebuffer_data = dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer); if (framebuffer_data == dev_data->frameBufferMap.end()) { return; @@ -8850,53 +8858,46 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); std::unique_lock lock(global_lock); GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); + auto renderPass = pRenderPassBegin ? getRenderPass(dev_data, pRenderPassBegin->renderPass) : nullptr; if (pCB) { - if (pRenderPassBegin && pRenderPassBegin->renderPass) { + if (renderPass) { #if MTMERGE - auto pass_data = dev_data->renderPassMap.find(pRenderPassBegin->renderPass); - if (pass_data != dev_data->renderPassMap.end()) { - RENDER_PASS_NODE* pRPNode = pass_data->second; - pCB->activeFramebuffer = pRenderPassBegin->framebuffer; - for (size_t i = 0; i < pRPNode->attachments.size(); ++i) { - MT_FB_ATTACHMENT_INFO &fb_info = dev_data->frameBufferMap[pRenderPassBegin->framebuffer].attachments[i]; - if (pRPNode->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { - std::function function = [=]() { - set_memory_valid(dev_data, fb_info.mem, true, fb_info.image); - return false; - }; - pCB->validate_functions.push_back(function); - } else if (pRPNode->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_DONT_CARE) { - std::function function = [=]() { - set_memory_valid(dev_data, fb_info.mem, false, fb_info.image); - return false; - }; - pCB->validate_functions.push_back(function); - } else if (pRPNode->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_LOAD) { - std::function function = [=]() { - return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image); - }; - pCB->validate_functions.push_back(function); - } - if (pRPNode->attachment_first_read[pRPNode->attachments[i].attachment]) { - std::function function = [=]() { - return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image); - }; - pCB->validate_functions.push_back(function); - } + pCB->activeFramebuffer = pRenderPassBegin->framebuffer; + for (size_t i = 0; i < renderPass->attachments.size(); ++i) { + MT_FB_ATTACHMENT_INFO &fb_info = dev_data->frameBufferMap[pRenderPassBegin->framebuffer].attachments[i]; + if (renderPass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { + std::function function = [=]() { + set_memory_valid(dev_data, fb_info.mem, true, fb_info.image); + return false; + }; + pCB->validate_functions.push_back(function); + } else if (renderPass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_DONT_CARE) { + std::function function = [=]() { + set_memory_valid(dev_data, fb_info.mem, false, fb_info.image); + return false; + }; + pCB->validate_functions.push_back(function); + } else if (renderPass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_LOAD) { + std::function function = [=]() { + return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image); + }; + pCB->validate_functions.push_back(function); + } + if (renderPass->attachment_first_read[renderPass->attachments[i].attachment]) { + std::function function = [=]() { + return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image); + }; + pCB->validate_functions.push_back(function); } } #endif skipCall |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin); skipCall |= VerifyFramebufferAndRenderPassLayouts(commandBuffer, pRenderPassBegin); skipCall |= insideRenderPass(dev_data, pCB, "vkCmdBeginRenderPass"); - auto render_pass_data = dev_data->renderPassMap.find(pRenderPassBegin->renderPass); - if (render_pass_data != dev_data->renderPassMap.end()) { - skipCall |= ValidateDependencies(dev_data, pRenderPassBegin, render_pass_data->second->subpassToNode); - pCB->activeRenderPass = render_pass_data->second; - } - else { - pCB->activeRenderPass = nullptr; + if (renderPass) { + skipCall |= ValidateDependencies(dev_data, pRenderPassBegin, renderPass); } + pCB->activeRenderPass = renderPass; skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdBeginRenderPass"); skipCall |= addCmd(dev_data, pCB, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()"); // This is a shallow copy as that is all that is needed for now @@ -8908,8 +8909,8 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p dev_data->frameBufferMap[pRenderPassBegin->framebuffer].referencingCmdBuffers.insert(pCB->commandBuffer); } else { skipCall |= - log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, - DRAWSTATE_INVALID_RENDERPASS, "DS", "You cannot use a NULL RenderPass object in vkCmdBeginRenderPass()"); + log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, + DRAWSTATE_INVALID_RENDERPASS, "DS", "You cannot use a NULL RenderPass object in vkCmdBeginRenderPass()"); } } lock.unlock(); @@ -9089,9 +9090,9 @@ static bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffe // Early exit if renderPass objects are identical (and therefore compatible) if (primaryPass == secondaryPass) return skip_call; - auto primary_data = dev_data->renderPassMap.find(primaryPass); - auto secondary_data = dev_data->renderPassMap.find(secondaryPass); - if (primary_data == dev_data->renderPassMap.end() || primary_data->second == nullptr) { + auto primary_render_pass = getRenderPass(dev_data, primaryPass); + auto secondary_render_pass = getRenderPass(dev_data, secondaryPass); + if (!primary_render_pass) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", @@ -9099,7 +9100,7 @@ static bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffe (void *)primaryBuffer, (uint64_t)(primaryPass)); return skip_call; } - if (secondary_data == dev_data->renderPassMap.end() || secondary_data->second == nullptr) { + if (!secondary_render_pass) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", @@ -9107,7 +9108,7 @@ static bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffe (void *)secondaryBuffer, (uint64_t)(secondaryPass)); return skip_call; } - if (primary_data->second->pCreateInfo->subpassCount != secondary_data->second->pCreateInfo->subpassCount) { + if (primary_render_pass->pCreateInfo->subpassCount != secondary_render_pass->pCreateInfo->subpassCount) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p which has a render pass 0x%" PRIx64 @@ -9116,10 +9117,10 @@ static bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffe (void *)secondaryBuffer, (uint64_t)(secondaryPass), (uint64_t)(primaryPass)); return skip_call; } - bool is_multi = primary_data->second->pCreateInfo->subpassCount > 1; - for (uint32_t i = 0; i < primary_data->second->pCreateInfo->subpassCount; ++i) { - skip_call |= - validateSubpassCompatibility(dev_data, primaryBuffer, primary_data->second, secondaryBuffer, secondary_data->second, i, is_multi); + auto subpassCount = primary_render_pass->pCreateInfo->subpassCount; + for (uint32_t i = 0; i < subpassCount; ++i) { + skip_call |= validateSubpassCompatibility(dev_data, primaryBuffer, primary_render_pass, secondaryBuffer, + secondary_render_pass, i, subpassCount > 1); } return skip_call; } -- cgit v1.2.3 From c8dc800e4aaeeb14a65822eb379740835c88daf2 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 17 May 2016 14:59:22 +1200 Subject: layers: Simplify CmdEndRenderPass Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 6a4e3576..782ab3e5 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -8941,38 +8941,34 @@ VKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) { bool skipCall = false; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); std::unique_lock lock(global_lock); - auto cb_data = dev_data->commandBufferMap.find(commandBuffer); - if (cb_data != dev_data->commandBufferMap.end()) { - RENDER_PASS_NODE* pRPNode = cb_data->second->activeRenderPass; + auto pCB = getCBNode(dev_data, commandBuffer); + if (pCB) { + RENDER_PASS_NODE* pRPNode = pCB->activeRenderPass; if (pRPNode) { for (size_t i = 0; i < pRPNode->attachments.size(); ++i) { - MT_FB_ATTACHMENT_INFO &fb_info = dev_data->frameBufferMap[cb_data->second->activeFramebuffer].attachments[i]; + MT_FB_ATTACHMENT_INFO &fb_info = dev_data->frameBufferMap[pCB->activeFramebuffer].attachments[i]; if (pRPNode->attachments[i].store_op == VK_ATTACHMENT_STORE_OP_STORE) { - if (cb_data != dev_data->commandBufferMap.end()) { - std::function function = [=]() { - set_memory_valid(dev_data, fb_info.mem, true, fb_info.image); - return false; - }; - cb_data->second->validate_functions.push_back(function); - } + std::function function = [=]() { + set_memory_valid(dev_data, fb_info.mem, true, fb_info.image); + return false; + }; + pCB->validate_functions.push_back(function); } else if (pRPNode->attachments[i].store_op == VK_ATTACHMENT_STORE_OP_DONT_CARE) { - if (cb_data != dev_data->commandBufferMap.end()) { - std::function function = [=]() { - set_memory_valid(dev_data, fb_info.mem, false, fb_info.image); - return false; - }; - cb_data->second->validate_functions.push_back(function); - } + std::function function = [=]() { + set_memory_valid(dev_data, fb_info.mem, false, fb_info.image); + return false; + }; + pCB->validate_functions.push_back(function); } } } - skipCall |= outsideRenderPass(dev_data, cb_data->second, "vkCmdEndRenderpass"); - skipCall |= validatePrimaryCommandBuffer(dev_data, cb_data->second, "vkCmdEndRenderPass"); - skipCall |= addCmd(dev_data, cb_data->second, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()"); - TransitionFinalSubpassLayouts(commandBuffer, &cb_data->second->activeRenderPassBeginInfo); - cb_data->second->activeRenderPass = nullptr; - cb_data->second->activeSubpass = 0; - cb_data->second->activeFramebuffer = VK_NULL_HANDLE; + skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass"); + skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass"); + skipCall |= addCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()"); + TransitionFinalSubpassLayouts(commandBuffer, &pCB->activeRenderPassBeginInfo); + pCB->activeRenderPass = nullptr; + pCB->activeSubpass = 0; + pCB->activeFramebuffer = VK_NULL_HANDLE; } lock.unlock(); if (!skipCall) -- cgit v1.2.3 From 2d2af8c6299282d561e7e6815de5d36f44388f46 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 17 May 2016 15:27:58 +1200 Subject: layers: Add getFramebuffer() helper Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 782ab3e5..e64578b8 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -1981,6 +1981,14 @@ static RENDER_PASS_NODE *getRenderPass(layer_data const *my_data, VkRenderPass r return it->second; } +static FRAMEBUFFER_NODE *getFramebuffer(layer_data *my_data, VkFramebuffer framebuffer) { + auto it = my_data->frameBufferMap.find(framebuffer); + if (it == my_data->frameBufferMap.end()) { + return nullptr; + } + return &it->second; +} + // Return true if for a given PSO, the given state enum is dynamic, else return false static bool isDynamic(const PIPELINE_NODE *pPipeline, const VkDynamicState state) { if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) { @@ -3756,10 +3764,9 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list for (auto framebuffer : pCB->framebuffers) { - auto fbNode = dev_data->frameBufferMap.find(framebuffer); - if (fbNode != dev_data->frameBufferMap.end()) { - fbNode->second.referencingCmdBuffers.erase(pCB->commandBuffer); - } + auto fbNode = getFramebuffer(dev_data, framebuffer); + if (fbNode) + fbNode->referencingCmdBuffers.erase(pCB->commandBuffer); } pCB->framebuffers.clear(); pCB->activeFramebuffer = VK_NULL_HANDLE; @@ -6154,9 +6161,9 @@ BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo reinterpret_cast(commandBuffer)); } else { string errorString = ""; - auto fbNode = dev_data->frameBufferMap.find(pInfo->framebuffer); - if (fbNode != dev_data->frameBufferMap.end()) { - VkRenderPass fbRP = fbNode->second.createInfo.renderPass; + auto framebuffer = getFramebuffer(dev_data, pInfo->framebuffer); + if (framebuffer) { + VkRenderPass fbRP = framebuffer->createInfo.renderPass; if (!verify_renderpass_compatibility(dev_data, fbRP, pInfo->renderPass, errorString)) { // renderPass that framebuffer was created with must be compatible with local renderPass skipCall |= @@ -6170,7 +6177,7 @@ BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo (uint64_t)(pInfo->framebuffer), (uint64_t)(fbRP), errorString.c_str()); } // Connect this framebuffer to this cmdBuffer - fbNode->second.referencingCmdBuffers.insert(pCB->commandBuffer); + framebuffer->referencingCmdBuffers.insert(pCB->commandBuffer); } } } @@ -8258,10 +8265,10 @@ bool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange isRangeOverlapping(range1.baseArrayLayer, range1.layerCount, range2.baseArrayLayer, range2.layerCount)); } -static bool ValidateDependencies(const layer_data *my_data, const VkRenderPassBeginInfo *pRenderPassBegin, +static bool ValidateDependencies(const layer_data *my_data, FRAMEBUFFER_NODE const * framebuffer, RENDER_PASS_NODE const * renderPass) { bool skip_call = false; - const VkFramebufferCreateInfo *pFramebufferInfo = &my_data->frameBufferMap.at(pRenderPassBegin->framebuffer).createInfo; + const VkFramebufferCreateInfo *pFramebufferInfo = &framebuffer->createInfo; const VkRenderPassCreateInfo *pCreateInfo = renderPass->pCreateInfo; auto const & subpass_to_node = renderPass->subpassToNode; std::vector> output_attachment_to_subpass(pCreateInfo->attachmentCount); @@ -8814,9 +8821,7 @@ static bool validatePrimaryCommandBuffer(const layer_data *my_data, const GLOBAL return skip_call; } -static void TransitionFinalSubpassLayouts(VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo *pRenderPassBegin) { - layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); - GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer); +static void TransitionFinalSubpassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin) { auto renderPass = getRenderPass(dev_data, pRenderPassBegin->renderPass); if (!renderPass) return; @@ -8859,12 +8864,13 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p std::unique_lock lock(global_lock); GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); auto renderPass = pRenderPassBegin ? getRenderPass(dev_data, pRenderPassBegin->renderPass) : nullptr; + auto framebuffer = pRenderPassBegin ? getFramebuffer(dev_data, pRenderPassBegin->framebuffer) : nullptr; if (pCB) { if (renderPass) { #if MTMERGE pCB->activeFramebuffer = pRenderPassBegin->framebuffer; for (size_t i = 0; i < renderPass->attachments.size(); ++i) { - MT_FB_ATTACHMENT_INFO &fb_info = dev_data->frameBufferMap[pRenderPassBegin->framebuffer].attachments[i]; + MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; if (renderPass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { std::function function = [=]() { set_memory_valid(dev_data, fb_info.mem, true, fb_info.image); @@ -8895,7 +8901,7 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p skipCall |= VerifyFramebufferAndRenderPassLayouts(commandBuffer, pRenderPassBegin); skipCall |= insideRenderPass(dev_data, pCB, "vkCmdBeginRenderPass"); if (renderPass) { - skipCall |= ValidateDependencies(dev_data, pRenderPassBegin, renderPass); + skipCall |= ValidateDependencies(dev_data, framebuffer, renderPass); } pCB->activeRenderPass = renderPass; skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdBeginRenderPass"); @@ -8965,7 +8971,7 @@ VKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) { skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass"); skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass"); skipCall |= addCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()"); - TransitionFinalSubpassLayouts(commandBuffer, &pCB->activeRenderPassBeginInfo); + TransitionFinalSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo); pCB->activeRenderPass = nullptr; pCB->activeSubpass = 0; pCB->activeFramebuffer = VK_NULL_HANDLE; -- cgit v1.2.3 From 75a872d3d227876a0b35857043b86017f5b98c4d Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 17 May 2016 15:31:00 +1200 Subject: layers: simplify TransitionSubpassLayouts Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index e64578b8..14a05f18 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -8783,10 +8783,8 @@ static bool VerifyFramebufferAndRenderPassLayouts(VkCommandBuffer cmdBuffer, con return skip_call; } -static void TransitionSubpassLayouts(VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, +static void TransitionSubpassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin, const int subpass_index) { - layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); - GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer); auto renderPass = getRenderPass(dev_data, pRenderPassBegin->renderPass); if (!renderPass) return; @@ -8935,7 +8933,7 @@ VKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpa skipCall |= addCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()"); pCB->activeSubpass++; pCB->activeSubpassContents = contents; - TransitionSubpassLayouts(commandBuffer, &pCB->activeRenderPassBeginInfo, pCB->activeSubpass); + TransitionSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, pCB->activeSubpass); skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass"); } lock.unlock(); -- cgit v1.2.3 From 339cb923b4a23a746d60d73a9624843362c4d0ec Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 17 May 2016 15:45:31 +1200 Subject: use getFramebuffer more Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 14a05f18..739398d1 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -8738,10 +8738,8 @@ static void deleteRenderPasses(layer_data *my_data) { my_data->renderPassMap.clear(); } -static bool VerifyFramebufferAndRenderPassLayouts(VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo *pRenderPassBegin) { +static bool VerifyFramebufferAndRenderPassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin) { bool skip_call = false; - layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); - GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer); const VkRenderPassCreateInfo *pRenderPassInfo = dev_data->renderPassMap[pRenderPassBegin->renderPass]->pCreateInfo; const VkFramebufferCreateInfo framebufferInfo = dev_data->frameBufferMap[pRenderPassBegin->framebuffer].createInfo; if (pRenderPassInfo->attachmentCount != framebufferInfo.attachmentCount) { @@ -8789,11 +8787,11 @@ static void TransitionSubpassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, if (!renderPass) return; - auto framebuffer_data = dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer); - if (framebuffer_data == dev_data->frameBufferMap.end()) { + auto framebuffer = getFramebuffer(dev_data, pRenderPassBegin->framebuffer); + if (!framebuffer) return; - } - const VkFramebufferCreateInfo framebufferInfo = framebuffer_data->second.createInfo; + + const VkFramebufferCreateInfo &framebufferInfo = framebuffer->createInfo; const VkSubpassDescription &subpass = renderPass->pCreateInfo->pSubpasses[subpass_index]; for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { const VkImageView &image_view = framebufferInfo.pAttachments[subpass.pInputAttachments[j].attachment]; @@ -8825,13 +8823,12 @@ static void TransitionFinalSubpassLayouts(layer_data *dev_data, GLOBAL_CB_NODE * return; const VkRenderPassCreateInfo *pRenderPassInfo = renderPass->pCreateInfo; - auto framebuffer_data = dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer); - if (framebuffer_data == dev_data->frameBufferMap.end()) { + auto framebuffer = getFramebuffer(dev_data, pRenderPassBegin->framebuffer); + if (!framebuffer) return; - } - const VkFramebufferCreateInfo framebufferInfo = framebuffer_data->second.createInfo; + for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) { - const VkImageView &image_view = framebufferInfo.pAttachments[i]; + const VkImageView &image_view = framebuffer->createInfo.pAttachments[i]; SetLayout(dev_data, pCB, image_view, pRenderPassInfo->pAttachments[i].finalLayout); } } @@ -8896,7 +8893,7 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p } #endif skipCall |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin); - skipCall |= VerifyFramebufferAndRenderPassLayouts(commandBuffer, pRenderPassBegin); + skipCall |= VerifyFramebufferAndRenderPassLayouts(dev_data, pCB, pRenderPassBegin); skipCall |= insideRenderPass(dev_data, pCB, "vkCmdBeginRenderPass"); if (renderPass) { skipCall |= ValidateDependencies(dev_data, framebuffer, renderPass); @@ -8910,7 +8907,7 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p pCB->activeSubpassContents = contents; pCB->framebuffers.insert(pRenderPassBegin->framebuffer); // Connect this framebuffer to this cmdBuffer - dev_data->frameBufferMap[pRenderPassBegin->framebuffer].referencingCmdBuffers.insert(pCB->commandBuffer); + framebuffer->referencingCmdBuffers.insert(pCB->commandBuffer); } else { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, @@ -8948,9 +8945,10 @@ VKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) { auto pCB = getCBNode(dev_data, commandBuffer); if (pCB) { RENDER_PASS_NODE* pRPNode = pCB->activeRenderPass; + auto framebuffer = getFramebuffer(dev_data, pCB->activeFramebuffer); if (pRPNode) { for (size_t i = 0; i < pRPNode->attachments.size(); ++i) { - MT_FB_ATTACHMENT_INFO &fb_info = dev_data->frameBufferMap[pCB->activeFramebuffer].attachments[i]; + MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; if (pRPNode->attachments[i].store_op == VK_ATTACHMENT_STORE_OP_STORE) { std::function function = [=]() { set_memory_valid(dev_data, fb_info.mem, true, fb_info.image); @@ -9141,8 +9139,8 @@ static bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuf " that is not compatible with the current framebuffer 0x%" PRIx64 ".", (void *)secondaryBuffer, (uint64_t)(secondary_fb), (uint64_t)(primary_fb)); } - auto fb_data = dev_data->frameBufferMap.find(secondary_fb); - if (fb_data == dev_data->frameBufferMap.end()) { + auto fb = getFramebuffer(dev_data, secondary_fb); + if (!fb) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p " @@ -9150,7 +9148,7 @@ static bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuf (void *)secondaryBuffer, (uint64_t)(secondary_fb)); return skip_call; } - skip_call |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb_data->second.createInfo.renderPass, + skip_call |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb->createInfo.renderPass, secondaryBuffer, pSubCB->beginInfo.pInheritanceInfo->renderPass); } return skip_call; -- cgit v1.2.3 From d2769d64be84e67a93a0df1503b4ea44c3d56f6b Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 17 May 2016 17:42:27 +1200 Subject: layers: More slight tidying Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 739398d1..4e584493 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -4104,10 +4104,8 @@ static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT // This validates that the initial layout specified in the command buffer for // the IMAGE is the same // as the global IMAGE layout -static bool ValidateCmdBufImageLayouts(VkCommandBuffer cmdBuffer) { +static bool ValidateCmdBufImageLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { bool skip_call = false; - layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map); - GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer); for (auto cb_image_data : pCB->imageLayoutMap) { VkImageLayout imageLayout; if (!FindLayout(dev_data, cb_image_data.first, imageLayout)) { @@ -4122,7 +4120,7 @@ static bool ValidateCmdBufImageLayouts(VkCommandBuffer cmdBuffer) { if (cb_image_data.first.hasSubresource) { skip_call |= log_msg( dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, - reinterpret_cast(cmdBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", + reinterpret_cast(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Cannot submit cmd buffer using image (0x%" PRIx64 ") [sub-resource: aspectMask 0x%X array layer %u, mip level %u], " "with layout %s when first use is %s.", reinterpret_cast(cb_image_data.first.image), cb_image_data.first.subresource.aspectMask, @@ -4132,7 +4130,7 @@ static bool ValidateCmdBufImageLayouts(VkCommandBuffer cmdBuffer) { } else { skip_call |= log_msg( dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, - reinterpret_cast(cmdBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", + reinterpret_cast(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS", "Cannot submit cmd buffer using image (0x%" PRIx64 ") with layout %s when " "first use is %s.", reinterpret_cast(cb_image_data.first.image), string_VkImageLayout(imageLayout), @@ -4552,7 +4550,6 @@ static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NO VKAPI_ATTR VkResult VKAPI_CALL QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) { bool skipCall = false; - GLOBAL_CB_NODE *pCBNode = NULL; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map); VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; std::unique_lock lock(global_lock); @@ -4619,8 +4616,8 @@ QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, V } } for (uint32_t i = 0; i < submit->commandBufferCount; i++) { - skipCall |= ValidateCmdBufImageLayouts(submit->pCommandBuffers[i]); - pCBNode = getCBNode(dev_data, submit->pCommandBuffers[i]); + auto pCBNode = getCBNode(dev_data, submit->pCommandBuffers[i]); + skipCall |= ValidateCmdBufImageLayouts(dev_data, pCBNode); if (pCBNode) { pCBNode->semaphores = semaphoreList; pCBNode->submitCount++; // increment submit count @@ -4952,10 +4949,9 @@ VKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool VkQueryResultFlags flags) { layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); unordered_map> queriesInFlight; - GLOBAL_CB_NODE *pCB = nullptr; std::unique_lock lock(global_lock); for (auto cmdBuffer : dev_data->globalInFlightCmdBuffers) { - pCB = getCBNode(dev_data, cmdBuffer); + auto pCB = getCBNode(dev_data, cmdBuffer); for (auto queryStatePair : pCB->queryToStateMap) { queriesInFlight[queryStatePair.first].push_back(cmdBuffer); } @@ -4970,7 +4966,7 @@ VKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool if (queryElement != queriesInFlight.end() && queryToStateElement != dev_data->queryToStateMap.end() && queryToStateElement->second) { for (auto cmdBuffer : queryElement->second) { - pCB = getCBNode(dev_data, cmdBuffer); + auto pCB = getCBNode(dev_data, cmdBuffer); auto queryEventElement = pCB->waitedEventsBeforeQueryReset.find(query); if (queryEventElement == pCB->waitedEventsBeforeQueryReset.end()) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, @@ -4989,7 +4985,7 @@ VKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool // TODO : Can there be the same query in use by multiple command buffers in flight? bool make_available = false; for (auto cmdBuffer : queryElement->second) { - pCB = getCBNode(dev_data, cmdBuffer); + auto pCB = getCBNode(dev_data, cmdBuffer); make_available |= pCB->queryToStateMap[query]; } if (!(((flags & VK_QUERY_RESULT_PARTIAL_BIT) || (flags & VK_QUERY_RESULT_WAIT_BIT)) && make_available)) { -- cgit v1.2.3 From e4c92d5ab6ea4b6a36f4d142698da5cabaee154b Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 17 May 2016 18:47:09 +1200 Subject: layers: Simplify command buffer pool cleanup We don't need to carefully pick through the pool's buffers, removing them. We're about to throw away the whole container. Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 4e584493..6e05d480 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5386,15 +5386,13 @@ DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocatio // Verify that command buffers in pool are complete (not in-flight) VkBool32 result = checkAndClearCommandBuffersInFlight(dev_data, commandPool, "destroy command pool with"); // Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its list from the commandPoolMap - if (dev_data->commandPoolMap.find(commandPool) != dev_data->commandPoolMap.end()) { - for (auto poolCb = dev_data->commandPoolMap[commandPool].commandBuffers.begin(); - poolCb != dev_data->commandPoolMap[commandPool].commandBuffers.end();) { - clear_cmd_buf_and_mem_references(dev_data, *poolCb); - auto del_cb = dev_data->commandBufferMap.find(*poolCb); - delete (*del_cb).second; // delete CB info structure + auto pool_it = dev_data->commandPoolMap.find(commandPool); + if (pool_it != dev_data->commandPoolMap.end()) { + for (auto cb : pool_it->second.commandBuffers) { + clear_cmd_buf_and_mem_references(dev_data, cb); + auto del_cb = dev_data->commandBufferMap.find(cb); + delete del_cb->second; // delete CB info structure dev_data->commandBufferMap.erase(del_cb); // Remove this command buffer - poolCb = dev_data->commandPoolMap[commandPool].commandBuffers.erase( - poolCb); // Remove CB reference from commandPoolMap's list } } dev_data->commandPoolMap.erase(commandPool); -- cgit v1.2.3 From 8ac68a5c55f9662b74db3826f97aa2f28d21503f Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Wed, 18 May 2016 13:43:26 -0600 Subject: layers: Refactor DescriptorSet update interface Mainly refactor and moving code in order to provide an interface to DescriptorSet class that matches top-level vkUpdateDescriptorSets() function. Split the validation of an update as a separate task from performing the update. This allows validation prior to calling down the chain and then only update the state if validation is clean. Hoisted all of the update validation into the DescriptorSet class which prevents having to copy all of the maps into the individual Descriptor classes. This simplifies both their creation and updating their contents. Updated the top-level core_validation UpdateDescriptorSets() code to match Vulkan Validation Layer Authoring Guidelines. As this is an initial POC for the architecture, I kept the Pre* & Post* functions in the core_validation.cpp file, but they should eventually be spun out. --- layers/core_validation.cpp | 94 +++---- layers/descriptor_sets.cpp | 674 ++++++++++++++++++++++++++------------------- layers/descriptor_sets.h | 90 +++--- 3 files changed, 467 insertions(+), 391 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 6e05d480..cd9388ae 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3407,65 +3407,6 @@ static bool validateIdleDescriptorSet(const layer_data *my_data, VkDescriptorSet } return skip_call; } -// update DS mappings based on write and copy update arrays -static bool dsUpdate(layer_data *my_data, VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pWDS, - uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pCDS) { - bool skip_call = false; - // Validate Write updates - uint32_t i = 0; - for (i = 0; i < descriptorWriteCount; i++) { - auto dest_set = pWDS[i].dstSet; - auto set_pair = my_data->setMap.find(dest_set); - if (set_pair == my_data->setMap.end()) { - skip_call |= - log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - reinterpret_cast(dest_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", - "Cannot call vkUpdateDescriptorSets() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", - reinterpret_cast(dest_set)); - } else { - string error_str; - if (!set_pair->second->WriteUpdate(my_data->report_data, &pWDS[i], &error_str)) { - skip_call |= - log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - reinterpret_cast(dest_set), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", - "vkUpdateDescriptorsSets() failed write update for Descriptor Set 0x%" PRIx64 " with error: %s", - reinterpret_cast(dest_set), error_str.c_str()); - } - } - } - // Now validate copy updates - for (i = 0; i < descriptorCopyCount; ++i) { - auto dst_set = pCDS[i].dstSet; - auto src_set = pCDS[i].srcSet; - auto src_pair = my_data->setMap.find(src_set); - auto dst_pair = my_data->setMap.find(dst_set); - if (src_pair == my_data->setMap.end()) { - skip_call |= log_msg( - my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - reinterpret_cast(src_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", - "Cannot call vkUpdateDescriptorSets() to copy from descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", - reinterpret_cast(src_set)); - } else if (dst_pair == my_data->setMap.end()) { - skip_call |= log_msg( - my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - reinterpret_cast(dst_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", - "Cannot call vkUpdateDescriptorSets() to copy to descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", - reinterpret_cast(dst_set)); - } else { - std::string error_str; - if (!dst_pair->second->CopyUpdate(my_data->report_data, &pCDS[i], src_pair->second, &error_str)) { - skip_call |= - log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - reinterpret_cast(dst_set), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", - "vkUpdateDescriptorsSets() failed copy update from Descriptor Set 0x%" PRIx64 - " to Descriptor Set 0x%" PRIx64 " with error: %s", - reinterpret_cast(src_set), reinterpret_cast(dst_set), error_str.c_str()); - } - } - } - return skip_call; -} - // Verify that given pool has descriptors that are being requested for allocation. // NOTE : Calls to this function should be wrapped in mutex static bool validate_descriptor_availability_in_pool(layer_data *dev_data, DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count, @@ -6070,18 +6011,47 @@ FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t co // TODO : Any other clean-up or book-keeping to do here? return result; } +// TODO : This is a Proof-of-concept for core validation architecture +// Really we'll want to break out these functions to separate files but +// keeping it all together here to prove out design +// PreCallValidate* handles validating all of the state prior to calling down chain to UpdateDescriptorSets() +static bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, + const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, + const VkCopyDescriptorSet *pDescriptorCopies) { + // First thing to do is perform map look-ups. + // NOTE : UpdateDescriptorSets is somewhat unique in that it's operating on a number of DescriptorSets + // so we can't just do a single map look-up up-front, but do them individually in functions below + + // Now make call(s) that validate state, but don't perform state updates in this function + // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the + // namespace which will parse params and make calls into specific class instances + return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data->setMap, descriptorWriteCount, + pDescriptorWrites, descriptorCopyCount, pDescriptorCopies); +} +// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets() +static void PostCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, + const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, + const VkCopyDescriptorSet *pDescriptorCopies) { + cvdescriptorset::PerformUpdateDescriptorSets(dev_data->setMap, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, + pDescriptorCopies); +} VKAPI_ATTR void VKAPI_CALL UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) { - // dsUpdate will return true only if a bailout error occurs, so we want to call down tree when update returns false + // Only map look-up at top level is for device-level layer_data layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); std::unique_lock lock(global_lock); - bool rtn = dsUpdate(dev_data, device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies); + bool skip_call = PreCallValidateUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, + pDescriptorCopies); lock.unlock(); - if (!rtn) { + if (!skip_call) { dev_data->device_dispatch_table->UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies); + lock.lock(); + // Since UpdateDescriptorSets() is void, nothing to check prior to updating state + PostCallRecordUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, + pDescriptorCopies); } } diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 1d9eed64..2955a6a3 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -280,9 +280,9 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D auto immut_sampler = p_layout_->GetImmutableSamplerPtrFromIndex(i); for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) { if (immut_sampler) - descriptors_.emplace_back(std::unique_ptr(new SamplerDescriptor(immut_sampler + di, sampler_map_))); + descriptors_.emplace_back(std::unique_ptr(new SamplerDescriptor(immut_sampler + di))); else - descriptors_.emplace_back(std::unique_ptr(new SamplerDescriptor(sampler_map_))); + descriptors_.emplace_back(std::unique_ptr(new SamplerDescriptor())); } break; } @@ -290,11 +290,9 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D auto immut = p_layout_->GetImmutableSamplerPtrFromIndex(i); for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) { if (immut) - descriptors_.emplace_back(std::unique_ptr(new ImageSamplerDescriptor( - immut + di, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, sampler_map_))); + descriptors_.emplace_back(std::unique_ptr(new ImageSamplerDescriptor(immut + di))); else - descriptors_.emplace_back(std::unique_ptr(new ImageSamplerDescriptor( - image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, sampler_map_))); + descriptors_.emplace_back(std::unique_ptr(new ImageSamplerDescriptor())); } break; } @@ -303,20 +301,19 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) - descriptors_.emplace_back(std::unique_ptr( - new ImageDescriptor(type, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_))); + descriptors_.emplace_back(std::unique_ptr(new ImageDescriptor(type))); break; case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) - descriptors_.emplace_back(std::unique_ptr(new TexelDescriptor(type, buffer_view_map_))); + descriptors_.emplace_back(std::unique_ptr(new TexelDescriptor(type))); break; case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) - descriptors_.emplace_back(std::unique_ptr(new BufferDescriptor(type, buffer_map_))); + descriptors_.emplace_back(std::unique_ptr(new BufferDescriptor(type))); break; default: assert(0); // Bad descriptor type specified @@ -468,74 +465,22 @@ void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers() { } } // Perform write update in given update struct -// If an error occurs, return false and fill in details in error_msg string -bool cvdescriptorset::DescriptorSet::WriteUpdate(debug_report_data *report_data, const VkWriteDescriptorSet *update, - std::string *error_msg) { +void cvdescriptorset::DescriptorSet::PerformWriteUpdate(const VkWriteDescriptorSet *update) { auto num_updates = 0; - // Verify idle ds - if (in_use.load()) { - std::stringstream error_str; - error_str << "Cannot call vkUpdateDescriptorSets() to perform write update on descriptor set " << set_ - << " that is in use by a command buffer."; - *error_msg = error_str.str(); - return false; - } - // Verify dst binding exists - if (!p_layout_->HasBinding(update->dstBinding)) { - std::stringstream error_str; - error_str << "DescriptorSet " << set_ << " does not have binding " << update->dstBinding << "."; - *error_msg = error_str.str(); - return false; - } else { - // We know that binding is valid, verify update and do update on each descriptor - auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement; - auto type = p_layout_->GetTypeFromBinding(update->dstBinding); - if (type != update->descriptorType) { - std::stringstream error_str; - error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with type " - << string_VkDescriptorType(type) << " but update type is " << string_VkDescriptorType(update->descriptorType); - *error_msg = error_str.str(); - return false; - } - if ((start_idx + update->descriptorCount) > p_layout_->GetTotalDescriptorCount()) { - std::stringstream error_str; - error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with " - << p_layout_->GetTotalDescriptorCount() << " total descriptors but update of " << update->descriptorCount - << " descriptors starting at binding offset of " - << p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) - << " combined with update array element offset of " << update->dstArrayElement - << " oversteps the size of this descriptor set."; - *error_msg = error_str.str(); - return false; - } - // Verify consecutive bindings match (if needed) - if (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, - "write update to", set_, error_msg)) - return false; - // Update is within bounds and consistent so perform update - for (uint32_t di = 0; di < update->descriptorCount; ++di) { - // TODO : Can we break this into a set-level "Validate" followed by Descriptor updating itself - // if the validate passes? That saves us all the map ptrs in each descriptor instance - if (!descriptors_[start_idx + di]->WriteUpdate(update, di, error_msg)) { - std::stringstream error_str; - error_str << "Write update to descriptor at global index " << start_idx + di << " within set " << set_ - << " binding #" << update->dstBinding << " failed with error message: " << error_msg->c_str(); - *error_msg = error_str.str(); - return false; - } - ++num_updates; - } + auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement; + // perform update + for (uint32_t di = 0; di < update->descriptorCount; ++di) { + descriptors_[start_idx + di]->WriteUpdate(update, di); + ++num_updates; } if (num_updates != 0) { some_update_ = true; } InvalidateBoundCmdBuffers(); - return true; } -// Copy update -bool cvdescriptorset::DescriptorSet::CopyUpdate(debug_report_data *report_data, const VkCopyDescriptorSet *update, - const DescriptorSet *src_set, std::string *error) { - auto num_updates = 0; +// Validate Copy update +bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data *report_data, const VkCopyDescriptorSet *update, + const DescriptorSet *src_set, std::string *error) { // Verify idle ds if (in_use.load()) { std::stringstream error_str; @@ -598,28 +543,34 @@ bool cvdescriptorset::DescriptorSet::CopyUpdate(debug_report_data *report_data, set_, error))) { return false; } + // Update parameters all look good so verify update contents + if (!VerifyCopyUpdateContents(update, src_set, src_start_idx, error)) + return false; + + // All checks passed so update is good + return true; +} +// Perform Copy update +void cvdescriptorset::DescriptorSet::PerformCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *src_set) { + auto num_updates = 0; + auto src_start_idx = src_set->GetGlobalStartIndexFromBinding(update->srcBinding) + update->srcArrayElement; + auto dst_start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement; // Update parameters all look good so perform update for (uint32_t di = 0; di < update->descriptorCount; ++di) { - if (!descriptors_[dst_start_idx]->CopyUpdate(src_set->descriptors_[src_start_idx].get(), error)) - return false; + descriptors_[dst_start_idx + di]->CopyUpdate(src_set->descriptors_[src_start_idx + di].get()); ++num_updates; } if (num_updates != 0) { some_update_ = true; } InvalidateBoundCmdBuffers(); - return true; } -cvdescriptorset::SamplerDescriptor::SamplerDescriptor( - const std::unordered_map> *sampler_map) - : sampler_(VK_NULL_HANDLE), immutable_(false), sampler_map_(sampler_map) { +cvdescriptorset::SamplerDescriptor::SamplerDescriptor() : sampler_(VK_NULL_HANDLE), immutable_(false) { updated = false; descriptor_class = PlainSampler; }; -cvdescriptorset::SamplerDescriptor::SamplerDescriptor( - const VkSampler *immut, const std::unordered_map> *sampler_map) - : sampler_(VK_NULL_HANDLE), immutable_(false), sampler_map_(sampler_map) { +cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const VkSampler *immut) : sampler_(VK_NULL_HANDLE), immutable_(false) { updated = false; descriptor_class = PlainSampler; if (immut) { @@ -726,75 +677,26 @@ bool cvdescriptorset::ValidateImageUpdate(const VkImageView image_view, const Vk } return true; } -bool cvdescriptorset::SamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index, std::string *error) { - if (!immutable_) { - if (!ValidateSampler(update->pImageInfo[index].sampler, sampler_map_)) { - std::stringstream error_str; - error_str << "Attempted write update to sampler descriptor with invalid sampler: " << update->pImageInfo[index].sampler - << "."; - *error = error_str.str(); - return false; - } - sampler_ = update->pImageInfo[index].sampler; - } else { - if (!ValidateSampler(sampler_, sampler_map_)) { - std::stringstream error_str; - error_str << "Attempted write update to immutable sampler descriptor which has invalid immutable sampler: " << sampler_ - << "."; - *error = error_str.str(); - return false; - } - // TODO : Do we want a way to warn here in case of updating immutable sampler (which can't be updated)? - } +void cvdescriptorset::SamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { + sampler_ = update->pImageInfo[index].sampler; updated = true; - return true; } -bool cvdescriptorset::SamplerDescriptor::CopyUpdate(const Descriptor *src, std::string *error) { +void cvdescriptorset::SamplerDescriptor::CopyUpdate(const Descriptor *src) { if (!immutable_) { auto update_sampler = static_cast(src)->sampler_; - if (!ValidateSampler(update_sampler, sampler_map_)) { - std::stringstream error_str; - error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << "."; - *error = error_str.str(); - return false; - } sampler_ = update_sampler; - } else { - if (!ValidateSampler(sampler_, sampler_map_)) { - std::stringstream error_str; - error_str << "Attempted copy update to immutable sampler descriptor which has invalid immutable sampler: " << sampler_ - << "."; - *error = error_str.str(); - return false; - } - // TODO : Do we want a way to warn here in case of updating immutable sampler (which can't be updated)? } updated = true; - return true; } -cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor( - const std::unordered_map *image_view_map, - const std::unordered_map *image_map, - const std::unordered_map *image_to_swapchain_map, - const std::unordered_map *swapchain_map, - const std::unordered_map> *sampler_map) - : sampler_(VK_NULL_HANDLE), immutable_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED), - sampler_map_(sampler_map), image_view_map_(image_view_map), image_map_(image_map), - image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { +cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor() + : sampler_(VK_NULL_HANDLE), immutable_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) { updated = false; descriptor_class = ImageSampler; } -cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor( - const VkSampler *immut, const std::unordered_map *image_view_map, - const std::unordered_map *image_map, - const std::unordered_map *image_to_swapchain_map, - const std::unordered_map *swapchain_map, - const std::unordered_map> *sampler_map) - : sampler_(VK_NULL_HANDLE), immutable_(true), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED), - sampler_map_(sampler_map), image_view_map_(image_view_map), image_map_(image_map), - image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { +cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(const VkSampler *immut) + : sampler_(VK_NULL_HANDLE), immutable_(true), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) { updated = false; descriptor_class = ImageSampler; if (immut) { @@ -803,134 +705,51 @@ cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor( updated = true; } } -bool cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index, - std::string *error) { - // First check sampler - if (!immutable_) { - if (!ValidateSampler(update->pImageInfo[index].sampler, sampler_map_)) { - std::stringstream error_str; - error_str << "Attempted write update to combined image sampler descriptor with invalid sampler: " - << update->pImageInfo[index].sampler << "."; - *error = error_str.str(); - return false; - } - sampler_ = update->pImageInfo[index].sampler; - } else { - if (!ValidateSampler(sampler_, sampler_map_)) { - std::stringstream error_str; - error_str << "Attempted write update to combined image sampler descriptor with immutable sampler which has invalid " - "immutable sampler: " - << sampler_ << "."; - *error = error_str.str(); - return false; - } - // TODO : Do we want a way to warn here in case of updating immutable sampler (which can't be updated)? - } - // Now validate images - auto image_view = update->pImageInfo[index].imageView; - auto image_layout = update->pImageInfo[index].imageLayout; - if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, - error)) { - std::stringstream error_str; - error_str << "Attempted write update to combined image sampler descriptor failed due to: " << error->c_str(); - *error = error_str.str(); - return false; - } +void cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { updated = true; - image_view_ = image_view; - image_layout_ = image_layout; - return true; + auto image_info = update->pImageInfo[index]; + sampler_ = image_info.sampler; + image_view_ = image_info.imageView; + image_layout_ = image_info.imageLayout; } -bool cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(const Descriptor *src, std::string *error) { +void cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(const Descriptor *src) { if (!immutable_) { auto update_sampler = static_cast(src)->sampler_; - if (!ValidateSampler(update_sampler, sampler_map_)) { - std::stringstream error_str; - error_str << "Attempted copy update to combined image sampler descriptor with invalid sampler: " << update_sampler - << "."; - *error = error_str.str(); - return false; - } sampler_ = update_sampler; - } else { - if (!ValidateSampler(sampler_, sampler_map_)) { - std::stringstream error_str; - error_str << "Attempted copy update to combined image sampler descriptor with immutable sampler that has invalid " - "immutable sampler: " - << sampler_ << "."; - *error = error_str.str(); - return false; - } - // TODO : Do we want a way to warn here in case of updating immutable sampler (which can't be updated)? } - // Now validate images auto image_view = static_cast(src)->image_view_; auto image_layout = static_cast(src)->image_layout_; - if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, - error)) { - std::stringstream error_str; - error_str << "Attempted copy update to combined image sampler descriptor failed due to: " << error->c_str(); - *error = error_str.str(); - return false; - } updated = true; image_view_ = image_view; image_layout_ = image_layout; - return true; } -cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type, - const std::unordered_map *image_view_map, - const std::unordered_map *image_map, - const std::unordered_map *image_to_swapchain_map, - const std::unordered_map *swapchain_map) - : storage_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED), image_view_map_(image_view_map), - image_map_(image_map), image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { +cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type) + : storage_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) { updated = false; descriptor_class = Image; if (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE == type) storage_ = true; }; -bool cvdescriptorset::ImageDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index, std::string *error) { - // First validate that the write update is valid - auto image_view = update->pImageInfo[index].imageView; - auto image_layout = update->pImageInfo[index].imageLayout; - if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, - error)) { - std::stringstream error_str; - error_str << "Attempted write update to image descriptor failed due to: " << error->c_str(); - *error = error_str.str(); - return false; - } - // Update is clean so process it +void cvdescriptorset::ImageDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { updated = true; - image_view_ = image_view; - image_layout_ = image_layout; - return true; + auto image_info = update->pImageInfo[index]; + image_view_ = image_info.imageView; + image_layout_ = image_info.imageLayout; } -bool cvdescriptorset::ImageDescriptor::CopyUpdate(const Descriptor *src, std::string *error) { - // First validate update +void cvdescriptorset::ImageDescriptor::CopyUpdate(const Descriptor *src) { auto image_view = static_cast(src)->image_view_; auto image_layout = static_cast(src)->image_layout_; - if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, - error)) { - std::stringstream error_str; - error_str << "Attempted copy update to image descriptor failed due to: " << error->c_str(); - *error = error_str.str(); - return false; - } updated = true; image_view_ = image_view; image_layout_ = image_layout; - return true; } -cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type, - const std::unordered_map *buffer_map) - : storage_(false), dynamic_(false), buffer_(VK_NULL_HANDLE), offset_(0), range_(0), buffer_map_(buffer_map) { +cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type) + : storage_(false), dynamic_(false), buffer_(VK_NULL_HANDLE), offset_(0), range_(0) { updated = false; descriptor_class = GeneralBuffer; if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) { @@ -942,70 +761,361 @@ cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type, storage_ = true; } } -bool cvdescriptorset::BufferDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index, std::string *error) { - // First validate bufferinfo - auto buffer = update->pBufferInfo[index].buffer; - if (!buffer_map_->count(buffer)) { - std::stringstream error_str; - error_str << "Attempted write update to buffer descriptor with invalid buffer: " << buffer; - *error = error_str.str(); - return false; - } +void cvdescriptorset::BufferDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { updated = true; - buffer_ = buffer; - offset_ = update->pBufferInfo[index].offset; - range_ = update->pBufferInfo[index].range; - return true; + auto buffer_info = update->pBufferInfo[index]; + buffer_ = buffer_info.buffer; + offset_ = buffer_info.offset; + range_ = buffer_info.range; } -bool cvdescriptorset::BufferDescriptor::CopyUpdate(const Descriptor *src, std::string *error) { - // First validate bufferinfo - auto buffer = static_cast(src)->buffer_; - if (!buffer_map_->count(buffer)) { - std::stringstream error_str; - error_str << "Attempted copy update to buffer descriptor with invalid buffer: " << buffer; - *error = error_str.str(); - return false; - } +void cvdescriptorset::BufferDescriptor::CopyUpdate(const Descriptor *src) { + auto buff_desc = static_cast(src); updated = true; - buffer_ = buffer; - offset_ = static_cast(src)->offset_; - range_ = static_cast(src)->range_; - return true; + buffer_ = buff_desc->buffer_; + offset_ = buff_desc->offset_; + range_ = buff_desc->range_; } -cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type, - const std::unordered_map *buffer_view_map) - : buffer_view_(VK_NULL_HANDLE), storage_(false), buffer_view_map_(buffer_view_map) { +cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type) : buffer_view_(VK_NULL_HANDLE), storage_(false) { updated = false; descriptor_class = TexelBuffer; if (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER == type) storage_ = true; }; -bool cvdescriptorset::TexelDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index, std::string *error) { - // First validate buffer view - auto buffer_view = update->pTexelBufferView[index]; - if (!buffer_view_map_->count(buffer_view)) { - std::stringstream error_str; - error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view; - *error = error_str.str(); - return false; - } +void cvdescriptorset::TexelDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { updated = true; - buffer_view_ = buffer_view; - return true; + buffer_view_ = update->pTexelBufferView[index]; } -bool cvdescriptorset::TexelDescriptor::CopyUpdate(const Descriptor *src, std::string *error) { - // First validate buffer view - auto buffer_view = static_cast(src)->buffer_view_; - if (!buffer_view_map_->count(buffer_view)) { +void cvdescriptorset::TexelDescriptor::CopyUpdate(const Descriptor *src) { + updated = true; + buffer_view_ = static_cast(src)->buffer_view_; +} +// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated +// sets, and then calls their respective Validate[Write|Copy]Update functions. +// If the update hits an issue for which the callback returns "true", meaning that the call down the chain should +// be skipped, then true is returned. +// If there is no issue with the update, then false is returned. +bool cvdescriptorset::ValidateUpdateDescriptorSets( + const debug_report_data *report_data, const std::unordered_map &set_map, + const uint32_t write_count, const VkWriteDescriptorSet *p_wds, const uint32_t copy_count, const VkCopyDescriptorSet *p_cds) { + bool skip_call = false; + // Validate Write updates + uint32_t i = 0; + for (i = 0; i < write_count; i++) { + auto dest_set = p_wds[i].dstSet; + auto set_pair = set_map.find(dest_set); + if (set_pair == set_map.end()) { + skip_call |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, + reinterpret_cast(dest_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", + "Cannot call vkUpdateDescriptorSets() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", + reinterpret_cast(dest_set)); + } else { + std::string error_str; + if (!set_pair->second->ValidateWriteUpdate(report_data, &p_wds[i], &error_str)) { + skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, + reinterpret_cast(dest_set), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", + "vkUpdateDescriptorsSets() failed write update validation for Descriptor Set 0x%" PRIx64 + " with error: %s", + reinterpret_cast(dest_set), error_str.c_str()); + } + } + } + // Now validate copy updates + for (i = 0; i < copy_count; ++i) { + auto dst_set = p_cds[i].dstSet; + auto src_set = p_cds[i].srcSet; + auto src_pair = set_map.find(src_set); + auto dst_pair = set_map.find(dst_set); + if (src_pair == set_map.end()) { + skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, + reinterpret_cast(src_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", + "Cannot call vkUpdateDescriptorSets() to copy from descriptor set 0x%" PRIxLEAST64 + " that has not been allocated.", + reinterpret_cast(src_set)); + } else if (dst_pair == set_map.end()) { + skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, + reinterpret_cast(dst_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", + "Cannot call vkUpdateDescriptorSets() to copy to descriptor set 0x%" PRIxLEAST64 + " that has not been allocated.", + reinterpret_cast(dst_set)); + } else { + std::string error_str; + if (!dst_pair->second->ValidateCopyUpdate(report_data, &p_cds[i], src_pair->second, &error_str)) { + skip_call |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, + reinterpret_cast(dst_set), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", + "vkUpdateDescriptorsSets() failed copy update from Descriptor Set 0x%" PRIx64 + " to Descriptor Set 0x%" PRIx64 " with error: %s", + reinterpret_cast(src_set), reinterpret_cast(dst_set), error_str.c_str()); + } + } + } + return skip_call; +} +// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated +// sets, and then calls their respective Perform[Write|Copy]Update functions. +// Prerequisite : ValidateUpdateDescriptorSets() should be called and return "false" prior to calling PerformUpdateDescriptorSets() +// with the same set of updates. +// This is split from the validate code to allow validation prior to calling down the chain, and then update after +// calling down the chain. +void cvdescriptorset::PerformUpdateDescriptorSets( + const std::unordered_map &set_map, const uint32_t write_count, + const VkWriteDescriptorSet *p_wds, const uint32_t copy_count, const VkCopyDescriptorSet *p_cds) { + // Write updates first + uint32_t i = 0; + for (i = 0; i < write_count; ++i) { + auto dest_set = p_wds[i].dstSet; + auto set_pair = set_map.find(dest_set); + if (set_pair != set_map.end()) { + set_pair->second->PerformWriteUpdate(&p_wds[i]); + } + } + // Now copy updates + for (i = 0; i < copy_count; ++i) { + auto dst_set = p_cds[i].dstSet; + auto src_set = p_cds[i].srcSet; + auto src_pair = set_map.find(src_set); + auto dst_pair = set_map.find(dst_set); + if (src_pair != set_map.end() && dst_pair != set_map.end()) { + dst_pair->second->PerformCopyUpdate(&p_cds[i], src_pair->second); + } + } +} +// Validate the state for a given write update but don't actually perform the update +// If an error would occur for this update, return false and fill in details in error_msg string +bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data *report_data, const VkWriteDescriptorSet *update, + std::string *error_msg) { + // Verify idle ds + if (in_use.load()) { std::stringstream error_str; - error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view; - *error = error_str.str(); + error_str << "Cannot call vkUpdateDescriptorSets() to perform write update on descriptor set " << set_ + << " that is in use by a command buffer."; + *error_msg = error_str.str(); return false; } - updated = true; - buffer_view_ = buffer_view; + // Verify dst binding exists + if (!p_layout_->HasBinding(update->dstBinding)) { + std::stringstream error_str; + error_str << "DescriptorSet " << set_ << " does not have binding " << update->dstBinding << "."; + *error_msg = error_str.str(); + return false; + } else { + // We know that binding is valid, verify update and do update on each descriptor + auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement; + auto type = p_layout_->GetTypeFromBinding(update->dstBinding); + if (type != update->descriptorType) { + std::stringstream error_str; + error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with type " + << string_VkDescriptorType(type) << " but update type is " << string_VkDescriptorType(update->descriptorType); + *error_msg = error_str.str(); + return false; + } + if ((start_idx + update->descriptorCount) > p_layout_->GetTotalDescriptorCount()) { + std::stringstream error_str; + error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with " + << p_layout_->GetTotalDescriptorCount() << " total descriptors but update of " << update->descriptorCount + << " descriptors starting at binding offset of " + << p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + << " combined with update array element offset of " << update->dstArrayElement + << " oversteps the size of this descriptor set."; + *error_msg = error_str.str(); + return false; + } + // Verify consecutive bindings match (if needed) + if (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, + "write update to", set_, error_msg)) + return false; + // Update is within bounds and consistent so last step is to validate update contents + if (!VerifyWriteUpdateContents(update, start_idx, error_msg)) { + std::stringstream error_str; + error_str << "Write update to descriptor in set " << set_ << " binding #" << update->dstBinding + << " failed with error message: " << error_msg->c_str(); + *error_msg = error_str.str(); + return false; + } + } + // All checks passed, update is clean return true; } +// Verify that the contents of the update are ok, but don't perform actual update +bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDescriptorSet *update, const uint32_t index, + std::string *error) const { + switch (update->descriptorType) { + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { + for (uint32_t di = 0; di < update->descriptorCount; ++di) { + // Validate image + auto image_view = update->pImageInfo[di].imageView; + auto image_layout = update->pImageInfo[di].imageLayout; + if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, + error)) { + std::stringstream error_str; + error_str << "Attempted write update to combined image sampler descriptor failed due to: " << error->c_str(); + *error = error_str.str(); + return false; + } + } + // Intentional fall-through to validate sampler + } + case VK_DESCRIPTOR_TYPE_SAMPLER: { + for (uint32_t di = 0; di < update->descriptorCount; ++di) { + if (!descriptors_[index + di].get()->IsImmutableSampler()) { + if (!ValidateSampler(update->pImageInfo[di].sampler, sampler_map_)) { + std::stringstream error_str; + error_str << "Attempted write update to sampler descriptor with invalid sampler: " + << update->pImageInfo[di].sampler << "."; + *error = error_str.str(); + return false; + } + } else { + // TODO : Warn here + } + } + break; + } + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { + for (uint32_t di = 0; di < update->descriptorCount; ++di) { + auto image_view = update->pImageInfo[di].imageView; + auto image_layout = update->pImageInfo[di].imageLayout; + if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, + error)) { + std::stringstream error_str; + error_str << "Attempted write update to image descriptor failed due to: " << error->c_str(); + *error = error_str.str(); + return false; + } + } + break; + } + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: { + for (uint32_t di = 0; di < update->descriptorCount; ++di) { + auto buffer_view = update->pTexelBufferView[di]; + if (!buffer_view_map_->count(buffer_view)) { + std::stringstream error_str; + error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view; + *error = error_str.str(); + return false; + } + } + break; + } + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: { + for (uint32_t di = 0; di < update->descriptorCount; ++di) { + auto buffer = update->pBufferInfo[di].buffer; + if (!buffer_map_->count(buffer)) { + std::stringstream error_str; + error_str << "Attempted write update to buffer descriptor with invalid buffer: " << buffer; + *error = error_str.str(); + return false; + } + } + break; + } + default: + assert(0); // We've already verified update type so should never get here + break; + } + // All checks passed so update contents are good + return true; +} +// Verify that the contents of the update are ok, but don't perform actual update +bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescriptorSet *update, const DescriptorSet *src_set, + const uint32_t index, std::string *error) const { + switch (src_set->descriptors_[index]->descriptor_class) { + case PlainSampler: { + for (uint32_t di = 0; di < update->descriptorCount; ++di) { + if (!src_set->descriptors_[index + di]->IsImmutableSampler()) { + auto update_sampler = static_cast(src_set->descriptors_[index + di].get())->GetSampler(); + if (!ValidateSampler(update_sampler, sampler_map_)) { + std::stringstream error_str; + error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << "."; + *error = error_str.str(); + return false; + } + } else { + // TODO : Warn here + } + } + break; + } + case ImageSampler: { + for (uint32_t di = 0; di < update->descriptorCount; ++di) { + auto img_samp_desc = static_cast(src_set->descriptors_[index + di].get()); + // First validate sampler + if (!img_samp_desc->IsImmutableSampler()) { + auto update_sampler = img_samp_desc->GetSampler(); + if (!ValidateSampler(update_sampler, sampler_map_)) { + std::stringstream error_str; + error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << "."; + *error = error_str.str(); + return false; + } + } else { + // TODO : Warn here + } + // Validate image + auto image_view = img_samp_desc->GetImageView(); + auto image_layout = img_samp_desc->GetImageLayout(); + if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, + error)) { + std::stringstream error_str; + error_str << "Attempted write update to combined image sampler descriptor failed due to: " << error->c_str(); + *error = error_str.str(); + return false; + } + } + } + case Image: { + for (uint32_t di = 0; di < update->descriptorCount; ++di) { + auto img_desc = static_cast(src_set->descriptors_[index + di].get()); + auto image_view = img_desc->GetImageView(); + auto image_layout = img_desc->GetImageLayout(); + if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, + error)) { + std::stringstream error_str; + error_str << "Attempted write update to image descriptor failed due to: " << error->c_str(); + *error = error_str.str(); + return false; + } + } + break; + } + case TexelBuffer: { + for (uint32_t di = 0; di < update->descriptorCount; ++di) { + auto buffer_view = static_cast(src_set->descriptors_[index + di].get())->GetBufferView(); + if (!buffer_view_map_->count(buffer_view)) { + std::stringstream error_str; + error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view; + *error = error_str.str(); + return false; + } + } + break; + } + case GeneralBuffer: { + for (uint32_t di = 0; di < update->descriptorCount; ++di) { + auto buffer = static_cast(src_set->descriptors_[index + di].get())->GetBuffer(); + if (!buffer_map_->count(buffer)) { + std::stringstream error_str; + error_str << "Attempted write update to buffer descriptor with invalid buffer: " << buffer; + *error = error_str.str(); + return false; + } + } + break; + } + default: + assert(0); // We've already verified update type so should never get here + break; + } + // All checks passed so update contents are good + return true; +} \ No newline at end of file diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 5abe45fc..655d5720 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -146,8 +146,8 @@ typedef enum _DescriptorClass { PlainSampler, ImageSampler, Image, TexelBuffer, class Descriptor { public: virtual ~Descriptor(){}; - virtual bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) = 0; - virtual bool CopyUpdate(const Descriptor *, std::string *) = 0; + virtual void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) = 0; + virtual void CopyUpdate(const Descriptor *) = 0; virtual DescriptorClass GetClass() const { return descriptor_class; }; // Special fast-path check for SamplerDescriptors that are immutable virtual bool IsImmutableSampler() const { return false; }; @@ -167,51 +167,41 @@ bool ValidateImageUpdate(const VkImageView, const VkImageLayout, const std::unor class SamplerDescriptor : public Descriptor { public: - SamplerDescriptor(const std::unordered_map> *); - SamplerDescriptor(const VkSampler *, const std::unordered_map> *); - bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) override; - bool CopyUpdate(const Descriptor *, std::string *) override; + SamplerDescriptor(); + SamplerDescriptor(const VkSampler *); + void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override; + void CopyUpdate(const Descriptor *) override; virtual bool IsImmutableSampler() const override { return immutable_; }; + VkSampler GetSampler() const { return sampler_; } private: // bool ValidateSampler(const VkSampler) const; VkSampler sampler_; bool immutable_; - const std::unordered_map> *sampler_map_; }; class ImageSamplerDescriptor : public Descriptor { public: - ImageSamplerDescriptor(const std::unordered_map *, - const std::unordered_map *, const std::unordered_map *, - const std::unordered_map *, - const std::unordered_map> *); - ImageSamplerDescriptor(const VkSampler *, const std::unordered_map *, - const std::unordered_map *, const std::unordered_map *, - const std::unordered_map *, - const std::unordered_map> *); - bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) override; - bool CopyUpdate(const Descriptor *, std::string *) override; + ImageSamplerDescriptor(); + ImageSamplerDescriptor(const VkSampler *); + void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override; + void CopyUpdate(const Descriptor *) override; + VkSampler GetSampler() const { return sampler_; } + VkImageView GetImageView() const { return image_view_; } + VkImageLayout GetImageLayout() const { return image_layout_; } private: VkSampler sampler_; bool immutable_; VkImageView image_view_; VkImageLayout image_layout_; - const std::unordered_map> *sampler_map_; - const std::unordered_map *image_view_map_; - const std::unordered_map *image_map_; - const std::unordered_map *image_to_swapchain_map_; - const std::unordered_map *swapchain_map_; }; class ImageDescriptor : public Descriptor { public: - ImageDescriptor(const VkDescriptorType, const std::unordered_map *, - const std::unordered_map *, const std::unordered_map *, - const std::unordered_map *); - bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) override; - bool CopyUpdate(const Descriptor *, std::string *) override; + ImageDescriptor(const VkDescriptorType); + void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override; + void CopyUpdate(const Descriptor *) override; virtual bool IsStorage() const override { return storage_; } VkImageView GetImageView() const { return image_view_; } VkImageLayout GetImageLayout() const { return image_layout_; } @@ -220,31 +210,26 @@ class ImageDescriptor : public Descriptor { bool storage_; VkImageView image_view_; VkImageLayout image_layout_; - const std::unordered_map *image_view_map_; - const std::unordered_map *image_map_; - const std::unordered_map *image_to_swapchain_map_; - const std::unordered_map *swapchain_map_; }; class TexelDescriptor : public Descriptor { public: - TexelDescriptor(const VkDescriptorType, const std::unordered_map *); - bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) override; - bool CopyUpdate(const Descriptor *, std::string *) override; + TexelDescriptor(const VkDescriptorType); + void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override; + void CopyUpdate(const Descriptor *) override; virtual bool IsStorage() const override { return storage_; } VkBufferView GetBufferView() const { return buffer_view_; } private: VkBufferView buffer_view_; bool storage_; - const std::unordered_map *buffer_view_map_; }; class BufferDescriptor : public Descriptor { public: - BufferDescriptor(const VkDescriptorType, const std::unordered_map *); - bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) override; - bool CopyUpdate(const Descriptor *, std::string *) override; + BufferDescriptor(const VkDescriptorType); + void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override; + void CopyUpdate(const Descriptor *) override; virtual bool IsDynamic() const override { return dynamic_; } virtual bool IsStorage() const override { return storage_; } VkBuffer GetBuffer() const { return buffer_; } @@ -257,11 +242,15 @@ class BufferDescriptor : public Descriptor { VkBuffer buffer_; VkDeviceSize offset_; VkDeviceSize range_; - const std::unordered_map *buffer_map_; }; -// Helper function for Updating descriptor sets since it crosses multiple sets -void UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites, - uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies); +// Helper functions for Updating descriptor sets since it crosses multiple sets +// Validate will make sure an update is ok without actually performing it +bool ValidateUpdateDescriptorSets(const debug_report_data *, + const std::unordered_map &, const uint32_t, + const VkWriteDescriptorSet *, const uint32_t, const VkCopyDescriptorSet *); +// Perform does the update with the assumption that ValidateUpdateDescriptorSets() has passed for the given update +void PerformUpdateDescriptorSets(const std::unordered_map &, const uint32_t, + const VkWriteDescriptorSet *, const uint32_t, const VkCopyDescriptorSet *); /* * DescriptorSet class * @@ -323,10 +312,16 @@ class DescriptorSet : public BASE_NODE { // For all descriptors in a set, add any buffers and images that may be updated to their respective unordered_sets & return // number of objects inserted uint32_t GetAllStorageUpdates(std::unordered_set *, std::unordered_set *) const; - // Perform write update based on update struct - bool WriteUpdate(debug_report_data *, const VkWriteDescriptorSet *, std::string *); - // Perform copy update, using 'this' set as the dest and the passed-in DescriptorSet as the src - bool CopyUpdate(debug_report_data *, const VkCopyDescriptorSet *, const DescriptorSet *, std::string *); + + // Descriptor Update functions. These functions validate state and perform update separately + // Validate contents of a WriteUpdate + bool ValidateWriteUpdate(const debug_report_data *, const VkWriteDescriptorSet *, std::string *); + // Perform a WriteUpdate whose contents were just validated using ValidateWriteUpdate + void PerformWriteUpdate(const VkWriteDescriptorSet *); + // Validate contents of a CopyUpdate + bool ValidateCopyUpdate(const debug_report_data *, const VkCopyDescriptorSet *, const DescriptorSet *, std::string *); + // Perform a CopyUpdate whose contents were just validated using ValidateCopyUpdate + void PerformCopyUpdate(const VkCopyDescriptorSet *, const DescriptorSet *); const DescriptorSetLayout *GetLayout() const { return p_layout_; }; VkDescriptorSet GetSet() const { return set_; }; @@ -350,7 +345,8 @@ class DescriptorSet : public BASE_NODE { bool IsUpdated() const { return some_update_; }; private: - bool ValidateUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) const; + bool VerifyWriteUpdateContents(const VkWriteDescriptorSet *, const uint32_t, std::string *) const; + bool VerifyCopyUpdateContents(const VkCopyDescriptorSet *, const DescriptorSet *, const uint32_t, std::string *) const; // Private helper to set all bound cmd buffers to INVALID state void InvalidateBoundCmdBuffers(); bool some_update_; // has any part of the set ever been updated? -- cgit v1.2.3 From 84f4ee9f6ff75d1fa1127af0952709f858a5f5b3 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 19 May 2016 08:00:00 -0600 Subject: layers: DescriptorSet class clean-up Minor formatting improvements, removed some useless "const" decls and unused vars and updated a few error codes to be more appropriate. --- layers/core_validation.cpp | 4 ++-- layers/descriptor_sets.cpp | 51 ++++++++++++++++++++++++---------------------- layers/descriptor_sets.h | 14 ++++++------- 3 files changed, 35 insertions(+), 34 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index cd9388ae..62874f35 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5944,8 +5944,8 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo } // Create new DescriptorSet instance and add to the pool's unordered_set of DescriptorSets cvdescriptorset::DescriptorSet *pNewNode = new cvdescriptorset::DescriptorSet( - pDescriptorSets[i], layout_pair->second, dev_data->report_data, &dev_data->bufferMap, &dev_data->memObjMap, - &dev_data->bufferViewMap, &dev_data->samplerMap, &dev_data->imageViewMap, &dev_data->imageMap, + pDescriptorSets[i], layout_pair->second, &dev_data->bufferMap, &dev_data->memObjMap, &dev_data->bufferViewMap, + &dev_data->samplerMap, &dev_data->imageViewMap, &dev_data->imageMap, &dev_data->device_extensions.imageToSwapchainMap, &dev_data->device_extensions.swapchainMap); if (NULL == pNewNode) { if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index d178a916..5fc1de3f 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -59,6 +59,7 @@ void cvdescriptorset::DescriptorSetLayout::FillBindingSet(std::unordered_setinsert(binding_index_pair.first); } + VkDescriptorSetLayoutBinding const * cvdescriptorset::DescriptorSetLayout::GetDescriptorSetLayoutBindingPtrFromBinding(const uint32_t binding) const { const auto &bi_itr = binding_to_index_map_.find(binding); @@ -260,7 +261,6 @@ bool cvdescriptorset::DescriptorSetLayout::VerifyUpdateConsistency(uint32_t curr } cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout, - const debug_report_data *debug_report_data, const std::unordered_map *buffer_map, const std::unordered_map *memory_map, const std::unordered_map *buffer_view_map, @@ -269,9 +269,9 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D const std::unordered_map *image_map, const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map) - : some_update_(false), set_(set), p_layout_(layout), report_data_(debug_report_data), buffer_map_(buffer_map), - memory_map_(memory_map), buffer_view_map_(buffer_view_map), sampler_map_(sampler_map), image_view_map_(image_view_map), - image_map_(image_map), image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { + : some_update_(false), set_(set), p_layout_(layout), buffer_map_(buffer_map), memory_map_(memory_map), + buffer_view_map_(buffer_view_map), sampler_map_(sampler_map), image_view_map_(image_view_map), image_map_(image_map), + image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { // Foreach binding, create default descriptors of given type for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) { auto type = p_layout_->GetTypeFromIndex(i); @@ -321,6 +321,7 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D } } } + cvdescriptorset::DescriptorSet::~DescriptorSet() { InvalidateBoundCmdBuffers(); // Remove link to any cmd buffers @@ -466,16 +467,14 @@ void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers() { } // Perform write update in given update struct void cvdescriptorset::DescriptorSet::PerformWriteUpdate(const VkWriteDescriptorSet *update) { - auto num_updates = 0; auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement; // perform update for (uint32_t di = 0; di < update->descriptorCount; ++di) { descriptors_[start_idx + di]->WriteUpdate(update, di); - ++num_updates; } - if (num_updates != 0) { + if (update->descriptorCount) some_update_ = true; - } + InvalidateBoundCmdBuffers(); } // Validate Copy update @@ -562,19 +561,18 @@ bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data } // Perform Copy update void cvdescriptorset::DescriptorSet::PerformCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *src_set) { - auto num_updates = 0; auto src_start_idx = src_set->GetGlobalStartIndexFromBinding(update->srcBinding) + update->srcArrayElement; auto dst_start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement; // Update parameters all look good so perform update for (uint32_t di = 0; di < update->descriptorCount; ++di) { descriptors_[dst_start_idx + di]->CopyUpdate(src_set->descriptors_[src_start_idx + di].get()); - ++num_updates; } - if (num_updates != 0) { + if (update->descriptorCount) some_update_ = true; - } + InvalidateBoundCmdBuffers(); } + cvdescriptorset::SamplerDescriptor::SamplerDescriptor() : sampler_(VK_NULL_HANDLE), immutable_(false) { updated = false; descriptor_class = PlainSampler; @@ -589,10 +587,12 @@ cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const VkSampler *immut) : updated = true; } } + bool cvdescriptorset::ValidateSampler(const VkSampler sampler, const std::unordered_map> *sampler_map) { return (sampler_map->count(sampler) != 0); } + bool cvdescriptorset::ValidateImageUpdate(const VkImageView image_view, const VkImageLayout image_layout, const std::unordered_map *image_view_map, const std::unordered_map *image_map, @@ -687,6 +687,7 @@ bool cvdescriptorset::ValidateImageUpdate(const VkImageView image_view, const Vk } return true; } + void cvdescriptorset::SamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { sampler_ = update->pImageInfo[index].sampler; updated = true; @@ -699,6 +700,7 @@ void cvdescriptorset::SamplerDescriptor::CopyUpdate(const Descriptor *src) { } updated = true; } + cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor() : sampler_(VK_NULL_HANDLE), immutable_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) { updated = false; @@ -715,9 +717,10 @@ cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(const VkSampler updated = true; } } + void cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { updated = true; - auto image_info = update->pImageInfo[index]; + const auto &image_info = update->pImageInfo[index]; sampler_ = image_info.sampler; image_view_ = image_info.imageView; image_layout_ = image_info.imageLayout; @@ -745,7 +748,7 @@ cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type) void cvdescriptorset::ImageDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { updated = true; - auto image_info = update->pImageInfo[index]; + const auto &image_info = update->pImageInfo[index]; image_view_ = image_info.imageView; image_layout_ = image_info.imageLayout; } @@ -773,7 +776,7 @@ cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type) } void cvdescriptorset::BufferDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { updated = true; - auto buffer_info = update->pBufferInfo[index]; + const auto &buffer_info = update->pBufferInfo[index]; buffer_ = buffer_info.buffer; offset_ = buffer_info.offset; range_ = buffer_info.range; @@ -793,6 +796,7 @@ cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type) : if (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER == type) storage_ = true; }; + void cvdescriptorset::TexelDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) { updated = true; buffer_view_ = update->pTexelBufferView[index]; @@ -809,17 +813,16 @@ void cvdescriptorset::TexelDescriptor::CopyUpdate(const Descriptor *src) { // If there is no issue with the update, then false is returned. bool cvdescriptorset::ValidateUpdateDescriptorSets( const debug_report_data *report_data, const std::unordered_map &set_map, - const uint32_t write_count, const VkWriteDescriptorSet *p_wds, const uint32_t copy_count, const VkCopyDescriptorSet *p_cds) { + uint32_t write_count, const VkWriteDescriptorSet *p_wds, uint32_t copy_count, const VkCopyDescriptorSet *p_cds) { bool skip_call = false; // Validate Write updates - uint32_t i = 0; - for (i = 0; i < write_count; i++) { + for (uint32_t i = 0; i < write_count; i++) { auto dest_set = p_wds[i].dstSet; auto set_pair = set_map.find(dest_set); if (set_pair == set_map.end()) { skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - reinterpret_cast(dest_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", + reinterpret_cast(dest_set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS", "Cannot call vkUpdateDescriptorSets() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", reinterpret_cast(dest_set)); } else { @@ -834,20 +837,20 @@ bool cvdescriptorset::ValidateUpdateDescriptorSets( } } // Now validate copy updates - for (i = 0; i < copy_count; ++i) { + for (uint32_t i = 0; i < copy_count; ++i) { auto dst_set = p_cds[i].dstSet; auto src_set = p_cds[i].srcSet; auto src_pair = set_map.find(src_set); auto dst_pair = set_map.find(dst_set); if (src_pair == set_map.end()) { skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - reinterpret_cast(src_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", + reinterpret_cast(src_set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS", "Cannot call vkUpdateDescriptorSets() to copy from descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", reinterpret_cast(src_set)); } else if (dst_pair == set_map.end()) { skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - reinterpret_cast(dst_set), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", + reinterpret_cast(dst_set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS", "Cannot call vkUpdateDescriptorSets() to copy to descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", reinterpret_cast(dst_set)); @@ -872,8 +875,8 @@ bool cvdescriptorset::ValidateUpdateDescriptorSets( // This is split from the validate code to allow validation prior to calling down the chain, and then update after // calling down the chain. void cvdescriptorset::PerformUpdateDescriptorSets( - const std::unordered_map &set_map, const uint32_t write_count, - const VkWriteDescriptorSet *p_wds, const uint32_t copy_count, const VkCopyDescriptorSet *p_cds) { + const std::unordered_map &set_map, uint32_t write_count, + const VkWriteDescriptorSet *p_wds, uint32_t copy_count, const VkCopyDescriptorSet *p_cds) { // Write updates first uint32_t i = 0; for (i = 0; i < write_count; ++i) { diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 655d5720..58e3b5cd 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -246,11 +246,11 @@ class BufferDescriptor : public Descriptor { // Helper functions for Updating descriptor sets since it crosses multiple sets // Validate will make sure an update is ok without actually performing it bool ValidateUpdateDescriptorSets(const debug_report_data *, - const std::unordered_map &, const uint32_t, - const VkWriteDescriptorSet *, const uint32_t, const VkCopyDescriptorSet *); + const std::unordered_map &, uint32_t, + const VkWriteDescriptorSet *, uint32_t, const VkCopyDescriptorSet *); // Perform does the update with the assumption that ValidateUpdateDescriptorSets() has passed for the given update -void PerformUpdateDescriptorSets(const std::unordered_map &, const uint32_t, - const VkWriteDescriptorSet *, const uint32_t, const VkCopyDescriptorSet *); +void PerformUpdateDescriptorSets(const std::unordered_map &, uint32_t, + const VkWriteDescriptorSet *, uint32_t, const VkCopyDescriptorSet *); /* * DescriptorSet class * @@ -272,8 +272,8 @@ void PerformUpdateDescriptorSets(const std::unordered_map *, const std::unordered_map *, + DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const std::unordered_map *, + const std::unordered_map *, const std::unordered_map *, const std::unordered_map> *, const std::unordered_map *, const std::unordered_map *, @@ -351,11 +351,9 @@ class DescriptorSet : public BASE_NODE { void InvalidateBoundCmdBuffers(); bool some_update_; // has any part of the set ever been updated? VkDescriptorSet set_; - uint32_t descriptor_count_; // Count of all descriptors in this set const DescriptorSetLayout *p_layout_; std::unordered_set bound_cmd_buffers_; std::vector> descriptors_; - const debug_report_data *report_data_; // Ptrs to object containers to verify bound data const std::unordered_map *buffer_map_; const std::unordered_map *memory_map_; -- cgit v1.2.3 From bae2437ca75278f04ea48f416442b7aaf7d02649 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 20 May 2016 16:34:01 +1200 Subject: layers: Get rid of pre-call updates in AllocateDescriptorSets Moving all the updates later requires that we totalize the required descriptors by type first, rather than testing each binding's requirement as we go. Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 47 +++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 62874f35..2fa18c61 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3410,7 +3410,8 @@ static bool validateIdleDescriptorSet(const layer_data *my_data, VkDescriptorSet // Verify that given pool has descriptors that are being requested for allocation. // NOTE : Calls to this function should be wrapped in mutex static bool validate_descriptor_availability_in_pool(layer_data *dev_data, DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count, - const VkDescriptorSetLayout *pSetLayouts) { + const VkDescriptorSetLayout *pSetLayouts, + uint32_t requiredDescriptorsByType[]) { bool skipCall = false; // Track number of descriptorSets allowable in this pool @@ -3420,10 +3421,9 @@ static bool validate_descriptor_availability_in_pool(layer_data *dev_data, DESCR "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64 ". This pool only has %d descriptorSets remaining.", count, reinterpret_cast(pPoolNode->pool), pPoolNode->availableSets); - } else { - pPoolNode->availableSets -= count; } + // Count total descriptors required per type for (uint32_t i = 0; i < count; ++i) { auto layout_pair = dev_data->descriptorSetLayoutMap.find(pSetLayouts[i]); if (layout_pair == dev_data->descriptorSetLayoutMap.end()) { @@ -3437,21 +3437,24 @@ static bool validate_descriptor_availability_in_pool(layer_data *dev_data, DESCR for (uint32_t j = 0; j < layout_node->GetBindingCount(); ++j) { const auto &binding_layout = layout_node->GetDescriptorSetLayoutBindingPtrFromIndex(j); uint32_t typeIndex = static_cast(binding_layout->descriptorType); - uint32_t poolSizeCount = binding_layout->descriptorCount; - if (poolSizeCount > pPoolNode->availableDescriptorTypeCount[typeIndex]) { - skipCall |= log_msg( - dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, - reinterpret_cast(pSetLayouts[i]), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", - "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64 - ". This pool only has %d descriptors of this type remaining.", - poolSizeCount, string_VkDescriptorType(binding_layout->descriptorType), (uint64_t)pPoolNode->pool, - pPoolNode->availableDescriptorTypeCount[typeIndex]); - } else { // Decrement available descriptors of this type - pPoolNode->availableDescriptorTypeCount[typeIndex] -= poolSizeCount; - } + requiredDescriptorsByType[typeIndex] += binding_layout->descriptorCount; } } } + + // Determine whether descriptor counts are satisfiable + for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { + if (requiredDescriptorsByType[i] > pPoolNode->availableDescriptorTypeCount[i]) { + skipCall |= log_msg( + dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, + reinterpret_cast(pSetLayouts[i]), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", + "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64 + ". This pool only has %d descriptors of this type remaining.", + requiredDescriptorsByType[i], string_VkDescriptorType(VkDescriptorType(i)), (uint64_t)pPoolNode->pool, + pPoolNode->availableDescriptorTypeCount[i]); + } + } + return skipCall; } @@ -5901,10 +5904,12 @@ VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) { bool skipCall = false; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); + uint32_t requiredDescriptorsByType[VK_DESCRIPTOR_TYPE_RANGE_SIZE] {}; std::unique_lock lock(global_lock); // Verify that requested descriptorSets are available in pool DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, pAllocateInfo->descriptorPool); + if (!pPoolNode) { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, (uint64_t)pAllocateInfo->descriptorPool, __LINE__, DRAWSTATE_INVALID_POOL, "DS", @@ -5912,16 +5917,24 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo (uint64_t)pAllocateInfo->descriptorPool); } else { // Make sure pool has all the available descriptors before calling down chain skipCall |= validate_descriptor_availability_in_pool(dev_data, pPoolNode, pAllocateInfo->descriptorSetCount, - pAllocateInfo->pSetLayouts); + pAllocateInfo->pSetLayouts, + requiredDescriptorsByType); } lock.unlock(); if (skipCall) return VK_ERROR_VALIDATION_FAILED_EXT; VkResult result = dev_data->device_dispatch_table->AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets); + if (VK_SUCCESS == result) { lock.lock(); - DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, pAllocateInfo->descriptorPool); if (pPoolNode) { + + /* Account for sets and descriptors allocated */ + pPoolNode->availableSets -= pAllocateInfo->descriptorSetCount; + for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { + pPoolNode->availableDescriptorTypeCount[i] -= requiredDescriptorsByType[i]; + } + if (pAllocateInfo->descriptorSetCount == 0) { log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, pAllocateInfo->descriptorSetCount, __LINE__, DRAWSTATE_NONE, "DS", -- cgit v1.2.3 From f51d50b4f42cb059b997c0ce19a8fbd7f7f891ae Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 20 May 2016 17:04:07 +1200 Subject: layers: Further rework to AllocateDescriptorSets - operator new does not return null, it throws. - do lookups once, at the start Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 74 +++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 40 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 2fa18c61..c1cb672e 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -1989,6 +1989,14 @@ static FRAMEBUFFER_NODE *getFramebuffer(layer_data *my_data, VkFramebuffer frame return &it->second; } +static cvdescriptorset::DescriptorSetLayout const *getDescriptorSetLayout(layer_data const *my_data, VkDescriptorSetLayout dsLayout) { + auto it = my_data->descriptorSetLayoutMap.find(dsLayout); + if (it == my_data->descriptorSetLayoutMap.end()) { + return nullptr; + } + return it->second; +} + // Return true if for a given PSO, the given state enum is dynamic, else return false static bool isDynamic(const PIPELINE_NODE *pPipeline, const VkDynamicState state) { if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) { @@ -3410,7 +3418,7 @@ static bool validateIdleDescriptorSet(const layer_data *my_data, VkDescriptorSet // Verify that given pool has descriptors that are being requested for allocation. // NOTE : Calls to this function should be wrapped in mutex static bool validate_descriptor_availability_in_pool(layer_data *dev_data, DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count, - const VkDescriptorSetLayout *pSetLayouts, + std::vector const & layout_nodes, uint32_t requiredDescriptorsByType[]) { bool skipCall = false; @@ -3424,16 +3432,8 @@ static bool validate_descriptor_availability_in_pool(layer_data *dev_data, DESCR } // Count total descriptors required per type - for (uint32_t i = 0; i < count; ++i) { - auto layout_pair = dev_data->descriptorSetLayoutMap.find(pSetLayouts[i]); - if (layout_pair == dev_data->descriptorSetLayoutMap.end()) { - skipCall |= - log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, - (uint64_t)pSetLayouts[i], __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", - "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", - (uint64_t)pSetLayouts[i]); - } else { - auto &layout_node = layout_pair->second; + for (auto layout_node : layout_nodes) { + if (layout_node) { for (uint32_t j = 0; j < layout_node->GetBindingCount(); ++j) { const auto &binding_layout = layout_node->GetDescriptorSetLayoutBindingPtrFromIndex(j); uint32_t typeIndex = static_cast(binding_layout->descriptorType); @@ -3446,8 +3446,8 @@ static bool validate_descriptor_availability_in_pool(layer_data *dev_data, DESCR for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { if (requiredDescriptorsByType[i] > pPoolNode->availableDescriptorTypeCount[i]) { skipCall |= log_msg( - dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, - reinterpret_cast(pSetLayouts[i]), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", + dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, + reinterpret_cast(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64 ". This pool only has %d descriptors of this type remaining.", requiredDescriptorsByType[i], string_VkDescriptorType(VkDescriptorType(i)), (uint64_t)pPoolNode->pool, @@ -5904,9 +5904,22 @@ VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) { bool skipCall = false; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); + uint32_t requiredDescriptorsByType[VK_DESCRIPTOR_TYPE_RANGE_SIZE] {}; + std::vector layout_nodes(pAllocateInfo->descriptorSetCount, nullptr); std::unique_lock lock(global_lock); + + for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) { + layout_nodes[i] = getDescriptorSetLayout(dev_data, pAllocateInfo->pSetLayouts[i]); + if (!layout_nodes[i]) { + skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, + (uint64_t)pAllocateInfo->pSetLayouts[i], __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", + "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", + (uint64_t)pAllocateInfo->pSetLayouts[i]); + } + } + // Verify that requested descriptorSets are available in pool DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, pAllocateInfo->descriptorPool); @@ -5917,8 +5930,7 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo (uint64_t)pAllocateInfo->descriptorPool); } else { // Make sure pool has all the available descriptors before calling down chain skipCall |= validate_descriptor_availability_in_pool(dev_data, pPoolNode, pAllocateInfo->descriptorSetCount, - pAllocateInfo->pSetLayouts, - requiredDescriptorsByType); + layout_nodes, requiredDescriptorsByType); } lock.unlock(); if (skipCall) @@ -5928,7 +5940,6 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo if (VK_SUCCESS == result) { lock.lock(); if (pPoolNode) { - /* Account for sets and descriptors allocated */ pPoolNode->availableSets -= pAllocateInfo->descriptorSetCount; for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { @@ -5940,35 +5951,18 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo pAllocateInfo->descriptorSetCount, __LINE__, DRAWSTATE_NONE, "DS", "AllocateDescriptorSets called with 0 count"); } + for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) { log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS", "Created Descriptor Set 0x%" PRIxLEAST64, (uint64_t)pDescriptorSets[i]); - auto layout_pair = dev_data->descriptorSetLayoutMap.find(pAllocateInfo->pSetLayouts[i]); - if (layout_pair == dev_data->descriptorSetLayoutMap.end()) { - if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, (uint64_t)pAllocateInfo->pSetLayouts[i], - __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", "Unable to find set layout node for layout 0x%" PRIxLEAST64 - " specified in vkAllocateDescriptorSets() call", - (uint64_t)pAllocateInfo->pSetLayouts[i])) { - lock.unlock(); - return VK_ERROR_VALIDATION_FAILED_EXT; - } - } // Create new DescriptorSet instance and add to the pool's unordered_set of DescriptorSets - cvdescriptorset::DescriptorSet *pNewNode = new cvdescriptorset::DescriptorSet( - pDescriptorSets[i], layout_pair->second, &dev_data->bufferMap, &dev_data->memObjMap, &dev_data->bufferViewMap, - &dev_data->samplerMap, &dev_data->imageViewMap, &dev_data->imageMap, - &dev_data->device_extensions.imageToSwapchainMap, &dev_data->device_extensions.swapchainMap); - if (NULL == pNewNode) { - if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__, - DRAWSTATE_OUT_OF_MEMORY, "DS", "Out of memory while attempting to allocate " - "cvdescriptorset::DescriptorSet in vkAllocateDescriptorSets()")) { - lock.unlock(); - return VK_ERROR_VALIDATION_FAILED_EXT; - } - } else { + if (layout_nodes[i]) { + auto pNewNode = new cvdescriptorset::DescriptorSet( + pDescriptorSets[i], layout_nodes[i], &dev_data->bufferMap, &dev_data->memObjMap, &dev_data->bufferViewMap, + &dev_data->samplerMap, &dev_data->imageViewMap, &dev_data->imageMap, + &dev_data->device_extensions.imageToSwapchainMap, &dev_data->device_extensions.swapchainMap); + // Insert set into this pool pPoolNode->sets.insert(pNewNode); pNewNode->in_use.store(0); -- cgit v1.2.3 From 73d109fd9c22c19901a9838c33d8e7fdbe736d50 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 20 May 2016 17:12:39 +1200 Subject: layers: Remove more AllocateDescriptorSets noise Can argue about whether this stuff at INFO level is worthwhile... Replace the comments with a clearer set of comments. Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index c1cb672e..1bf27e2d 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5920,7 +5920,6 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo } } - // Verify that requested descriptorSets are available in pool DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, pAllocateInfo->descriptorPool); if (!pPoolNode) { @@ -5933,8 +5932,10 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo layout_nodes, requiredDescriptorsByType); } lock.unlock(); + if (skipCall) return VK_ERROR_VALIDATION_FAILED_EXT; + VkResult result = dev_data->device_dispatch_table->AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets); if (VK_SUCCESS == result) { @@ -5946,24 +5947,16 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo pPoolNode->availableDescriptorTypeCount[i] -= requiredDescriptorsByType[i]; } - if (pAllocateInfo->descriptorSetCount == 0) { - log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - pAllocateInfo->descriptorSetCount, __LINE__, DRAWSTATE_NONE, "DS", - "AllocateDescriptorSets called with 0 count"); - } - + /* Create tracking object for each descriptor set; insert into + * global map and the pool's set. + */ for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) { - log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, - (uint64_t)pDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS", "Created Descriptor Set 0x%" PRIxLEAST64, - (uint64_t)pDescriptorSets[i]); - // Create new DescriptorSet instance and add to the pool's unordered_set of DescriptorSets if (layout_nodes[i]) { auto pNewNode = new cvdescriptorset::DescriptorSet( pDescriptorSets[i], layout_nodes[i], &dev_data->bufferMap, &dev_data->memObjMap, &dev_data->bufferViewMap, &dev_data->samplerMap, &dev_data->imageViewMap, &dev_data->imageMap, &dev_data->device_extensions.imageToSwapchainMap, &dev_data->device_extensions.swapchainMap); - // Insert set into this pool pPoolNode->sets.insert(pNewNode); pNewNode->in_use.store(0); dev_data->setMap[pDescriptorSets[i]] = pNewNode; -- cgit v1.2.3 From 34c2c1b598abfb812cc2ca56f99bbaf93c5e6757 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 20 May 2016 17:14:32 +1200 Subject: layers: Use getDescriptorSetLayout helper in more places Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 1bf27e2d..b182ea02 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5846,13 +5846,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(VkDevice device, const VkPip plNode.setLayouts.resize(pCreateInfo->setLayoutCount); for (i = 0; i < pCreateInfo->setLayoutCount; ++i) { plNode.descriptorSetLayouts[i] = pCreateInfo->pSetLayouts[i]; - auto set_layout_it = dev_data->descriptorSetLayoutMap.find(pCreateInfo->pSetLayouts[i]); - if (set_layout_it != dev_data->descriptorSetLayoutMap.end()) { - plNode.setLayouts[i] = set_layout_it->second; - } - else { - plNode.setLayouts[i] = nullptr; - } + plNode.setLayouts[i] = getDescriptorSetLayout(dev_data, pCreateInfo->pSetLayouts[i]); } plNode.pushConstantRanges.resize(pCreateInfo->pushConstantRangeCount); for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { -- cgit v1.2.3 From 2edec5a133b3b0e75110c4ce357a33e5806c88ea Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 20 May 2016 17:38:44 +1200 Subject: layers: Use pipeline layout -> ds layout direct map Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index b182ea02..bc6d9f71 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -2181,7 +2181,7 @@ static bool verify_set_layout_compatibility(layer_data *my_data, const cvdescrip errorMsg = errorStr.str(); return false; } - auto layout_node = my_data->descriptorSetLayoutMap[pipeline_layout_it->second.descriptorSetLayouts[layoutIndex]]; + auto layout_node = pipeline_layout_it->second.setLayouts[layoutIndex]; return pSet->IsCompatible(layout_node, &errorMsg); } -- cgit v1.2.3 From 1679dfd7d4f2329474a375f2bb1e5f5e5ec6f9c9 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 20 May 2016 18:27:28 +1200 Subject: layers: Add getPipelineLayout helper, use it Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 40 ++++++++++++++++++++-------------------- layers/core_validation.h | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index bc6d9f71..eaed5b64 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -1925,7 +1925,7 @@ static bool validate_push_constant_usage(debug_report_data *report_data, // For given pipelineLayout verify that the set_layout_node at slot.first // has the requested binding at slot.second and return ptr to that binding -static VkDescriptorSetLayoutBinding const * get_descriptor_binding(PIPELINE_LAYOUT_NODE *pipelineLayout, descriptor_slot_t slot) { +static VkDescriptorSetLayoutBinding const * get_descriptor_binding(PIPELINE_LAYOUT_NODE const *pipelineLayout, descriptor_slot_t slot) { if (!pipelineLayout) return nullptr; @@ -1997,6 +1997,14 @@ static cvdescriptorset::DescriptorSetLayout const *getDescriptorSetLayout(layer_ return it->second; } +static PIPELINE_LAYOUT_NODE const *getPipelineLayout(layer_data const *my_data, VkPipelineLayout pipeLayout) { + auto it = my_data->pipelineLayoutMap.find(pipeLayout); + if (it == my_data->pipelineLayoutMap.end()) { + return nullptr; + } + return &it->second; +} + // Return true if for a given PSO, the given state enum is dynamic, else return false static bool isDynamic(const PIPELINE_NODE *pPipeline, const VkDynamicState state) { if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) { @@ -2166,22 +2174,22 @@ static bool verify_renderpass_compatibility(layer_data *my_data, const VkRenderP // pipelineLayout[layoutIndex] static bool verify_set_layout_compatibility(layer_data *my_data, const cvdescriptorset::DescriptorSet *pSet, const VkPipelineLayout layout, const uint32_t layoutIndex, string &errorMsg) { - auto pipeline_layout_it = my_data->pipelineLayoutMap.find(layout); - if (pipeline_layout_it == my_data->pipelineLayoutMap.end()) { + auto pipeline_layout = getPipelineLayout(my_data, layout); + if (!pipeline_layout) { stringstream errorStr; errorStr << "invalid VkPipelineLayout (" << layout << ")"; errorMsg = errorStr.str(); return false; } - if (layoutIndex >= pipeline_layout_it->second.descriptorSetLayouts.size()) { + if (layoutIndex >= pipeline_layout->descriptorSetLayouts.size()) { stringstream errorStr; - errorStr << "VkPipelineLayout (" << layout << ") only contains " << pipeline_layout_it->second.descriptorSetLayouts.size() - << " setLayouts corresponding to sets 0-" << pipeline_layout_it->second.descriptorSetLayouts.size() - 1 + errorStr << "VkPipelineLayout (" << layout << ") only contains " << pipeline_layout->descriptorSetLayouts.size() + << " setLayouts corresponding to sets 0-" << pipeline_layout->descriptorSetLayouts.size() - 1 << ", but you're attempting to bind set to index " << layoutIndex; errorMsg = errorStr.str(); return false; } - auto layout_node = pipeline_layout_it->second.setLayouts[layoutIndex]; + auto layout_node = pipeline_layout->setLayouts[layoutIndex]; return pSet->IsCompatible(layout_node, &errorMsg); } @@ -5631,11 +5639,7 @@ CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t pPipeNode[i] = new PIPELINE_NODE; pPipeNode[i]->initGraphicsPipeline(&pCreateInfos[i]); pPipeNode[i]->renderPass = getRenderPass(dev_data, pCreateInfos[i].renderPass); - - auto pipeline_layout_it = dev_data->pipelineLayoutMap.find(pCreateInfos[i].layout); - if (pipeline_layout_it != dev_data->pipelineLayoutMap.end()) { - pPipeNode[i]->pipelineLayout = &pipeline_layout_it->second; - } + pPipeNode[i]->pipelineLayout = getPipelineLayout(dev_data, pCreateInfos[i].layout); skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode, i); } @@ -5679,11 +5683,7 @@ CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t // Create and initialize internal tracking data structure pPipeNode[i] = new PIPELINE_NODE; pPipeNode[i]->initComputePipeline(&pCreateInfos[i]); - - auto pipeline_layout_it = dev_data->pipelineLayoutMap.find(pCreateInfos[i].layout); - if (pipeline_layout_it != dev_data->pipelineLayoutMap.end()) { - pPipeNode[i]->pipelineLayout = &pipeline_layout_it->second; - } + pPipeNode[i]->pipelineLayout = getPipelineLayout(dev_data, pCreateInfos[i].layout); // memcpy(&pPipeNode[i]->computePipelineCI, (const void *)&pCreateInfos[i], sizeof(VkComputePipelineCreateInfo)); // TODO: Add Compute Pipeline Verification @@ -7994,8 +7994,8 @@ VKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPip } // Check if push constant update is within any of the ranges with the same stage flags specified in pipeline layout. - auto pipeline_layout_it = dev_data->pipelineLayoutMap.find(layout); - if (pipeline_layout_it == dev_data->pipelineLayoutMap.end()) { + auto pipeline_layout = getPipelineLayout(dev_data, layout); + if (!pipeline_layout) { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "vkCmdPushConstants() Pipeline Layout 0x%" PRIx64 " not found.", (uint64_t)layout); @@ -8003,7 +8003,7 @@ VKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPip // Coalesce adjacent/overlapping pipeline ranges before checking to see if incoming range is // contained in the pipeline ranges. // Build a {start, end} span list for ranges with matching stage flags. - const auto &ranges = pipeline_layout_it->second.pushConstantRanges; + const auto &ranges = pipeline_layout->pushConstantRanges; struct span { uint32_t start; uint32_t end; diff --git a/layers/core_validation.h b/layers/core_validation.h index 1d312e12..b4927b7b 100644 --- a/layers/core_validation.h +++ b/layers/core_validation.h @@ -148,7 +148,7 @@ class PIPELINE_NODE { std::vector attachments; bool blendConstantsEnabled; // Blend constants enabled for any attachments RENDER_PASS_NODE *renderPass; - PIPELINE_LAYOUT_NODE *pipelineLayout; + PIPELINE_LAYOUT_NODE const *pipelineLayout; // Default constructor PIPELINE_NODE() -- cgit v1.2.3 From d2970375fcce017d2284c00e4e88151e73196800 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Mon, 23 May 2016 11:29:51 +1200 Subject: layers: Move and rename validate_descriptor_availability_in_pool Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 90 +++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 44 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index eaed5b64..b7368f56 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3423,48 +3423,6 @@ static bool validateIdleDescriptorSet(const layer_data *my_data, VkDescriptorSet } return skip_call; } -// Verify that given pool has descriptors that are being requested for allocation. -// NOTE : Calls to this function should be wrapped in mutex -static bool validate_descriptor_availability_in_pool(layer_data *dev_data, DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count, - std::vector const & layout_nodes, - uint32_t requiredDescriptorsByType[]) { - bool skipCall = false; - - // Track number of descriptorSets allowable in this pool - if (pPoolNode->availableSets < count) { - skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, - reinterpret_cast(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", - "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64 - ". This pool only has %d descriptorSets remaining.", - count, reinterpret_cast(pPoolNode->pool), pPoolNode->availableSets); - } - - // Count total descriptors required per type - for (auto layout_node : layout_nodes) { - if (layout_node) { - for (uint32_t j = 0; j < layout_node->GetBindingCount(); ++j) { - const auto &binding_layout = layout_node->GetDescriptorSetLayoutBindingPtrFromIndex(j); - uint32_t typeIndex = static_cast(binding_layout->descriptorType); - requiredDescriptorsByType[typeIndex] += binding_layout->descriptorCount; - } - } - } - - // Determine whether descriptor counts are satisfiable - for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { - if (requiredDescriptorsByType[i] > pPoolNode->availableDescriptorTypeCount[i]) { - skipCall |= log_msg( - dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, - reinterpret_cast(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", - "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64 - ". This pool only has %d descriptors of this type remaining.", - requiredDescriptorsByType[i], string_VkDescriptorType(VkDescriptorType(i)), (uint64_t)pPoolNode->pool, - pPoolNode->availableDescriptorTypeCount[i]); - } - } - - return skipCall; -} // Free the descriptor set, remove it from setMap and invalidate any cmd buffers that it was bound to static void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) { @@ -5894,6 +5852,50 @@ ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescript return result; } +// Ensure the pool contains enough descriptors and descriptor sets to satisfy +// an allocation request. Fills requiredDescriptorsByType with the total number +// of descriptors of each type required, for later update. +static bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count, + std::vector const & layout_nodes, + uint32_t requiredDescriptorsByType[]) { + bool skipCall = false; + + // Track number of descriptorSets allowable in this pool + if (pPoolNode->availableSets < count) { + skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, + reinterpret_cast(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", + "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64 + ". This pool only has %d descriptorSets remaining.", + count, reinterpret_cast(pPoolNode->pool), pPoolNode->availableSets); + } + + // Count total descriptors required per type + for (auto layout_node : layout_nodes) { + if (layout_node) { + for (uint32_t j = 0; j < layout_node->GetBindingCount(); ++j) { + const auto &binding_layout = layout_node->GetDescriptorSetLayoutBindingPtrFromIndex(j); + uint32_t typeIndex = static_cast(binding_layout->descriptorType); + requiredDescriptorsByType[typeIndex] += binding_layout->descriptorCount; + } + } + } + + // Determine whether descriptor counts are satisfiable + for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { + if (requiredDescriptorsByType[i] > pPoolNode->availableDescriptorTypeCount[i]) { + skipCall |= log_msg( + dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, + reinterpret_cast(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", + "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64 + ". This pool only has %d descriptors of this type remaining.", + requiredDescriptorsByType[i], string_VkDescriptorType(VkDescriptorType(i)), (uint64_t)pPoolNode->pool, + pPoolNode->availableDescriptorTypeCount[i]); + } + } + + return skipCall; +} + VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) { bool skipCall = false; @@ -5922,8 +5924,8 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo "Unable to find pool node for pool 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", (uint64_t)pAllocateInfo->descriptorPool); } else { // Make sure pool has all the available descriptors before calling down chain - skipCall |= validate_descriptor_availability_in_pool(dev_data, pPoolNode, pAllocateInfo->descriptorSetCount, - layout_nodes, requiredDescriptorsByType); + skipCall |= PreCallValidateAllocateDescriptorSets(dev_data, pPoolNode, pAllocateInfo->descriptorSetCount, + layout_nodes, requiredDescriptorsByType); } lock.unlock(); -- cgit v1.2.3 From 77bfc0df13075008e4a6657a8e61a7727778ee4a Mon Sep 17 00:00:00 2001 From: Michael Lentine Date: Fri, 20 May 2016 10:14:00 -0500 Subject: layers: Fix event tracking to differentiate reading and writing --- layers/core_validation.cpp | 43 ++++++++++++++++++++++++++++++++---------- layers/core_validation.h | 1 + layers/core_validation_types.h | 5 +++-- 3 files changed, 37 insertions(+), 12 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index b7368f56..c7d9bc4d 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -65,7 +65,11 @@ #include #define LOGCONSOLE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "DS", __VA_ARGS__)) #else -#define LOGCONSOLE(...) printf(__VA_ARGS__) +#define LOGCONSOLE(...) \ + { \ + printf(__VA_ARGS__); \ + printf("\n"); \ + } #endif using namespace std; @@ -4102,6 +4106,10 @@ static bool validateAndIncrementResources(layer_data *my_data, GLOBAL_CB_NODE *p eventNode->second.in_use.fetch_add(1); } } + for (auto event : pCB->writeEventsBeforeWait) { + auto eventNode = my_data->eventMap.find(event); + eventNode->second.write_in_use++; + } return skip_call; } @@ -4162,6 +4170,12 @@ static void decrementResources(layer_data *my_data, VkCommandBuffer cmdBuffer) { eventNode->second.in_use.fetch_sub(1); } } + for (auto event : pCB->writeEventsBeforeWait) { + auto eventNode = my_data->eventMap.find(event); + if (eventNode != my_data->eventMap.end()) { + eventNode->second.write_in_use--; + } + } for (auto queryStatePair : pCB->queryToStateMap) { my_data->queryToStateMap[queryStatePair.first] = queryStatePair.second; } @@ -7405,6 +7419,9 @@ CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags s skipCall |= addCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()"); skipCall |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent"); pCB->events.push_back(event); + if (!pCB->waitedEvents.count(event)) { + pCB->writeEventsBeforeWait.push_back(event); + } std::function eventUpdate = std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, stageMask); pCB->eventUpdates.push_back(eventUpdate); @@ -7424,6 +7441,9 @@ CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags skipCall |= addCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()"); skipCall |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent"); pCB->events.push_back(event); + if (!pCB->waitedEvents.count(event)) { + pCB->writeEventsBeforeWait.push_back(event); + } std::function eventUpdate = std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, VkPipelineStageFlags(0)); pCB->eventUpdates.push_back(eventUpdate); @@ -7789,13 +7809,16 @@ bool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCo } } } - if (sourceStageMask != stageMask) { - skip_call |= - log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, - DRAWSTATE_INVALID_EVENT, "DS", - "Submitting cmdbuffer with call to VkCmdWaitEvents using srcStageMask 0x%x which must be the bitwise OR of the " - "stageMask parameters used in calls to vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if used with vkSetEvent.", - sourceStageMask); + // TODO: Need to validate that host_bit is only set if set event is called + // but set event can be called at any time. + if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) { + skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, + DRAWSTATE_INVALID_EVENT, "DS", "Submitting cmdbuffer with call to VkCmdWaitEvents " + "using srcStageMask 0x%x which must be the bitwise " + "OR of the stageMask parameters used in calls to " + "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if " + "used with vkSetEvent but instead is 0x%x.", + sourceStageMask, stageMask); } return skip_call; } @@ -7812,7 +7835,7 @@ CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent if (pCB) { auto firstEventIndex = pCB->events.size(); for (uint32_t i = 0; i < eventCount; ++i) { - pCB->waitedEvents.push_back(pEvents[i]); + pCB->waitedEvents.insert(pEvents[i]); pCB->events.push_back(pEvents[i]); } std::function eventUpdate = @@ -9479,7 +9502,7 @@ VKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) { if (event_node != dev_data->eventMap.end()) { event_node->second.needsSignaled = false; event_node->second.stageMask = VK_PIPELINE_STAGE_HOST_BIT; - if (event_node->second.in_use.load()) { + if (event_node->second.write_in_use) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, reinterpret_cast(event), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", "Cannot call vkSetEvent() on event 0x%" PRIxLEAST64 " that is already in use by a command buffer.", diff --git a/layers/core_validation.h b/layers/core_validation.h index b4927b7b..e44bbf89 100644 --- a/layers/core_validation.h +++ b/layers/core_validation.h @@ -234,6 +234,7 @@ class SEMAPHORE_NODE : public BASE_NODE { class EVENT_NODE : public BASE_NODE { public: using BASE_NODE::in_use; + int write_in_use; bool needsSignaled; VkPipelineStageFlags stageMask; }; diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 5d9f0715..683eefc5 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -415,10 +415,11 @@ struct GLOBAL_CB_NODE : public BASE_NODE { std::unordered_set destroyedSets; std::unordered_set updatedSets; std::unordered_set destroyedFramebuffers; - std::vector waitedEvents; + std::unordered_set waitedEvents; + std::vector writeEventsBeforeWait; std::vector semaphores; std::vector events; - std::unordered_map> waitedEventsBeforeQueryReset; + std::unordered_map> waitedEventsBeforeQueryReset; std::unordered_map queryToStateMap; // 0 is unavailable, 1 is available std::unordered_set activeQueries; std::unordered_set startedQueries; -- cgit v1.2.3 From d76bc8d4251b296a865d83d894e06afe4f3ef44f Mon Sep 17 00:00:00 2001 From: Michael Lentine Date: Fri, 20 May 2016 17:45:02 -0500 Subject: layers: Fix query tracking across multiple command buffers on the same queue --- layers/core_validation.cpp | 75 +++++++++++++++++++++++++++++++++++------- layers/core_validation.h | 1 + layers/core_validation_types.h | 1 + 3 files changed, 65 insertions(+), 12 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index c7d9bc4d..e8c4cc38 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3675,6 +3675,7 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { pCB->updateBuffers.clear(); clear_cmd_buf_and_mem_references(dev_data, pCB); pCB->eventUpdates.clear(); + pCB->queryUpdates.clear(); // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list for (auto framebuffer : pCB->framebuffers) { @@ -4275,6 +4276,9 @@ static void updateTrackedCommandBuffers(layer_data *dev_data, VkQueue queue, VkQ for (auto eventStagePair : other_queue_data->second.eventToStageMap) { queue_data->second.eventToStageMap[eventStagePair.first] = eventStagePair.second; } + for (auto queryStatePair : other_queue_data->second.queryToStateMap) { + queue_data->second.queryToStateMap[queryStatePair.first] = queryStatePair.second; + } } // This is the core function for tracking command buffers. There are two primary ways command @@ -4555,6 +4559,9 @@ QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, V for (auto &function : pCBNode->eventUpdates) { skipCall |= function(queue); } + for (auto &function : pCBNode->queryUpdates) { + skipCall |= function(queue); + } } } } @@ -7881,6 +7888,19 @@ CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageM pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); } +bool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) { + layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map); + GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); + if (pCB) { + pCB->queryToStateMap[object] = value; + } + auto queue_data = dev_data->queueMap.find(queue); + if (queue_data != dev_data->queueMap.end()) { + queue_data->second.queryToStateMap[object] = value; + } + return false; +} + VKAPI_ATTR void VKAPI_CALL CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags) { bool skipCall = false; @@ -7915,7 +7935,8 @@ VKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPoo } else { pCB->activeQueries.erase(query); } - pCB->queryToStateMap[query] = 1; + std::function queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, 1); + pCB->queryUpdates.push_back(queryUpdate); if (pCB->state == CB_RECORDING) { skipCall |= addCmd(dev_data, pCB, CMD_ENDQUERY, "VkCmdEndQuery()"); } else { @@ -7937,7 +7958,8 @@ CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t for (uint32_t i = 0; i < queryCount; i++) { QueryObject query = {queryPool, firstQuery + i}; pCB->waitedEventsBeforeQueryReset[query] = pCB->waitedEvents; - pCB->queryToStateMap[query] = 0; + std::function queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, 0); + pCB->queryUpdates.push_back(queryUpdate); } if (pCB->state == CB_RECORDING) { skipCall |= addCmd(dev_data, pCB, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()"); @@ -7951,6 +7973,40 @@ CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t dev_data->device_dispatch_table->CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount); } +bool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t queryCount, uint32_t firstQuery) { + bool skip_call = false; + layer_data *dev_data = get_my_data_ptr(get_dispatch_key(pCB->commandBuffer), layer_data_map); + auto queue_data = dev_data->queueMap.find(queue); + if (queue_data == dev_data->queueMap.end()) + return false; + for (uint32_t i = 0; i < queryCount; i++) { + QueryObject query = {queryPool, firstQuery + i}; + auto query_data = queue_data->second.queryToStateMap.find(query); + bool fail = false; + if (query_data != queue_data->second.queryToStateMap.end()) { + if (!query_data->second) { + fail = true; + } + } else { + auto global_query_data = dev_data->queryToStateMap.find(query); + if (global_query_data != dev_data->queryToStateMap.end()) { + if (!global_query_data->second) { + fail = true; + } + } else { + fail = true; + } + } + if (fail) { + skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, + DRAWSTATE_INVALID_QUERY, "DS", + "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d", + reinterpret_cast(queryPool), firstQuery + i); + } + } + return skip_call; +} + VKAPI_ATTR void VKAPI_CALL CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) { @@ -7976,15 +8032,9 @@ CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, ui "vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT"); #endif if (pCB) { - for (uint32_t i = 0; i < queryCount; i++) { - QueryObject query = {queryPool, firstQuery + i}; - if (!pCB->queryToStateMap[query]) { - skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, - __LINE__, DRAWSTATE_INVALID_QUERY, "DS", - "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d", - (uint64_t)(queryPool), firstQuery + i); - } - } + std::function queryUpdate = + std::bind(validateQuery, std::placeholders::_1, pCB, queryPool, queryCount, firstQuery); + pCB->queryUpdates.push_back(queryUpdate); if (pCB->state == CB_RECORDING) { skipCall |= addCmd(dev_data, pCB, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()"); } else { @@ -8103,7 +8153,8 @@ CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelin GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); if (pCB) { QueryObject query = {queryPool, slot}; - pCB->queryToStateMap[query] = 1; + std::function queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, 1); + pCB->queryUpdates.push_back(queryUpdate); if (pCB->state == CB_RECORDING) { skipCall |= addCmd(dev_data, pCB, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()"); } else { diff --git a/layers/core_validation.h b/layers/core_validation.h index e44bbf89..d6857344 100644 --- a/layers/core_validation.h +++ b/layers/core_validation.h @@ -250,6 +250,7 @@ class QUEUE_NODE { #endif std::vector untrackedCmdBuffers; std::unordered_map eventToStageMap; + std::unordered_map queryToStateMap; // 0 is unavailable, 1 is available }; class QUERY_POOL_NODE : public BASE_NODE { diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 683eefc5..c0394180 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -439,6 +439,7 @@ struct GLOBAL_CB_NODE : public BASE_NODE { std::vector> validate_functions; std::unordered_set memObjs; std::vector> eventUpdates; + std::vector> queryUpdates; ~GLOBAL_CB_NODE(); }; -- cgit v1.2.3 From 2160a5be0d79709a39000edaade13b8849340539 Mon Sep 17 00:00:00 2001 From: Michael Lentine Date: Mon, 23 May 2016 13:18:13 -0500 Subject: Mark fence in use after the check. --- layers/core_validation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index e8c4cc38..c623d70e 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -9583,7 +9583,6 @@ QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *p std::unique_lock lock(global_lock); // First verify that fence is not in use if (fence != VK_NULL_HANDLE) { - trackCommandBuffers(dev_data, queue, 0, nullptr, fence); auto fence_data = dev_data->fenceMap.find(fence); if ((bindInfoCount != 0) && fence_data->second.in_use.load()) { skip_call |= @@ -9598,6 +9597,7 @@ QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *p "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", reinterpret_cast(fence)); } + trackCommandBuffers(dev_data, queue, 0, nullptr, fence); } for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) { const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx]; -- cgit v1.2.3 From e3a00781d1d512dbc36c71086a8e61eed386c587 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Mon, 23 May 2016 13:45:36 -0600 Subject: layers: Display accessMask in HEX --- layers/core_validation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index c623d70e..4659a248 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -7535,7 +7535,7 @@ static bool ValidateMaskBits(const layer_data *my_data, VkCommandBuffer cmdBuffe // TODO: Verify against Valid Use skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, - DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask %d %s are specified when layout is %s.", + DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", type, accessMask, string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout)); } } else { @@ -7605,7 +7605,7 @@ static bool ValidateMaskBitsFromLayouts(const layer_data *my_data, VkCommandBuff // TODO: Verify against Valid Use section spec skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, - DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask %d %s are specified when layout is %s.", + DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.", type, accessMask, string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout)); } break; -- cgit v1.2.3 From 67af5a545ff2e1f01686c540c0d9fd0829074c9d Mon Sep 17 00:00:00 2001 From: Michael Lentine Date: Tue, 24 May 2016 09:49:25 -0500 Subject: Clear priorFences on reset. --- layers/core_validation.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index e8c4cc38..baa8e233 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -4218,6 +4218,12 @@ static bool decrementResources(layer_data *my_data, uint32_t fenceCount, const V queue_pair->second.lastFences.erase(last_fence_data); } } + for (auto& fence_data : my_data->fenceMap) { + auto prior_fence_data = + std::find(fence_data.second.priorFences.begin(), fence_data.second.priorFences.end(), fence_pair.first); + if (prior_fence_data != fence_data.second.priorFences.end()) + fence_data.second.priorFences.erase(prior_fence_data); + } } return skip_call; } @@ -5371,6 +5377,7 @@ VKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, if (fence_item != dev_data->fenceMap.end()) { fence_item->second.needsSignaled = true; fence_item->second.queues.clear(); + fence_item->second.priorFences.clear(); if (fence_item->second.in_use.load()) { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, -- cgit v1.2.3 From 45b973ef19d6fac273da7a17586441baae1f7ff7 Mon Sep 17 00:00:00 2001 From: Karl Schultz Date: Tue, 24 May 2016 13:49:59 -0600 Subject: build: Fix Windows compilation warnings Use false/true instead of 0/1 in recently-added std::bind calls. --- layers/core_validation.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 6f2ea1ad..e0d04c29 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -7942,7 +7942,7 @@ VKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPoo } else { pCB->activeQueries.erase(query); } - std::function queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, 1); + std::function queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); pCB->queryUpdates.push_back(queryUpdate); if (pCB->state == CB_RECORDING) { skipCall |= addCmd(dev_data, pCB, CMD_ENDQUERY, "VkCmdEndQuery()"); @@ -7965,7 +7965,7 @@ CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t for (uint32_t i = 0; i < queryCount; i++) { QueryObject query = {queryPool, firstQuery + i}; pCB->waitedEventsBeforeQueryReset[query] = pCB->waitedEvents; - std::function queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, 0); + std::function queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, false); pCB->queryUpdates.push_back(queryUpdate); } if (pCB->state == CB_RECORDING) { @@ -8160,7 +8160,7 @@ CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelin GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); if (pCB) { QueryObject query = {queryPool, slot}; - std::function queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, 1); + std::function queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true); pCB->queryUpdates.push_back(queryUpdate); if (pCB->state == CB_RECORDING) { skipCall |= addCmd(dev_data, pCB, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()"); -- cgit v1.2.3 From 72db2cf8ed223058623943abb345225cd80f3e89 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Mon, 23 May 2016 16:02:29 -0600 Subject: layers: Handle static arrays in codegen Update safe_struct codegen to handle the case of a static array in a struct. This removes exceptions for VkDebugMarkerMarkerInfoEXT and VkPipelineColorBlendStateCreateInfo so they can be treated as all other structs. --- layers/core_validation.cpp | 2 +- vk_helper.py | 45 ++++++++++++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 18 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index e0d04c29..73a318e1 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -2696,7 +2696,7 @@ static bool validatePipelineDrawtimeState(layer_data const *my_data, const GLOBA VkSampleCountFlagBits subpass_num_samples = VkSampleCountFlagBits(0); uint32_t i; - const VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState; + const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState; if ((color_blend_state != NULL) && (pCB->activeSubpass == pPipeline->graphicsPipelineCI.subpass) && (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount)) { skip_call |= diff --git a/vk_helper.py b/vk_helper.py index ab99f638..a405d571 100755 --- a/vk_helper.py +++ b/vk_helper.py @@ -1563,7 +1563,7 @@ class StructWrapperGen: # If struct has sType or ptr members, generate safe type def _hasSafeStruct(self, s): - exceptions = ['VkPhysicalDeviceFeatures', 'VkPipelineColorBlendStateCreateInfo', 'VkDebugMarkerMarkerInfoEXT'] + exceptions = ['VkPhysicalDeviceFeatures'] if s in exceptions: return False if 'sType' == self.struct_dict[s][0]['name']: @@ -1713,23 +1713,34 @@ class StructWrapperGen: destruct_txt += ' if (%s)\n' % (m_name) destruct_txt += ' delete[] %s;\n' % (m_name) elif self.struct_dict[s][m]['array']: - # Init array ptr to NULL - init_list += '\n\t%s(NULL),' % (m_name) - init_func_txt += ' %s = NULL;\n' % (m_name) - array_element = 'pInStruct->%s[i]' % (m_name) - if is_type(self.struct_dict[s][m]['type'], 'struct') and self._hasSafeStruct(self.struct_dict[s][m]['type']): - array_element = '%s(&pInStruct->%s[i])' % (self._getSafeStructName(self.struct_dict[s][m]['type']), m_name) - construct_txt += ' if (%s && pInStruct->%s) {\n' % (self.struct_dict[s][m]['array_size'], m_name) - construct_txt += ' %s = new %s[%s];\n' % (m_name, m_type, self.struct_dict[s][m]['array_size']) - destruct_txt += ' if (%s)\n' % (m_name) - destruct_txt += ' delete[] %s;\n' % (m_name) - construct_txt += ' for (uint32_t i=0; i<%s; ++i) {\n' % (self.struct_dict[s][m]['array_size']) - if 'safe_' in m_type: - construct_txt += ' %s[i].initialize(&pInStruct->%s[i]);\n' % (m_name, m_name) + if not self.struct_dict[s][m]['dyn_array']: + # Handle static array case + array_init_str = '' + for i in range(int(self.struct_dict[s][m]['array_size'])): + array_init_str += 'pInStruct->%s[%d], ' % (m_name, i) + array_init_str = array_init_str.strip().rstrip(',') + init_list += '\n\t%s{%s},' % (m_name, array_init_str) + init_func_txt += ' for (uint32_t i=0; i<%s; ++i) {\n' % (self.struct_dict[s][m]['array_size']) + init_func_txt += ' %s[i] = pInStruct->%s[i];\n' % (m_name, m_name) + init_func_txt += ' }\n' else: - construct_txt += ' %s[i] = %s;\n' % (m_name, array_element) - construct_txt += ' }\n' - construct_txt += ' }\n' + # Init array ptr to NULL + init_list += '\n\t%s(NULL),' % (m_name) + init_func_txt += ' %s = NULL;\n' % (m_name) + array_element = 'pInStruct->%s[i]' % (m_name) + if is_type(self.struct_dict[s][m]['type'], 'struct') and self._hasSafeStruct(self.struct_dict[s][m]['type']): + array_element = '%s(&pInStruct->%s[i])' % (self._getSafeStructName(self.struct_dict[s][m]['type']), m_name) + construct_txt += ' if (%s && pInStruct->%s) {\n' % (self.struct_dict[s][m]['array_size'], m_name) + construct_txt += ' %s = new %s[%s];\n' % (m_name, m_type, self.struct_dict[s][m]['array_size']) + destruct_txt += ' if (%s)\n' % (m_name) + destruct_txt += ' delete[] %s;\n' % (m_name) + construct_txt += ' for (uint32_t i=0; i<%s; ++i) {\n' % (self.struct_dict[s][m]['array_size']) + if 'safe_' in m_type: + construct_txt += ' %s[i].initialize(&pInStruct->%s[i]);\n' % (m_name, m_name) + else: + construct_txt += ' %s[i] = %s;\n' % (m_name, array_element) + construct_txt += ' }\n' + construct_txt += ' }\n' elif self.struct_dict[s][m]['ptr']: construct_txt += ' if (pInStruct->%s)\n' % (m_name) construct_txt += ' %s = new %s(pInStruct->%s);\n' % (m_name, m_type, m_name) -- cgit v1.2.3 From f866a08cf788a3519a65f44fd1d05f9849971d09 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 31 May 2016 16:09:42 +1200 Subject: layers: Wire up validation of compute pipelines Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 73a318e1..806d594a 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5673,6 +5673,9 @@ CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t // memcpy(&pPipeNode[i]->computePipelineCI, (const void *)&pCreateInfos[i], sizeof(VkComputePipelineCreateInfo)); // TODO: Add Compute Pipeline Verification + skipCall |= !validate_compute_pipeline(dev_data->report_data, pPipeNode[i], + &dev_data->phys_dev_properties.features, + dev_data->shaderModuleMap); // skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode[i]); } -- cgit v1.2.3 From a9ec01cf6e4c109fb7e8b20ba4ac8c3de64693fe Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 31 May 2016 16:45:13 +1200 Subject: layers: Make precise DS validation work for both bind points Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 806d594a..46bfaddf 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -2784,9 +2784,10 @@ static bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE * } // Now complete other state checks - // TODO : When Compute shaders are properly parsed, fix this section to validate them as well if (state.pipelineLayout) { string errorString; + auto pipelineLayout = (bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) ? pPipe->graphicsPipelineCI.layout : pPipe->computePipelineCI.layout; + // Need a vector (vs. std::set) of active Sets for dynamicOffset validation in case same set bound w/ different offsets vector, std::vector const *>> activeSetBindingsPairs; for (auto & setBindingPair : pPipe->active_slots) { @@ -2798,7 +2799,7 @@ static bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE * "VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.", (uint64_t)pPipe->pipeline, setIndex); } else if (!verify_set_layout_compatibility(my_data, state.boundDescriptorSets[setIndex], - pPipe->graphicsPipelineCI.layout, setIndex, errorString)) { + pipelineLayout, setIndex, errorString)) { // Set is bound but not compatible w/ overlapping pipelineLayout from PSO VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet(); result |= @@ -2806,7 +2807,7 @@ static bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE * (uint64_t)setHandle, __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS", "VkDescriptorSet (0x%" PRIxLEAST64 ") bound as set #%u is not compatible with overlapping VkPipelineLayout 0x%" PRIxLEAST64 " due to: %s", - (uint64_t)setHandle, setIndex, (uint64_t)pPipe->graphicsPipelineCI.layout, errorString.c_str()); + (uint64_t)setHandle, setIndex, (uint64_t)pipelineLayout, errorString.c_str()); } else { // Valid set is bound and layout compatible, validate that it's updated // Pull the set node cvdescriptorset::DescriptorSet *pSet = state.boundDescriptorSets[setIndex]; -- cgit v1.2.3 From 3abf44e4873001e85d24c14c0d0ba4aa98714016 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 31 May 2016 16:33:48 +1200 Subject: layers: Do accurate draw-time validation of descriptors used by compute Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 208 ++++++++++++++++++++++----------------------- 1 file changed, 100 insertions(+), 108 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 46bfaddf..2c932512 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -2681,25 +2681,75 @@ static VkSampleCountFlagBits getNumSamples(PIPELINE_NODE const *pipe) { } // Validate draw-time state related to the PSO -static bool validatePipelineDrawtimeState(layer_data const *my_data, const GLOBAL_CB_NODE *pCB, - const VkPipelineBindPoint pipelineBindPoint, PIPELINE_NODE const *pPipeline) { +static bool validatePipelineDrawtimeState(layer_data const *my_data, + LAST_BOUND_STATE const &state, + const GLOBAL_CB_NODE *pCB, + PIPELINE_NODE const *pPipeline) { bool skip_call = false; - if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) { - // Verify that any MSAA request in PSO matches sample# in bound FB - // Skip the check if rasterization is disabled. - if (!pPipeline->graphicsPipelineCI.pRasterizationState || - (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) { - VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline); - if (pCB->activeRenderPass) { - const VkRenderPassCreateInfo *render_pass_info = pCB->activeRenderPass->pCreateInfo; - const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass]; - VkSampleCountFlagBits subpass_num_samples = VkSampleCountFlagBits(0); - uint32_t i; - - const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState; - if ((color_blend_state != NULL) && (pCB->activeSubpass == pPipeline->graphicsPipelineCI.subpass) && - (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount)) { - skip_call |= + + // Verify Vtx binding + if (pPipeline->vertexBindingDescriptions.size() > 0) { + for (size_t i = 0; i < pPipeline->vertexBindingDescriptions.size(); i++) { + if ((pCB->currentDrawData.buffers.size() < (i + 1)) || (pCB->currentDrawData.buffers[i] == VK_NULL_HANDLE)) { + skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, + __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", + "The Pipeline State Object (0x%" PRIxLEAST64 + ") expects that this Command Buffer's vertex binding Index " PRINTF_SIZE_T_SPECIFIER + " should be set via vkCmdBindVertexBuffers.", + (uint64_t)state.pipeline, i); + } + } + } else { + if (!pCB->currentDrawData.buffers.empty()) { + skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, + 0, __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", + "Vertex buffers are bound to command buffer (0x%" PRIxLEAST64 + ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").", + (uint64_t)pCB->commandBuffer, (uint64_t)state.pipeline); + } + } + // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count. + // Skip check if rasterization is disabled or there is no viewport. + if ((!pPipeline->graphicsPipelineCI.pRasterizationState || + (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) && + pPipeline->graphicsPipelineCI.pViewportState) { + bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT); + bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR); + if (dynViewport) { + if (pCB->viewports.size() != pPipeline->graphicsPipelineCI.pViewportState->viewportCount) { + skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, + __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", + "Dynamic viewportCount from vkCmdSetViewport() is " PRINTF_SIZE_T_SPECIFIER + ", but PSO viewportCount is %u. These counts must match.", + pCB->viewports.size(), pPipeline->graphicsPipelineCI.pViewportState->viewportCount); + } + } + if (dynScissor) { + if (pCB->scissors.size() != pPipeline->graphicsPipelineCI.pViewportState->scissorCount) { + skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, + __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", + "Dynamic scissorCount from vkCmdSetScissor() is " PRINTF_SIZE_T_SPECIFIER + ", but PSO scissorCount is %u. These counts must match.", + pCB->scissors.size(), pPipeline->graphicsPipelineCI.pViewportState->scissorCount); + } + } + } + + // Verify that any MSAA request in PSO matches sample# in bound FB + // Skip the check if rasterization is disabled. + if (!pPipeline->graphicsPipelineCI.pRasterizationState || + (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) { + VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline); + if (pCB->activeRenderPass) { + const VkRenderPassCreateInfo *render_pass_info = pCB->activeRenderPass->pCreateInfo; + const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass]; + VkSampleCountFlagBits subpass_num_samples = VkSampleCountFlagBits(0); + uint32_t i; + + const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState; + if ((color_blend_state != NULL) && (pCB->activeSubpass == pPipeline->graphicsPipelineCI.subpass) && + (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount)) { + skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, reinterpret_cast(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", "Render pass subpass %u mismatch with blending state defined and blend state attachment " @@ -2707,53 +2757,51 @@ static bool validatePipelineDrawtimeState(layer_data const *my_data, const GLOBA "must be the same at draw-time.", pCB->activeSubpass, color_blend_state->attachmentCount, subpass_desc->colorAttachmentCount, reinterpret_cast(pPipeline->pipeline)); - } + } - for (i = 0; i < subpass_desc->colorAttachmentCount; i++) { - VkSampleCountFlagBits samples; + for (i = 0; i < subpass_desc->colorAttachmentCount; i++) { + VkSampleCountFlagBits samples; - if (subpass_desc->pColorAttachments[i].attachment == VK_ATTACHMENT_UNUSED) - continue; + if (subpass_desc->pColorAttachments[i].attachment == VK_ATTACHMENT_UNUSED) + continue; - samples = render_pass_info->pAttachments[subpass_desc->pColorAttachments[i].attachment].samples; - if (subpass_num_samples == static_cast(0)) { - subpass_num_samples = samples; - } else if (subpass_num_samples != samples) { - subpass_num_samples = static_cast(-1); - break; - } + samples = render_pass_info->pAttachments[subpass_desc->pColorAttachments[i].attachment].samples; + if (subpass_num_samples == static_cast(0)) { + subpass_num_samples = samples; + } else if (subpass_num_samples != samples) { + subpass_num_samples = static_cast(-1); + break; } - if ((subpass_desc->pDepthStencilAttachment != NULL) && - (subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)) { - const VkSampleCountFlagBits samples = + } + if ((subpass_desc->pDepthStencilAttachment != NULL) && + (subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)) { + const VkSampleCountFlagBits samples = render_pass_info->pAttachments[subpass_desc->pDepthStencilAttachment->attachment].samples; - if (subpass_num_samples == static_cast(0)) - subpass_num_samples = samples; - else if (subpass_num_samples != samples) - subpass_num_samples = static_cast(-1); - } + if (subpass_num_samples == static_cast(0)) + subpass_num_samples = samples; + else if (subpass_num_samples != samples) + subpass_num_samples = static_cast(-1); + } - if (((subpass_desc->colorAttachmentCount > 0) || (subpass_desc->pDepthStencilAttachment != NULL)) && - (pso_num_samples != subpass_num_samples)) { - skip_call |= + if (((subpass_desc->colorAttachmentCount > 0) || (subpass_desc->pDepthStencilAttachment != NULL)) && + (pso_num_samples != subpass_num_samples)) { + skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, reinterpret_cast(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", "Num samples mismatch! At draw-time in Pipeline (0x%" PRIxLEAST64 ") with %u samples while current RenderPass (0x%" PRIxLEAST64 ") w/ %u samples!", reinterpret_cast(pPipeline->pipeline), pso_num_samples, reinterpret_cast(pCB->activeRenderPass->renderPass), subpass_num_samples); - } - } else { - skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, - reinterpret_cast(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", - "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!", - reinterpret_cast(pPipeline->pipeline)); } + } else { + skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, + reinterpret_cast(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS", + "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!", + reinterpret_cast(pPipeline->pipeline)); } - // TODO : Add more checks here - } else { - // TODO : Validate non-gfx pipeline updates } + // TODO : Add more checks here + return skip_call; } @@ -2775,13 +2823,6 @@ static bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE * // First check flag states if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint) result = validate_draw_state_flags(my_data, pCB, pPipe, indexedDraw); - else { - // First block of code below to validate active sets should eventually - // work for the compute case but currently doesn't so return early for now - // TODO : When active sets in compute shaders are correctly parsed, - // stop returning early here and handle them in top block below - return result; - } // Now complete other state checks if (state.pipelineLayout) { @@ -2833,59 +2874,10 @@ static bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE * // For given active slots, verify any dynamic descriptors and record updated images & buffers result |= validate_and_update_drawtime_descriptor_state(my_data, pCB, activeSetBindingsPairs); } - // TODO : If/when compute pipelines/shaders are handled above, code below is only for gfx bind poing - //if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint) { - // Verify Vtx binding - if (pPipe->vertexBindingDescriptions.size() > 0) { - for (size_t i = 0; i < pPipe->vertexBindingDescriptions.size(); i++) { - if ((pCB->currentDrawData.buffers.size() < (i + 1)) || (pCB->currentDrawData.buffers[i] == VK_NULL_HANDLE)) { - result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, - __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", - "The Pipeline State Object (0x%" PRIxLEAST64 - ") expects that this Command Buffer's vertex binding Index " PRINTF_SIZE_T_SPECIFIER - " should be set via vkCmdBindVertexBuffers.", - (uint64_t)state.pipeline, i); - } - } - } else { - if (!pCB->currentDrawData.buffers.empty()) { - result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, - 0, __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS", - "Vertex buffers are bound to command buffer (0x%" PRIxLEAST64 - ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").", - (uint64_t)pCB->commandBuffer, (uint64_t)state.pipeline); - } - } - // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count. - // Skip check if rasterization is disabled or there is no viewport. - if ((!pPipe->graphicsPipelineCI.pRasterizationState || - (pPipe->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) && - pPipe->graphicsPipelineCI.pViewportState) { - bool dynViewport = isDynamic(pPipe, VK_DYNAMIC_STATE_VIEWPORT); - bool dynScissor = isDynamic(pPipe, VK_DYNAMIC_STATE_SCISSOR); - if (dynViewport) { - if (pCB->viewports.size() != pPipe->graphicsPipelineCI.pViewportState->viewportCount) { - result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, - __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", - "Dynamic viewportCount from vkCmdSetViewport() is " PRINTF_SIZE_T_SPECIFIER - ", but PSO viewportCount is %u. These counts must match.", - pCB->viewports.size(), pPipe->graphicsPipelineCI.pViewportState->viewportCount); - } - } - if (dynScissor) { - if (pCB->scissors.size() != pPipe->graphicsPipelineCI.pViewportState->scissorCount) { - result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, - __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS", - "Dynamic scissorCount from vkCmdSetScissor() is " PRINTF_SIZE_T_SPECIFIER - ", but PSO scissorCount is %u. These counts must match.", - pCB->scissors.size(), pPipe->graphicsPipelineCI.pViewportState->scissorCount); - } - } - } - //} // end of "if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint) {" block // Check general pipeline state that needs to be validated at drawtime - result |= validatePipelineDrawtimeState(my_data, pCB, bindPoint, pPipe); + if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint) + result |= validatePipelineDrawtimeState(my_data, state, pCB, pPipe); return result; } -- cgit v1.2.3 From 413eae5c4dc394f99f4b89e91346ce77fe74bc11 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Tue, 31 May 2016 16:34:40 +1200 Subject: layers: Remove old hacks for imprecise descriptor tracking for compute We do it properly now. Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 15 --------------- layers/descriptor_sets.cpp | 10 +--------- layers/descriptor_sets.h | 3 --- 3 files changed, 1 insertion(+), 27 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 2c932512..933c2f2d 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -2659,17 +2659,6 @@ static bool validate_and_update_drawtime_descriptor_state( } return result; } -// TODO : This is a temp function that naively updates bound storage images and buffers based on which descriptor sets are bound. -// When validate_and_update_draw_state() handles compute shaders so that active_slots is correct for compute pipelines, this -// function can be killed and validate_and_update_draw_state() used instead -static void update_shader_storage_images_and_buffers(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { - // For the bound descriptor sets, pull off any storage images and buffers - // This may be more than are actually updated depending on which are active, but for now this is a stop-gap for compute - // pipelines - for (auto set : pCB->lastBound[VK_PIPELINE_BIND_POINT_COMPUTE].uniqueBoundSets) { - set->GetAllStorageUpdates(&pCB->updateBuffers, &pCB->updateImages); - } -} // For given pipeline, return number of MSAA samples, or one if MSAA disabled static VkSampleCountFlagBits getNumSamples(PIPELINE_NODE const *pipe) { @@ -6884,8 +6873,6 @@ VKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); if (pCB) { skipCall |= validate_and_update_draw_state(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_COMPUTE); - // TODO : Call below is temporary until call above can be re-enabled - update_shader_storage_images_and_buffers(dev_data, pCB); skipCall |= markStoreImagesAndBuffersAsWritten(dev_data, pCB); skipCall |= addCmd(dev_data, pCB, CMD_DISPATCH, "vkCmdDispatch()"); skipCall |= insideRenderPass(dev_data, pCB, "vkCmdDispatch"); @@ -6907,8 +6894,6 @@ CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); if (pCB) { skipCall |= validate_and_update_draw_state(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_COMPUTE); - // TODO : Call below is temporary until call above can be re-enabled - update_shader_storage_images_and_buffers(dev_data, pCB); skipCall |= markStoreImagesAndBuffersAsWritten(dev_data, pCB); skipCall |= addCmd(dev_data, pCB, CMD_DISPATCHINDIRECT, "vkCmdDispatchIndirect()"); skipCall |= insideRenderPass(dev_data, pCB, "vkCmdDispatchIndirect"); diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 5fc1de3f..b0e16e82 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -451,14 +451,6 @@ uint32_t cvdescriptorset::DescriptorSet::GetStorageUpdates(const std::unordered_ } return num_updates; } -// This is a special case for compute shaders that should eventually be removed once we have proper valid binding info for compute -// case -uint32_t cvdescriptorset::DescriptorSet::GetAllStorageUpdates(std::unordered_set *buffer_set, - std::unordered_set *image_set) const { - std::unordered_set binding_set; - p_layout_->FillBindingSet(&binding_set); - return GetStorageUpdates(binding_set, buffer_set, image_set); -} // Set is being deleted or updates so invalidate all bound cmd buffers void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers() { for (auto cb_node : bound_cmd_buffers_) { @@ -1131,4 +1123,4 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri } // All checks passed so update contents are good return true; -} \ No newline at end of file +} diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 6f2073b7..6a0d7e78 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -310,9 +310,6 @@ class DescriptorSet : public BASE_NODE { // of objects inserted uint32_t GetStorageUpdates(const std::unordered_set &, std::unordered_set *, std::unordered_set *) const; - // For all descriptors in a set, add any buffers and images that may be updated to their respective unordered_sets & return - // number of objects inserted - uint32_t GetAllStorageUpdates(std::unordered_set *, std::unordered_set *) const; // Descriptor Update functions. These functions validate state and perform update separately // Validate contents of a WriteUpdate -- cgit v1.2.3 From 9557cc3e3feb80245e75b1b7966574e52d8dd115 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 26 May 2016 13:12:38 -0600 Subject: layers: Make layer_data const in getPoolNode() Remove "[]" map operator and use iterator from find instead to return pool ptr so that layer_data param can be const. This will allow this function to be used from "PreValidate" calls where no state is changed. --- layers/core_validation.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 933c2f2d..ff93d9a6 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3122,11 +3122,12 @@ static void deletePipelines(layer_data *my_data) { // Block of code at start here specifically for managing/tracking DSs // Return Pool node ptr for specified pool or else NULL -static DESCRIPTOR_POOL_NODE *getPoolNode(layer_data *my_data, const VkDescriptorPool pool) { - if (my_data->descriptorPoolMap.find(pool) == my_data->descriptorPoolMap.end()) { +static DESCRIPTOR_POOL_NODE *getPoolNode(const layer_data *dev_data, const VkDescriptorPool pool) { + auto pool_it = dev_data->descriptorPoolMap.find(pool); + if (pool_it == dev_data->descriptorPoolMap.end()) { return NULL; } - return my_data->descriptorPoolMap[pool]; + return pool_it->second; } // Return false if update struct is of valid type, otherwise flag error and return code from callback -- cgit v1.2.3 From e4ca22360d4a70d21c171d9f69dd502298211724 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 26 May 2016 13:30:45 -0600 Subject: layers: Refactor FreeDescriptorSets() Create PreValidate/PostRecord functions for FreeDescriptorSets(). Currently the validation and state updates are handled in-line in these functions, but this change makes it easy to migrate the code to descriptor pool class without affecting top-level intercept function. --- layers/core_validation.cpp | 76 +++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 32 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index ff93d9a6..fcc25f39 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5869,18 +5869,18 @@ ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescript // Ensure the pool contains enough descriptors and descriptor sets to satisfy // an allocation request. Fills requiredDescriptorsByType with the total number // of descriptors of each type required, for later update. -static bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count, - std::vector const & layout_nodes, +static bool PreCallValidateAllocateDescriptorSets(const layer_data *dev_data, const DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count, + std::vector const &layout_nodes, uint32_t requiredDescriptorsByType[]) { bool skipCall = false; // Track number of descriptorSets allowable in this pool if (pPoolNode->availableSets < count) { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, - reinterpret_cast(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", + reinterpret_cast(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64 ". This pool only has %d descriptorSets remaining.", - count, reinterpret_cast(pPoolNode->pool), pPoolNode->availableSets); + count, reinterpret_cast(pPoolNode->pool), pPoolNode->availableSets); } // Count total descriptors required per type @@ -5977,48 +5977,60 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo } return result; } +// Verify state before freeing DescriptorSets +static bool PreCallValidateFreeDescriptorSets(const layer_data *dev_data, VkDescriptorPool pool, uint32_t count, + const VkDescriptorSet *descriptor_sets) { + bool skip_call = false; + // First make sure sets being destroyed are not currently in-use + for (uint32_t i = 0; i < count; ++i) + skip_call |= validateIdleDescriptorSet(dev_data, descriptor_sets[i], "vkFreeDescriptorSets"); + + DESCRIPTOR_POOL_NODE *pool_node = getPoolNode(dev_data, pool); + if (pool_node && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pool_node->createInfo.flags)) { + // Can't Free from a NON_FREE pool + skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, + reinterpret_cast(pool), __LINE__, DRAWSTATE_CANT_FREE_FROM_NON_FREE_POOL, "DS", + "It is invalid to call vkFreeDescriptorSets() with a pool created without setting " + "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT."); + } + return skip_call; +} +// Sets have been removed from the pool so update underlying state +static void PostCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count, + const VkDescriptorSet *descriptor_sets) { + DESCRIPTOR_POOL_NODE *pool_state = getPoolNode(dev_data, pool); + // Update available descriptor sets in pool + pool_state->availableSets += count; + + // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap + for (uint32_t i = 0; i < count; ++i) { + auto set_state = dev_data->setMap[descriptor_sets[i]]; + uint32_t type_index = 0, descriptor_count = 0; + for (uint32_t j = 0; j < set_state->GetBindingCount(); ++j) { + type_index = static_cast(set_state->GetTypeFromIndex(j)); + descriptor_count = set_state->GetDescriptorCountFromIndex(j); + pool_state->availableDescriptorTypeCount[type_index] += descriptor_count; + } + freeDescriptorSet(dev_data, set_state); + pool_state->sets.erase(set_state); + } +} VKAPI_ATTR VkResult VKAPI_CALL FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet *pDescriptorSets) { - bool skipCall = false; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); // Make sure that no sets being destroyed are in-flight std::unique_lock lock(global_lock); - for (uint32_t i = 0; i < count; ++i) - skipCall |= validateIdleDescriptorSet(dev_data, pDescriptorSets[i], "vkFreeDescriptorSets"); - DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, descriptorPool); - if (pPoolNode && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pPoolNode->createInfo.flags)) { - // Can't Free from a NON_FREE pool - skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, - (uint64_t)device, __LINE__, DRAWSTATE_CANT_FREE_FROM_NON_FREE_POOL, "DS", - "It is invalid to call vkFreeDescriptorSets() with a pool created without setting " - "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT."); - } + bool skipCall = PreCallValidateFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); lock.unlock(); if (skipCall) return VK_ERROR_VALIDATION_FAILED_EXT; VkResult result = dev_data->device_dispatch_table->FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets); if (VK_SUCCESS == result) { lock.lock(); - - // Update available descriptor sets in pool - pPoolNode->availableSets += count; - - // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap - for (uint32_t i = 0; i < count; ++i) { - cvdescriptorset::DescriptorSet *pSet = dev_data->setMap[pDescriptorSets[i]]; // getSetNode() without locking - uint32_t typeIndex = 0, poolSizeCount = 0; - for (uint32_t j = 0; j < pSet->GetBindingCount(); ++j) { - typeIndex = static_cast(pSet->GetTypeFromIndex(j)); - poolSizeCount = pSet->GetDescriptorCountFromIndex(j); - pPoolNode->availableDescriptorTypeCount[typeIndex] += poolSizeCount; - } - freeDescriptorSet(dev_data, pSet); - pPoolNode->sets.erase(pSet); - } + PostCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets); lock.unlock(); } - // TODO : Any other clean-up or book-keeping to do here? return result; } // TODO : This is a Proof-of-concept for core validation architecture -- cgit v1.2.3 From e5d662877d01e94f8518d5a837cbd145591200ca Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 26 May 2016 13:39:11 -0600 Subject: layers: Update freeDescriptorSet() comment --- layers/core_validation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index fcc25f39..381ca02e 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3411,7 +3411,7 @@ static bool validateIdleDescriptorSet(const layer_data *my_data, VkDescriptorSet return skip_call; } -// Free the descriptor set, remove it from setMap and invalidate any cmd buffers that it was bound to +// Remove set from setMap and delete the set static void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) { dev_data->setMap.erase(descriptor_set->GetSet()); delete descriptor_set; -- cgit v1.2.3 From 8491e5be6c0ecb358754945729a90280a7b58ba5 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Tue, 31 May 2016 13:06:24 -0600 Subject: layers: GH601 Add check for clearValueCount We were missing check "clearValueCount must be greater than or equal to the number of attachments in renderPass that specify a loadOp of VK_ATTACHMENT_LOAD_OP_CLEAR" (Vulkan spec 1.0.15 section 7.4) This change adds that check. --- layers/core_validation.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 381ca02e..f2eff32c 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -8897,11 +8897,12 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p auto framebuffer = pRenderPassBegin ? getFramebuffer(dev_data, pRenderPassBegin->framebuffer) : nullptr; if (pCB) { if (renderPass) { -#if MTMERGE + uint32_t clear_op_count = 0; pCB->activeFramebuffer = pRenderPassBegin->framebuffer; for (size_t i = 0; i < renderPass->attachments.size(); ++i) { MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i]; if (renderPass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) { + ++clear_op_count; std::function function = [=]() { set_memory_valid(dev_data, fb_info.mem, true, fb_info.image); return false; @@ -8926,7 +8927,15 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p pCB->validate_functions.push_back(function); } } -#endif + if (clear_op_count > pRenderPassBegin->clearValueCount) { + skipCall |= log_msg( + dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, + reinterpret_cast(renderPass), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", + "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but the actual number " + "of attachments in renderPass 0x%" PRIx64 " that use VK_ATTACHMENT_LOAD_OP_CLEAR is %u. The clearValueCount " + "must therefore be greater than or equal to %u.", + pRenderPassBegin->clearValueCount, reinterpret_cast(renderPass), clear_op_count, clear_op_count); + } skipCall |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin); skipCall |= VerifyFramebufferAndRenderPassLayouts(dev_data, pCB, pRenderPassBegin); skipCall |= insideRenderPass(dev_data, pCB, "vkCmdBeginRenderPass"); -- cgit v1.2.3 From 66f66bb3b0a7df1441f3bc07b35e3db4dbb46af8 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Tue, 31 May 2016 13:20:20 -0600 Subject: layers: Kill redundant check At this point in the code we already know that renderPass is valid so no need to re-check it. --- layers/core_validation.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index f2eff32c..aa342c49 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -8939,9 +8939,7 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p skipCall |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin); skipCall |= VerifyFramebufferAndRenderPassLayouts(dev_data, pCB, pRenderPassBegin); skipCall |= insideRenderPass(dev_data, pCB, "vkCmdBeginRenderPass"); - if (renderPass) { - skipCall |= ValidateDependencies(dev_data, framebuffer, renderPass); - } + skipCall |= ValidateDependencies(dev_data, framebuffer, renderPass); pCB->activeRenderPass = renderPass; skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdBeginRenderPass"); skipCall |= addCmd(dev_data, pCB, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()"); -- cgit v1.2.3 From 87324738d20915ffa03c27928dd7b4fa3d31ab87 Mon Sep 17 00:00:00 2001 From: Mark Mueller Date: Mon, 30 May 2016 16:46:38 -0600 Subject: layers: LX506 fix vkFlushMappedMemoryRanges validation error Fix LX506: vkFlushMappedMemoryRanges validation error with VkMappedMemoryRange::size = VK_WHOLE_SIZE. Resolution: Change test of size variable to correctly test the size passed by application against the relevant mapped memory Change-Id: I6d855482985512b5096696f5c37346dde8a391ac --- layers/core_validation.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index aa342c49..f5e05092 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -9428,16 +9428,18 @@ static bool validateMemoryIsMapped(layer_data *my_data, const char *funcName, ui "(" PRINTF_SIZE_T_SPECIFIER ").", funcName, static_cast(pMemRanges[i].offset), static_cast(mem_element->second.memRange.offset)); } - if ((mem_element->second.memRange.size != VK_WHOLE_SIZE) && - ((mem_element->second.memRange.offset + mem_element->second.memRange.size) < - (pMemRanges[i].offset + pMemRanges[i].size))) { + + const uint64_t my_dataTerminus = + (mem_element->second.memRange.size == VK_WHOLE_SIZE) ? mem_element->second.allocInfo.allocationSize : + (mem_element->second.memRange.offset + mem_element->second.memRange.size); + if (pMemRanges[i].size != VK_WHOLE_SIZE && (my_dataTerminus < (pMemRanges[i].offset + pMemRanges[i].size))) { skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pMemRanges[i].memory, __LINE__, MEMTRACK_INVALID_MAP, "MEM", "%s: Flush/Invalidate upper-bound (" PRINTF_SIZE_T_SPECIFIER ") exceeds the Memory Object's upper-bound " "(" PRINTF_SIZE_T_SPECIFIER ").", funcName, static_cast(pMemRanges[i].offset + pMemRanges[i].size), - static_cast(mem_element->second.memRange.offset + mem_element->second.memRange.size)); + static_cast(my_dataTerminus)); } } } -- cgit v1.2.3 From c90ca65de9cd73f7a1ddaff9c05b21cfe47cca6e Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 20 May 2016 07:11:22 +0800 Subject: layers: simplify v0 function implementations Since each of the layer library contains only a layer, we can simplify v0 functions by making them wrappers to the contained layer's corresponding commands. While we have to make changes to each layer individually, all the changes should be the same in spirit. The exception is vk-layer-generate.py where the missing vkEnumerateDeviceExtensionProperties is also added. --- layers/core_validation.cpp | 48 ++++++++------ layers/device_limits.cpp | 48 ++++++++------ layers/image.cpp | 48 ++++++++------ layers/parameter_validation.cpp | 48 ++++++++------ layers/swapchain.cpp | 48 ++++++++------ layers/threading.cpp | 54 ++++++++++------ vk-layer-generate.py | 134 +++++++++++++++++++++++++--------------- 7 files changed, 261 insertions(+), 167 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index f5e05092..cf44ce68 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -9915,6 +9915,24 @@ DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugR pMsg); } +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &global_layer, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &global_layer, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { + if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) + return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties); + + return VK_ERROR_LAYER_NOT_PRESENT; +} + VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { @@ -9993,14 +10011,12 @@ intercept_core_instance_command(const char *name) { { "vkCreateInstance", reinterpret_cast(CreateInstance) }, { "vkCreateDevice", reinterpret_cast(CreateDevice) }, { "vkDestroyInstance", reinterpret_cast(DestroyInstance) }, + { "vkEnumerateInstanceLayerProperties", reinterpret_cast(EnumerateInstanceLayerProperties) }, + { "vkEnumerateDeviceLayerProperties", reinterpret_cast(EnumerateDeviceLayerProperties) }, + { "vkEnumerateInstanceExtensionProperties", reinterpret_cast(EnumerateInstanceExtensionProperties) }, { "vkEnumerateDeviceExtensionProperties", reinterpret_cast(EnumerateDeviceExtensionProperties) }, }; - // we should never be queried for these commands - assert(strcmp(name, "vkEnumerateInstanceLayerProperties") && - strcmp(name, "vkEnumerateInstanceExtensionProperties") && - strcmp(name, "vkEnumerateDeviceLayerProperties")); - for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) { if (!strcmp(core_instance_commands[i].name, name)) return core_instance_commands[i].proc; @@ -10191,27 +10207,30 @@ vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebu core_validation::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); } -// loader-layer interface v0 +// loader-layer interface v0, just wrappers since there is only a layer VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - return util_GetExtensionProperties(1, core_validation::instance_extensions, pCount, pProperties); + return core_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { - return util_GetLayerProperties(1, &core_validation::global_layer, pCount, pProperties); + return core_validation::EnumerateInstanceLayerProperties(pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { - return util_GetLayerProperties(1, &core_validation::global_layer, pCount, pProperties); + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); + return core_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - // the layer command handles VK_NULL_HANDLE just fine + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); return core_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); } @@ -10220,14 +10239,5 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD } VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { - if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties")) - return reinterpret_cast(vkEnumerateInstanceLayerProperties); - if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties")) - return reinterpret_cast(vkEnumerateDeviceLayerProperties); - if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties")) - return reinterpret_cast(vkEnumerateInstanceExtensionProperties); - if (!strcmp(funcName, "vkGetInstanceProcAddr")) - return reinterpret_cast(vkGetInstanceProcAddr); - return core_validation::GetInstanceProcAddr(instance, funcName); } diff --git a/layers/device_limits.cpp b/layers/device_limits.cpp index a5b1ca79..df52cf31 100644 --- a/layers/device_limits.cpp +++ b/layers/device_limits.cpp @@ -669,6 +669,24 @@ DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugR pMsg); } +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &global_layer, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &global_layer, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { + if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) + return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties); + + return VK_ERROR_LAYER_NOT_PRESENT; +} + VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, @@ -750,14 +768,12 @@ intercept_core_instance_command(const char *name) { { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast(GetPhysicalDeviceQueueFamilyProperties) }, { "vkGetPhysicalDeviceMemoryProperties", reinterpret_cast(GetPhysicalDeviceMemoryProperties) }, { "vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast(GetPhysicalDeviceSparseImageFormatProperties) }, + { "vkEnumerateInstanceLayerProperties", reinterpret_cast(EnumerateInstanceLayerProperties) }, + { "vkEnumerateDeviceLayerProperties", reinterpret_cast(EnumerateDeviceLayerProperties) }, + { "vkEnumerateInstanceExtensionProperties", reinterpret_cast(EnumerateInstanceExtensionProperties) }, { "vkEnumerateDeviceExtensionProperties", reinterpret_cast(EnumerateDeviceExtensionProperties) }, }; - // we should never be queried for these commands - assert(strcmp(name, "vkEnumerateInstanceLayerProperties") && - strcmp(name, "vkEnumerateInstanceExtensionProperties") && - strcmp(name, "vkEnumerateDeviceLayerProperties")); - for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) { if (!strcmp(core_instance_commands[i].name, name)) return core_instance_commands[i].proc; @@ -820,27 +836,30 @@ vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebu device_limits::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); } -// loader-layer interface v0 +// loader-layer interface v0, just wrappers since there is only a layer VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { - return util_GetLayerProperties(1, &device_limits::global_layer, pCount, pProperties); + return device_limits::EnumerateInstanceLayerProperties(pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { - return util_GetLayerProperties(1, &device_limits::global_layer, pCount, pProperties); + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); + return device_limits::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - return util_GetExtensionProperties(1, device_limits::instance_extensions, pCount, pProperties); + return device_limits::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - // the layer command handles VK_NULL_HANDLE just fine + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); return device_limits::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); } @@ -849,14 +868,5 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD } VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { - if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties")) - return reinterpret_cast(vkEnumerateInstanceLayerProperties); - if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties")) - return reinterpret_cast(vkEnumerateDeviceLayerProperties); - if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties")) - return reinterpret_cast(vkEnumerateInstanceExtensionProperties); - if (!strcmp(funcName, "vkGetInstanceProcAddr")) - return reinterpret_cast(vkGetInstanceProcAddr); - return device_limits::GetInstanceProcAddr(instance, funcName); } diff --git a/layers/image.cpp b/layers/image.cpp index 88ae5ba1..81140e9d 100644 --- a/layers/image.cpp +++ b/layers/image.cpp @@ -1286,6 +1286,24 @@ GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDevicePro phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, pProperties); } +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &global_layer, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &global_layer, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { + if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) + return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties); + + return VK_ERROR_LAYER_NOT_PRESENT; +} + VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { @@ -1353,15 +1371,13 @@ intercept_core_instance_command(const char *name) { { "vkCreateInstance", reinterpret_cast(CreateInstance) }, { "vkDestroyInstance", reinterpret_cast(DestroyInstance) }, { "vkCreateDevice", reinterpret_cast(CreateDevice) }, + { "vkEnumerateInstanceLayerProperties", reinterpret_cast(EnumerateInstanceLayerProperties) }, + { "vkEnumerateDeviceLayerProperties", reinterpret_cast(EnumerateDeviceLayerProperties) }, + { "vkEnumerateInstanceExtensionProperties", reinterpret_cast(EnumerateInstanceExtensionProperties) }, { "vkEnumerateDeviceExtensionProperties", reinterpret_cast(EnumerateDeviceExtensionProperties) }, { "vkGetPhysicalDeviceProperties", reinterpret_cast(GetPhysicalDeviceProperties) }, }; - // we should never be queried for these commands - assert(strcmp(name, "vkEnumerateInstanceLayerProperties") && - strcmp(name, "vkEnumerateInstanceExtensionProperties") && - strcmp(name, "vkEnumerateDeviceLayerProperties")); - for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) { if (!strcmp(core_instance_commands[i].name, name)) return core_instance_commands[i].proc; @@ -1425,27 +1441,30 @@ vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebu image::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); } -// loader-layer interface v0 +// loader-layer interface v0, just wrappers since there is only a layer VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - return util_GetExtensionProperties(1, image::instance_extensions, pCount, pProperties); + return image::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { - return util_GetLayerProperties(1, &image::global_layer, pCount, pProperties); + return image::EnumerateInstanceLayerProperties(pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { - return util_GetLayerProperties(1, &image::global_layer, pCount, pProperties); + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); + return image::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - // the layer command handles VK_NULL_HANDLE just fine + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); return image::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); } @@ -1454,14 +1473,5 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD } VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { - if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties")) - return reinterpret_cast(vkEnumerateInstanceLayerProperties); - if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties")) - return reinterpret_cast(vkEnumerateInstanceExtensionProperties); - if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties")) - return reinterpret_cast(vkEnumerateDeviceLayerProperties); - if (!strcmp(funcName, "vkGetInstanceProcAddr")) - return reinterpret_cast(vkGetInstanceProcAddr); - return image::GetInstanceProcAddr(instance, funcName); } diff --git a/layers/parameter_validation.cpp b/layers/parameter_validation.cpp index e584d46c..c70142bb 100644 --- a/layers/parameter_validation.cpp +++ b/layers/parameter_validation.cpp @@ -4453,6 +4453,24 @@ CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, c } } +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &global_layer, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &global_layer, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { + if (pLayerName && !strcmp(pLayerName, global_layer.layerName)) + return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties); + + return VK_ERROR_LAYER_NOT_PRESENT; +} + VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { @@ -4528,14 +4546,12 @@ intercept_core_instance_command(const char *name) { { "vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast(GetPhysicalDeviceSparseImageFormatProperties) }, { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast(GetPhysicalDeviceQueueFamilyProperties) }, { "vkGetPhysicalDeviceMemoryProperties", reinterpret_cast(GetPhysicalDeviceMemoryProperties) }, + { "vkEnumerateInstanceLayerProperties", reinterpret_cast(EnumerateInstanceLayerProperties) }, + { "vkEnumerateDeviceLayerProperties", reinterpret_cast(EnumerateDeviceLayerProperties) }, + { "vkEnumerateInstanceExtensionProperties", reinterpret_cast(EnumerateInstanceExtensionProperties) }, { "vkEnumerateDeviceExtensionProperties", reinterpret_cast(EnumerateDeviceExtensionProperties) }, }; - // we should never be queried for these commands - assert(strcmp(name, "vkEnumerateInstanceLayerProperties") && - strcmp(name, "vkEnumerateInstanceExtensionProperties") && - strcmp(name, "vkEnumerateDeviceLayerProperties")); - for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) { if (!strcmp(core_instance_commands[i].name, name)) return core_instance_commands[i].proc; @@ -4698,25 +4714,26 @@ vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebu VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - return util_GetExtensionProperties(1, parameter_validation::instance_extensions, pCount, pProperties); + return parameter_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { - return util_GetLayerProperties(1, ¶meter_validation::global_layer, pCount, pProperties); + return parameter_validation::EnumerateInstanceLayerProperties(pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { - - /* parameter_validation's physical device layers are the same as global */ - return util_GetLayerProperties(1, ¶meter_validation::global_layer, pCount, pProperties); + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); + return parameter_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - // the layer command handles VK_NULL_HANDLE just fine + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); return parameter_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); } @@ -4725,14 +4742,5 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD } VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { - if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties")) - return reinterpret_cast(vkEnumerateInstanceLayerProperties); - if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties")) - return reinterpret_cast(vkEnumerateDeviceLayerProperties); - if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties")) - return reinterpret_cast(vkEnumerateInstanceExtensionProperties); - if (!strcmp(funcName, "vkGetInstanceProcAddr")) - return reinterpret_cast(vkGetInstanceProcAddr); - return parameter_validation::GetInstanceProcAddr(instance, funcName); } diff --git a/layers/swapchain.cpp b/layers/swapchain.cpp index b603ec77..1642468d 100644 --- a/layers/swapchain.cpp +++ b/layers/swapchain.cpp @@ -2121,6 +2121,24 @@ DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugR pMsg); } +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { + if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName)) + return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties); + + return VK_ERROR_LAYER_NOT_PRESENT; +} + VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { @@ -2204,15 +2222,13 @@ intercept_core_instance_command(const char *name) { { "vkDestroyInstance", reinterpret_cast(DestroyInstance) }, { "vkCreateDevice", reinterpret_cast(CreateDevice) }, { "vkEnumeratePhysicalDevices", reinterpret_cast(EnumeratePhysicalDevices) }, + { "vkEnumerateInstanceLayerProperties", reinterpret_cast(EnumerateInstanceLayerProperties) }, + { "vkEnumerateDeviceLayerProperties", reinterpret_cast(EnumerateDeviceLayerProperties) }, + { "vkEnumerateInstanceExtensionProperties", reinterpret_cast(EnumerateInstanceExtensionProperties) }, { "vkEnumerateDeviceExtensionProperties", reinterpret_cast(EnumerateDeviceExtensionProperties) }, { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast(GetPhysicalDeviceQueueFamilyProperties) }, }; - // we should never be queried for these commands - assert(strcmp(name, "vkEnumerateInstanceLayerProperties") && - strcmp(name, "vkEnumerateInstanceExtensionProperties") && - strcmp(name, "vkEnumerateDeviceLayerProperties")); - for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) { if (!strcmp(core_instance_commands[i].name, name)) return core_instance_commands[i].proc; @@ -2331,27 +2347,30 @@ vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebu swapchain::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); } -// loader-layer interface v0 +// loader-layer interface v0, just wrappers since there is only a layer VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - return util_GetExtensionProperties(ARRAY_SIZE(swapchain::instance_extensions), swapchain::instance_extensions, pCount, pProperties); + return swapchain::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { - return util_GetLayerProperties(1, &swapchain::swapchain_layer, pCount, pProperties); + return swapchain::EnumerateInstanceLayerProperties(pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { - return util_GetLayerProperties(1, &swapchain::swapchain_layer, pCount, pProperties); + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); + return swapchain::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - // the layer command handles VK_NULL_HANDLE just fine + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); return swapchain::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); } @@ -2360,14 +2379,5 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD } VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { - if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties")) - return reinterpret_cast(vkEnumerateInstanceLayerProperties); - if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties")) - return reinterpret_cast(vkEnumerateDeviceLayerProperties); - if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties")) - return reinterpret_cast(vkEnumerateInstanceExtensionProperties); - if (!strcmp(funcName, "vkGetInstanceProcAddr")) - return reinterpret_cast(vkGetInstanceProcAddr); - return swapchain::GetInstanceProcAddr(instance, funcName); } diff --git a/layers/threading.cpp b/layers/threading.cpp index 2de00522..f5d37eba 100644 --- a/layers/threading.cpp +++ b/layers/threading.cpp @@ -176,6 +176,24 @@ static inline PFN_vkVoidFunction layer_intercept_proc(const char *name) { return NULL; } +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &layerProps, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { + return util_GetLayerProperties(1, &layerProps, pCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL +EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { + if (pLayerName && !strcmp(pLayerName, layerProps.layerName)) + return util_GetExtensionProperties(1, threading_extensions, pCount, pProperties); + + return VK_ERROR_LAYER_NOT_PRESENT; +} + VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { @@ -194,16 +212,17 @@ static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name) if (!name || name[0] != 'v' || name[1] != 'k') return NULL; - // we should never be queried for these commands - assert(strcmp(name, "vkEnumerateInstanceLayerProperties") && - strcmp(name, "vkEnumerateInstanceExtensionProperties") && - strcmp(name, "vkEnumerateDeviceLayerProperties")); - name += 2; if (!strcmp(name, "CreateInstance")) return (PFN_vkVoidFunction)CreateInstance; if (!strcmp(name, "DestroyInstance")) return (PFN_vkVoidFunction)DestroyInstance; + if (!strcmp(name, "EnumerateInstanceLayerProperties")) + return (PFN_vkVoidFunction)EnumerateInstanceLayerProperties; + if (!strcmp(name, "EnumerateInstanceExtensionProperties")) + return (PFN_vkVoidFunction)EnumerateInstanceExtensionProperties; + if (!strcmp(name, "EnumerateDeviceLayerProperties")) + return (PFN_vkVoidFunction)EnumerateDeviceLayerProperties; if (!strcmp(name, "EnumerateDeviceExtensionProperties")) return (PFN_vkVoidFunction)EnumerateDeviceExtensionProperties; if (!strcmp(name, "CreateDevice")) @@ -351,26 +370,30 @@ vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebu threading::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg); } -// loader-layer interface v0 +// loader-layer interface v0, just wrappers since there is only a layer VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - return util_GetExtensionProperties(ARRAY_SIZE(threading::threading_extensions), threading::threading_extensions, pCount, pProperties); + return threading::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties); } -VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { - return util_GetLayerProperties(1, &threading::layerProps, pCount, pProperties); +VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL +vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) { + return threading::EnumerateInstanceLayerProperties(pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) { - return util_GetLayerProperties(1, &threading::layerProps, pCount, pProperties); + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); + return threading::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties); } VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) { - // the layer command handles VK_NULL_HANDLE just fine + // the layer command handles VK_NULL_HANDLE just fine internally + assert(physicalDevice == VK_NULL_HANDLE); return threading::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties); } @@ -379,14 +402,5 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD } VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) { - if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties")) - return reinterpret_cast(vkEnumerateInstanceLayerProperties); - if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties")) - return reinterpret_cast(vkEnumerateDeviceLayerProperties); - if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties")) - return reinterpret_cast(vkEnumerateInstanceExtensionProperties); - if (!strcmp(funcName, "vkGetInstanceProcAddr")) - return reinterpret_cast(vkGetInstanceProcAddr); - return threading::GetInstanceProcAddr(instance, funcName); } diff --git a/vk-layer-generate.py b/vk-layer-generate.py index 24f3c93b..0ec0bc07 100755 --- a/vk-layer-generate.py +++ b/vk-layer-generate.py @@ -375,50 +375,24 @@ class Subcommand(object): def _gen_layer_interface_v0_functions(self): body = [] body.append('%s' % self.lineinfo.get()) - body.append('// loader-layer interface v0') + body.append('// loader-layer interface v0, just wrappers since there is only a layer') body.append('') - if self.layer_name == 'object_tracker': - body.append('static const VkExtensionProperties instance_extensions[] = {') - body.append(' {') - body.append(' VK_EXT_DEBUG_REPORT_EXTENSION_NAME,') - body.append(' VK_EXT_DEBUG_REPORT_SPEC_VERSION') - body.append(' }') - body.append('};') - body.append('') - - body.append('static const VkLayerProperties globalLayerProps = {') - body.append(' "VK_LAYER_LUNARG_%s",' % self.layer_name) - body.append(' VK_LAYER_API_VERSION, // specVersion') - body.append(' 1, // implementationVersion') - body.append(' "LunarG Validation Layer"') - body.append('};') - body.append('') - else: - body.append('static const VkLayerProperties globalLayerProps = {') - body.append(' "VK_LAYER_GOOGLE_%s",' % self.layer_name) - body.append(' VK_LAYER_API_VERSION, // specVersion') - body.append(' 1, // implementationVersion') - body.append(' "Google Validation Layer"') - body.append('};') - body.append('') - body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties* pProperties)') body.append('{') - if self.layer_name == 'object_tracker': - body.append(' return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);') - else: - body.append(' return util_GetExtensionProperties(0, NULL, pCount, pProperties);') + body.append(' return %s::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);' % self.layer_name) body.append('}') body.append('') body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties* pProperties)') body.append('{') - body.append(' return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);') + body.append(' return %s::EnumerateInstanceLayerProperties(pCount, pProperties);' % self.layer_name) body.append('}') body.append('') body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties* pProperties)') body.append('{') - body.append(' return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);') + body.append(' // the layer command handles VK_NULL_HANDLE just fine internally') + body.append(' assert(physicalDevice == VK_NULL_HANDLE);') + body.append(' return %s::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);' % self.layer_name) body.append('}') body.append('') body.append('VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName)') @@ -428,17 +402,17 @@ class Subcommand(object): body.append('') body.append('VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName)') body.append('{') - body.append(' if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))') - body.append(' return reinterpret_cast(vkEnumerateInstanceLayerProperties);') - body.append(' if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))') - body.append(' return reinterpret_cast(vkEnumerateDeviceLayerProperties);') - body.append(' if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))') - body.append(' return reinterpret_cast(vkEnumerateInstanceExtensionProperties);') - body.append(' if (!strcmp(funcName, "vkGetInstanceProcAddr"))') - body.append(' return reinterpret_cast(vkGetInstanceProcAddr);') - body.append('') body.append(' return %s::GetInstanceProcAddr(instance, funcName);' % self.layer_name) body.append('}') + body.append('') + body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,') + body.append(' const char *pLayerName, uint32_t *pCount,') + body.append(' VkExtensionProperties *pProperties)') + body.append('{') + body.append(' // the layer command handles VK_NULL_HANDLE just fine internally') + body.append(' assert(physicalDevice == VK_NULL_HANDLE);') + body.append(' return %s::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);' % self.layer_name) + body.append('}') return "\n".join(body) @@ -451,11 +425,9 @@ class Subcommand(object): for proto in self.protos: if proto.name in ["EnumerateInstanceExtensionProperties", "EnumerateInstanceLayerProperties", - "EnumerateDeviceLayerProperties"]: - # the layer do not need to define these - continue - elif proto.name in ["GetDeviceProcAddr", - "GetInstanceProcAddr"]: + "EnumerateDeviceLayerProperties", + "GetDeviceProcAddr", + "GetInstanceProcAddr"]: funcs.append(proto.c_func(attr="VKAPI") + ';') intercepted.append(proto) else: @@ -503,11 +475,6 @@ class Subcommand(object): body.append("{") body.append(generate_get_proc_addr_check("name")) body.append("") - body.append(" // we should never be queried for these commands") - body.append(" assert(strcmp(name, \"vkEnumerateInstanceLayerProperties\") &&") - body.append(" strcmp(name, \"vkEnumerateInstanceExtensionProperties\") &&") - body.append(" strcmp(name, \"vkEnumerateDeviceLayerProperties\"));") - body.append("") body.append(" name += 2;") body.append(" %s" % "\n ".join(instance_lookups)) body.append("") @@ -525,6 +492,69 @@ class Subcommand(object): exts.append(self._gen_debug_report_msg()) return "\n".join(exts) + def _generate_layer_introspection_function(self): + body = [] + body.append('%s' % self.lineinfo.get()) + if self.layer_name == 'object_tracker': + body.append('static const VkExtensionProperties instance_extensions[] = {') + body.append(' {') + body.append(' VK_EXT_DEBUG_REPORT_EXTENSION_NAME,') + body.append(' VK_EXT_DEBUG_REPORT_SPEC_VERSION') + body.append(' }') + body.append('};') + body.append('') + + body.append('static const VkLayerProperties globalLayerProps = {') + body.append(' "VK_LAYER_LUNARG_%s",' % self.layer_name) + body.append(' VK_LAYER_API_VERSION, // specVersion') + body.append(' 1, // implementationVersion') + body.append(' "LunarG Validation Layer"') + body.append('};') + body.append('') + else: + body.append('static const VkLayerProperties globalLayerProps = {') + body.append(' "VK_LAYER_GOOGLE_%s",' % self.layer_name) + body.append(' VK_LAYER_API_VERSION, // specVersion') + body.append(' 1, // implementationVersion') + body.append(' "Google Validation Layer"') + body.append('};') + body.append('') + + body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties* pProperties)') + body.append('{') + body.append(' return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);') + body.append('}') + body.append('') + body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties* pProperties)') + body.append('{') + body.append(' return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);') + body.append('}') + body.append('') + body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties* pProperties)') + body.append('{') + body.append(' if (pLayerName && !strcmp(pLayerName, globalLayerProps.layerName))') + if self.layer_name == 'object_tracker': + body.append(' return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);') + else: + body.append(' return util_GetExtensionProperties(0, NULL, pCount, pProperties);') + body.append('') + body.append(' return VK_ERROR_LAYER_NOT_PRESENT;') + body.append('}') + body.append('') + body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,') + body.append(' const char *pLayerName, uint32_t *pCount,') + body.append(' VkExtensionProperties *pProperties)') + body.append('{') + body.append(' if (pLayerName && !strcmp(pLayerName, globalLayerProps.layerName))') + body.append(' return util_GetExtensionProperties(0, nullptr, pCount, pProperties);') + body.append('') + body.append(' assert(physicalDevice);') + body.append(' VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, physicalDevice);' % self.layer_name) + body.append(' return pTable->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);') + body.append('}') + + return "\n".join(body) + def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]): func_body = [] # @@ -1358,6 +1388,7 @@ class ObjectTrackerSubcommand(Subcommand): self.generate_destroy_device(), self._generate_dispatch_entrypoints(), self._generate_extensions(), + self._generate_layer_introspection_function(), self._generate_layer_gpa_function(extensions, instance_extensions), "} // namespace %s" % self.layer_name, @@ -1662,6 +1693,7 @@ class UniqueObjectsSubcommand(Subcommand): body = ["namespace %s {" % self.layer_name, self._generate_dispatch_entrypoints(), + self._generate_layer_introspection_function(), self._generate_layer_gpa_function(extensions, instance_extensions), "} // namespace %s" % self.layer_name, -- cgit v1.2.3 From 2fc91e01eeb0cec1b03332570c5eebe0d380a305 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 26 May 2016 11:21:59 -0600 Subject: layers: Add DescriptorSet interface for allocation Create a top-level "Validate" and "Perform" interface for the vkAllocateDescriptorSets() function in DescriptorSet class. Refactor AllocateDescriptorSets() in core_validation to use the new interface. All checks are now performed in a "Pre" function and all state updates are recorded in a "Post" function. --- layers/core_validation.cpp | 106 +++++++-------------------------------------- layers/descriptor_sets.cpp | 93 +++++++++++++++++++++++++++++++++++++++ layers/descriptor_sets.h | 21 +++++++-- 3 files changed, 127 insertions(+), 93 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index cf44ce68..e7201a7d 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5869,110 +5869,36 @@ ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescript // Ensure the pool contains enough descriptors and descriptor sets to satisfy // an allocation request. Fills requiredDescriptorsByType with the total number // of descriptors of each type required, for later update. -static bool PreCallValidateAllocateDescriptorSets(const layer_data *dev_data, const DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count, - std::vector const &layout_nodes, - uint32_t requiredDescriptorsByType[]) { - bool skipCall = false; - - // Track number of descriptorSets allowable in this pool - if (pPoolNode->availableSets < count) { - skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, - reinterpret_cast(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", - "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64 - ". This pool only has %d descriptorSets remaining.", - count, reinterpret_cast(pPoolNode->pool), pPoolNode->availableSets); - } - - // Count total descriptors required per type - for (auto layout_node : layout_nodes) { - if (layout_node) { - for (uint32_t j = 0; j < layout_node->GetBindingCount(); ++j) { - const auto &binding_layout = layout_node->GetDescriptorSetLayoutBindingPtrFromIndex(j); - uint32_t typeIndex = static_cast(binding_layout->descriptorType); - requiredDescriptorsByType[typeIndex] += binding_layout->descriptorCount; - } - } - } - - // Determine whether descriptor counts are satisfiable - for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { - if (requiredDescriptorsByType[i] > pPoolNode->availableDescriptorTypeCount[i]) { - skipCall |= log_msg( - dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, - reinterpret_cast(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", - "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64 - ". This pool only has %d descriptors of this type remaining.", - requiredDescriptorsByType[i], string_VkDescriptorType(VkDescriptorType(i)), (uint64_t)pPoolNode->pool, - pPoolNode->availableDescriptorTypeCount[i]); - } - } - - return skipCall; +static bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo) { + // All state checks for AllocateDescriptorSets is done in single function + return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data->report_data, pAllocateInfo, dev_data->descriptorSetLayoutMap, + dev_data->descriptorPoolMap); +} +// Allocation state was good and call down chain was made so update state based on allocating descriptor sets +static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, + VkDescriptorSet *pDescriptorSets) { + // All the updates are contained in a single cvdescriptorset function + cvdescriptorset::PerformAllocateDescriptorSets( + pAllocateInfo, pDescriptorSets, &dev_data->descriptorPoolMap, &dev_data->setMap, dev_data->descriptorSetLayoutMap, + dev_data->bufferMap, dev_data->memObjMap, dev_data->bufferViewMap, dev_data->samplerMap, dev_data->imageViewMap, + dev_data->imageMap, dev_data->device_extensions.imageToSwapchainMap, dev_data->device_extensions.swapchainMap); } VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) { - bool skipCall = false; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); - - uint32_t requiredDescriptorsByType[VK_DESCRIPTOR_TYPE_RANGE_SIZE] {}; - std::vector layout_nodes(pAllocateInfo->descriptorSetCount, nullptr); - std::unique_lock lock(global_lock); - - for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) { - layout_nodes[i] = getDescriptorSetLayout(dev_data, pAllocateInfo->pSetLayouts[i]); - if (!layout_nodes[i]) { - skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, - (uint64_t)pAllocateInfo->pSetLayouts[i], __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", - "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", - (uint64_t)pAllocateInfo->pSetLayouts[i]); - } - } - - DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, pAllocateInfo->descriptorPool); - - if (!pPoolNode) { - skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, - (uint64_t)pAllocateInfo->descriptorPool, __LINE__, DRAWSTATE_INVALID_POOL, "DS", - "Unable to find pool node for pool 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", - (uint64_t)pAllocateInfo->descriptorPool); - } else { // Make sure pool has all the available descriptors before calling down chain - skipCall |= PreCallValidateAllocateDescriptorSets(dev_data, pPoolNode, pAllocateInfo->descriptorSetCount, - layout_nodes, requiredDescriptorsByType); - } + bool skip_call = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo); lock.unlock(); - if (skipCall) + if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; VkResult result = dev_data->device_dispatch_table->AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets); if (VK_SUCCESS == result) { lock.lock(); - if (pPoolNode) { - /* Account for sets and descriptors allocated */ - pPoolNode->availableSets -= pAllocateInfo->descriptorSetCount; - for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { - pPoolNode->availableDescriptorTypeCount[i] -= requiredDescriptorsByType[i]; - } - - /* Create tracking object for each descriptor set; insert into - * global map and the pool's set. - */ - for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) { - if (layout_nodes[i]) { - auto pNewNode = new cvdescriptorset::DescriptorSet( - pDescriptorSets[i], layout_nodes[i], &dev_data->bufferMap, &dev_data->memObjMap, &dev_data->bufferViewMap, - &dev_data->samplerMap, &dev_data->imageViewMap, &dev_data->imageMap, - &dev_data->device_extensions.imageToSwapchainMap, &dev_data->device_extensions.swapchainMap); - - pPoolNode->sets.insert(pNewNode); - pNewNode->in_use.store(0); - dev_data->setMap[pDescriptorSets[i]] = pNewNode; - } - } - } + PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets); lock.unlock(); } return result; diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 0530f40c..ede1b5a3 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -1222,3 +1222,96 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri // All checks passed so update contents are good return true; } +// Verify that the state at allocate time is correct, but don't actually allocate the sets yet +bool cvdescriptorset::ValidateAllocateDescriptorSets( + const debug_report_data *report_data, const VkDescriptorSetAllocateInfo *p_alloc_info, + const std::unordered_map &set_layout_map, + const std::unordered_map &pool_map) { + bool skip_call = false; + uint32_t requiredDescriptorsByType[VK_DESCRIPTOR_TYPE_RANGE_SIZE]{}; + + for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { + auto layout_it = set_layout_map.find(p_alloc_info->pSetLayouts[i]); + if (layout_it == set_layout_map.end()) { + skip_call |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, + reinterpret_cast(p_alloc_info->pSetLayouts[i]), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", + "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", + reinterpret_cast(p_alloc_info->pSetLayouts[i])); + } + // Count total descriptors required per type + for (uint32_t j = 0; j < layout_it->second->GetBindingCount(); ++j) { + const auto &binding_layout = layout_it->second->GetDescriptorSetLayoutBindingPtrFromIndex(j); + uint32_t typeIndex = static_cast(binding_layout->descriptorType); + requiredDescriptorsByType[typeIndex] += binding_layout->descriptorCount; + } + } + auto pool_it = pool_map.find(p_alloc_info->descriptorPool); + if (pool_it == pool_map.end()) { + skip_call |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, + reinterpret_cast(p_alloc_info->descriptorPool), __LINE__, DRAWSTATE_INVALID_POOL, "DS", + "Unable to find pool node for pool 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", + reinterpret_cast(p_alloc_info->descriptorPool)); + } else { // Make sure pool has all the available descriptors before calling down chain + // Track number of descriptorSets allowable in this pool + if (pool_it->second->availableSets < p_alloc_info->descriptorSetCount) { + skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, + reinterpret_cast(pool_it->second->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, + "DS", "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64 + ". This pool only has %d descriptorSets remaining.", + p_alloc_info->descriptorSetCount, reinterpret_cast(pool_it->second->pool), + pool_it->second->availableSets); + } + // Determine whether descriptor counts are satisfiable + for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { + if (requiredDescriptorsByType[i] > pool_it->second->availableDescriptorTypeCount[i]) { + skip_call |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, + reinterpret_cast(pool_it->second->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, + "DS", "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64 + ". This pool only has %d descriptors of this type remaining.", + requiredDescriptorsByType[i], string_VkDescriptorType(VkDescriptorType(i)), + reinterpret_cast(pool_it->second->pool), pool_it->second->availableDescriptorTypeCount[i]); + } + } + } + return skip_call; +} +// Decrement allocated sets from the pool and insert new sets into set_map +void cvdescriptorset::PerformAllocateDescriptorSets( + const VkDescriptorSetAllocateInfo *p_alloc_info, const VkDescriptorSet *descriptor_sets, + std::unordered_map *pool_map, + std::unordered_map *set_map, + const std::unordered_map &layout_map, + const std::unordered_map &buffer_map, + const std::unordered_map &mem_obj_map, + const std::unordered_map &buffer_view_map, + const std::unordered_map> &sampler_map, + const std::unordered_map &image_view_map, + const std::unordered_map &image_map, + const std::unordered_map &image_to_swapchain_map, + const std::unordered_map &swapchain_map) { + auto pool_state = (*pool_map)[p_alloc_info->descriptorPool]; + /* Account for sets allocated from pool */ + pool_state->availableSets -= p_alloc_info->descriptorSetCount; + /* Create tracking object for each descriptor set; insert into + * global map and the pool's set. + */ + for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { + auto layout_state = layout_map.find(p_alloc_info->pSetLayouts[i])->second; + // Account for individual descriptors allocated from pool + for (uint32_t j = 0; j < layout_state->GetBindingCount(); ++j) { + const auto &binding_layout = layout_state->GetDescriptorSetLayoutBindingPtrFromIndex(j); + uint32_t type_index = static_cast(binding_layout->descriptorType); + pool_state->availableDescriptorTypeCount[type_index] -= binding_layout->descriptorCount; + } + auto new_ds = + new cvdescriptorset::DescriptorSet(descriptor_sets[i], layout_state, &buffer_map, &mem_obj_map, &buffer_view_map, + &sampler_map, &image_view_map, &image_map, &image_to_swapchain_map, &swapchain_map); + + pool_state->sets.insert(new_ds); + new_ds->in_use.store(0); + (*set_map)[descriptor_sets[i]] = new_ds; + } +} diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index b0496b1e..af062dd7 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -245,14 +245,29 @@ class BufferDescriptor : public Descriptor { VkDeviceSize offset_; VkDeviceSize range_; }; -// Helper functions for Updating descriptor sets since it crosses multiple sets -// Validate will make sure an update is ok without actually performing it +// Helper functions for descriptor set functions that cross multiple sets +// "Validate" will make sure an update is ok without actually performing it bool ValidateUpdateDescriptorSets(const debug_report_data *, const std::unordered_map &, uint32_t, const VkWriteDescriptorSet *, uint32_t, const VkCopyDescriptorSet *); -// Perform does the update with the assumption that ValidateUpdateDescriptorSets() has passed for the given update +// "Perform" does the update with the assumption that ValidateUpdateDescriptorSets() has passed for the given update void PerformUpdateDescriptorSets(const std::unordered_map &, uint32_t, const VkWriteDescriptorSet *, uint32_t, const VkCopyDescriptorSet *); +// Validate that Allocation state is ok +bool ValidateAllocateDescriptorSets(const debug_report_data *, const VkDescriptorSetAllocateInfo *, + const std::unordered_map &, + const std::unordered_map &); +// Update state based on allocating new descriptorsets +void PerformAllocateDescriptorSets( + const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, std::unordered_map *, + std::unordered_map *, + const std::unordered_map &, + const std::unordered_map &, const std::unordered_map &, + const std::unordered_map &, + const std::unordered_map> &, + const std::unordered_map &, const std::unordered_map &, + const std::unordered_map &, const std::unordered_map &); + /* * DescriptorSet class * -- cgit v1.2.3 From 2f68b290d22d933fda156e0101bb2ebf2f493c04 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Wed, 1 Jun 2016 11:33:50 -0600 Subject: layers: Pass common data between pre/post AllocDescriptorSets With the break between PreValidate* and PostRecord* calls in the layers we can suffer having to do some repeat work in the Post step. In order to prevent this, this CL slightly modifies the interface to pass common data between the pre/post calls in a custom AllocateDescriptorSetsData struct. I initially attempted to fill this data in a separate function that would preceed the PreValidate* call, but such a function would need to include some validation as it includes map checks which may fail. The simplest solution, then, seems to be passing a ptr to the common data to the PreValidate* function who then fills the data. If the validation and call down the chain succeed, the PostRecord* function then takes a ptr to the common data to prevent having to redo the work that was done at validation time. --- layers/core_validation.cpp | 20 ++++++++++++-------- layers/descriptor_sets.cpp | 44 ++++++++++++++++++++++---------------------- layers/descriptor_sets.h | 30 ++++++++++++++++++++---------- 3 files changed, 54 insertions(+), 40 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index e7201a7d..21d3b077 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5869,26 +5869,30 @@ ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescript // Ensure the pool contains enough descriptors and descriptor sets to satisfy // an allocation request. Fills requiredDescriptorsByType with the total number // of descriptors of each type required, for later update. -static bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo) { +static bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, + cvdescriptorset::AllocateDescriptorSetsData *common_data) { // All state checks for AllocateDescriptorSets is done in single function return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data->report_data, pAllocateInfo, dev_data->descriptorSetLayoutMap, - dev_data->descriptorPoolMap); + dev_data->descriptorPoolMap, common_data); } // Allocation state was good and call down chain was made so update state based on allocating descriptor sets static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, - VkDescriptorSet *pDescriptorSets) { + VkDescriptorSet *pDescriptorSets, + const cvdescriptorset::AllocateDescriptorSetsData *common_data) { // All the updates are contained in a single cvdescriptorset function cvdescriptorset::PerformAllocateDescriptorSets( - pAllocateInfo, pDescriptorSets, &dev_data->descriptorPoolMap, &dev_data->setMap, dev_data->descriptorSetLayoutMap, - dev_data->bufferMap, dev_data->memObjMap, dev_data->bufferViewMap, dev_data->samplerMap, dev_data->imageViewMap, - dev_data->imageMap, dev_data->device_extensions.imageToSwapchainMap, dev_data->device_extensions.swapchainMap); + pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, &dev_data->setMap, + dev_data->descriptorSetLayoutMap, dev_data->bufferMap, dev_data->memObjMap, dev_data->bufferViewMap, dev_data->samplerMap, + dev_data->imageViewMap, dev_data->imageMap, dev_data->device_extensions.imageToSwapchainMap, + dev_data->device_extensions.swapchainMap); } VKAPI_ATTR VkResult VKAPI_CALL AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) { layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); std::unique_lock lock(global_lock); - bool skip_call = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo); + cvdescriptorset::AllocateDescriptorSetsData common_data(pAllocateInfo->descriptorSetCount); + bool skip_call = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo, &common_data); lock.unlock(); if (skip_call) @@ -5898,7 +5902,7 @@ AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllo if (VK_SUCCESS == result) { lock.lock(); - PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets); + PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets, &common_data); lock.unlock(); } return result; diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index ede1b5a3..5cb38e56 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -260,6 +260,9 @@ bool cvdescriptorset::DescriptorSetLayout::VerifyUpdateConsistency(uint32_t curr return true; } +cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t count) + : required_descriptors_by_type{}, layout_nodes(count, nullptr) {} + cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout, const std::unordered_map *buffer_map, const std::unordered_map *memory_map, @@ -1226,9 +1229,8 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri bool cvdescriptorset::ValidateAllocateDescriptorSets( const debug_report_data *report_data, const VkDescriptorSetAllocateInfo *p_alloc_info, const std::unordered_map &set_layout_map, - const std::unordered_map &pool_map) { + const std::unordered_map &pool_map, AllocateDescriptorSetsData *ds_data) { bool skip_call = false; - uint32_t requiredDescriptorsByType[VK_DESCRIPTOR_TYPE_RANGE_SIZE]{}; for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { auto layout_it = set_layout_map.find(p_alloc_info->pSetLayouts[i]); @@ -1238,12 +1240,14 @@ bool cvdescriptorset::ValidateAllocateDescriptorSets( reinterpret_cast(p_alloc_info->pSetLayouts[i]), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", reinterpret_cast(p_alloc_info->pSetLayouts[i])); - } - // Count total descriptors required per type - for (uint32_t j = 0; j < layout_it->second->GetBindingCount(); ++j) { - const auto &binding_layout = layout_it->second->GetDescriptorSetLayoutBindingPtrFromIndex(j); - uint32_t typeIndex = static_cast(binding_layout->descriptorType); - requiredDescriptorsByType[typeIndex] += binding_layout->descriptorCount; + } else { + ds_data->layout_nodes[i] = layout_it->second; + // Count total descriptors required per type + for (uint32_t j = 0; j < layout_it->second->GetBindingCount(); ++j) { + const auto &binding_layout = layout_it->second->GetDescriptorSetLayoutBindingPtrFromIndex(j); + uint32_t typeIndex = static_cast(binding_layout->descriptorType); + ds_data->required_descriptors_by_type[typeIndex] += binding_layout->descriptorCount; + } } } auto pool_it = pool_map.find(p_alloc_info->descriptorPool); @@ -1265,13 +1269,13 @@ bool cvdescriptorset::ValidateAllocateDescriptorSets( } // Determine whether descriptor counts are satisfiable for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { - if (requiredDescriptorsByType[i] > pool_it->second->availableDescriptorTypeCount[i]) { + if (ds_data->required_descriptors_by_type[i] > pool_it->second->availableDescriptorTypeCount[i]) { skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, reinterpret_cast(pool_it->second->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64 ". This pool only has %d descriptors of this type remaining.", - requiredDescriptorsByType[i], string_VkDescriptorType(VkDescriptorType(i)), + ds_data->required_descriptors_by_type[i], string_VkDescriptorType(VkDescriptorType(i)), reinterpret_cast(pool_it->second->pool), pool_it->second->availableDescriptorTypeCount[i]); } } @@ -1281,7 +1285,7 @@ bool cvdescriptorset::ValidateAllocateDescriptorSets( // Decrement allocated sets from the pool and insert new sets into set_map void cvdescriptorset::PerformAllocateDescriptorSets( const VkDescriptorSetAllocateInfo *p_alloc_info, const VkDescriptorSet *descriptor_sets, - std::unordered_map *pool_map, + const AllocateDescriptorSetsData *ds_data, std::unordered_map *pool_map, std::unordered_map *set_map, const std::unordered_map &layout_map, const std::unordered_map &buffer_map, @@ -1293,22 +1297,18 @@ void cvdescriptorset::PerformAllocateDescriptorSets( const std::unordered_map &image_to_swapchain_map, const std::unordered_map &swapchain_map) { auto pool_state = (*pool_map)[p_alloc_info->descriptorPool]; - /* Account for sets allocated from pool */ + /* Account for sets and individual descriptors allocated from pool */ pool_state->availableSets -= p_alloc_info->descriptorSetCount; + for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { + pool_state->availableDescriptorTypeCount[i] -= ds_data->required_descriptors_by_type[i]; + } /* Create tracking object for each descriptor set; insert into * global map and the pool's set. */ for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { - auto layout_state = layout_map.find(p_alloc_info->pSetLayouts[i])->second; - // Account for individual descriptors allocated from pool - for (uint32_t j = 0; j < layout_state->GetBindingCount(); ++j) { - const auto &binding_layout = layout_state->GetDescriptorSetLayoutBindingPtrFromIndex(j); - uint32_t type_index = static_cast(binding_layout->descriptorType); - pool_state->availableDescriptorTypeCount[type_index] -= binding_layout->descriptorCount; - } - auto new_ds = - new cvdescriptorset::DescriptorSet(descriptor_sets[i], layout_state, &buffer_map, &mem_obj_map, &buffer_view_map, - &sampler_map, &image_view_map, &image_map, &image_to_swapchain_map, &swapchain_map); + auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], &buffer_map, &mem_obj_map, + &buffer_view_map, &sampler_map, &image_view_map, &image_map, + &image_to_swapchain_map, &swapchain_map); pool_state->sets.insert(new_ds); new_ds->in_use.store(0); diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index af062dd7..bb5907ca 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -245,6 +245,12 @@ class BufferDescriptor : public Descriptor { VkDeviceSize offset_; VkDeviceSize range_; }; +// Structs to contain common elements that need to be shared between Validate* and Perform* calls below +struct AllocateDescriptorSetsData { + uint32_t required_descriptors_by_type[VK_DESCRIPTOR_TYPE_RANGE_SIZE]; + std::vector layout_nodes; + AllocateDescriptorSetsData(uint32_t); +}; // Helper functions for descriptor set functions that cross multiple sets // "Validate" will make sure an update is ok without actually performing it bool ValidateUpdateDescriptorSets(const debug_report_data *, @@ -256,17 +262,21 @@ void PerformUpdateDescriptorSets(const std::unordered_map &, - const std::unordered_map &); + const std::unordered_map &, + AllocateDescriptorSetsData *); // Update state based on allocating new descriptorsets -void PerformAllocateDescriptorSets( - const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, std::unordered_map *, - std::unordered_map *, - const std::unordered_map &, - const std::unordered_map &, const std::unordered_map &, - const std::unordered_map &, - const std::unordered_map> &, - const std::unordered_map &, const std::unordered_map &, - const std::unordered_map &, const std::unordered_map &); +void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, const AllocateDescriptorSetsData *, + std::unordered_map *, + std::unordered_map *, + const std::unordered_map &, + const std::unordered_map &, + const std::unordered_map &, + const std::unordered_map &, + const std::unordered_map> &, + const std::unordered_map &, + const std::unordered_map &, + const std::unordered_map &, + const std::unordered_map &); /* * DescriptorSet class -- cgit v1.2.3 From caefb8d8551f5a32cb850c939a4c4505cd83a1c4 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Wed, 1 Jun 2016 11:56:42 -0600 Subject: layers: Comment update The behavior of the PreCallValidateAllocateDescriptorSets slightly changed so updating comment accordingly. --- layers/core_validation.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 21d3b077..635f6c4b 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5865,10 +5865,9 @@ ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescript } return result; } - // Ensure the pool contains enough descriptors and descriptor sets to satisfy -// an allocation request. Fills requiredDescriptorsByType with the total number -// of descriptors of each type required, for later update. +// an allocation request. Fills common_data with the total number of descriptors of each type required, +// as well as DescriptorSetLayout ptrs used for later update. static bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, cvdescriptorset::AllocateDescriptorSetsData *common_data) { // All state checks for AllocateDescriptorSets is done in single function -- cgit v1.2.3 From ffaf95b453b9bd058f26bf0276f4010caaeabcf1 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Wed, 1 Jun 2016 16:41:17 -0600 Subject: layers: Make layer_data visible to DescriptorSet This is the start of migrating core_validation::layer_data to be visible in DescriptorSet class. DescriptorSet class can't see the contents of layer_data, so it also needs the get() helper functions to look up items from the maps. This first change only brings along getSetNode() utility function so only set_map references can be removed. Will add follow-on CLs to remove more maps from DescriptorSet class and bring in more utility functions. --- layers/core_validation.cpp | 15 +++++++------- layers/core_validation_types.h | 5 +++++ layers/descriptor_sets.cpp | 45 +++++++++++++++++++++--------------------- layers/descriptor_sets.h | 29 ++++++++++++--------------- 4 files changed, 49 insertions(+), 45 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 635f6c4b..66d3abd2 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -2625,11 +2625,12 @@ static bool validate_compute_pipeline(debug_report_data *report_data, PIPELINE_N } // Return Set node ptr for specified set or else NULL -static cvdescriptorset::DescriptorSet *getSetNode(layer_data *my_data, const VkDescriptorSet set) { - if (my_data->setMap.find(set) == my_data->setMap.end()) { +cvdescriptorset::DescriptorSet *getSetNode(const layer_data *my_data, const VkDescriptorSet set) { + auto set_it = my_data->setMap.find(set); + if (set_it == my_data->setMap.end()) { return NULL; } - return my_data->setMap[set]; + return set_it->second; } // For the given command buffer, verify and update the state for activeSetBindingsPairs // This includes: @@ -5880,7 +5881,7 @@ static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkD const cvdescriptorset::AllocateDescriptorSetsData *common_data) { // All the updates are contained in a single cvdescriptorset function cvdescriptorset::PerformAllocateDescriptorSets( - pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, &dev_data->setMap, + pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, &dev_data->setMap, dev_data, dev_data->descriptorSetLayoutMap, dev_data->bufferMap, dev_data->memObjMap, dev_data->bufferViewMap, dev_data->samplerMap, dev_data->imageViewMap, dev_data->imageMap, dev_data->device_extensions.imageToSwapchainMap, dev_data->device_extensions.swapchainMap); @@ -5976,14 +5977,14 @@ static bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t d // Now make call(s) that validate state, but don't perform state updates in this function // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the // namespace which will parse params and make calls into specific class instances - return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data->setMap, descriptorWriteCount, - pDescriptorWrites, descriptorCopyCount, pDescriptorCopies); + return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data, descriptorWriteCount, pDescriptorWrites, + descriptorCopyCount, pDescriptorCopies); } // PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets() static void PostCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) { - cvdescriptorset::PerformUpdateDescriptorSets(dev_data->setMap, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, + cvdescriptorset::PerformUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies); } diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 0b35fa16..901c1870 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -62,6 +62,11 @@ class BASE_NODE { std::atomic_int in_use; }; +namespace core_validation { +struct layer_data; +cvdescriptorset::DescriptorSet *getSetNode(const layer_data *, const VkDescriptorSet); +} + struct DESCRIPTOR_POOL_NODE { VkDescriptorPool pool; uint32_t maxSets; // Max descriptor sets allowed in this pool diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 5cb38e56..97e21b5a 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -841,15 +841,16 @@ void cvdescriptorset::TexelDescriptor::CopyUpdate(const Descriptor *src) { // If the update hits an issue for which the callback returns "true", meaning that the call down the chain should // be skipped, then true is returned. // If there is no issue with the update, then false is returned. -bool cvdescriptorset::ValidateUpdateDescriptorSets( - const debug_report_data *report_data, const std::unordered_map &set_map, - uint32_t write_count, const VkWriteDescriptorSet *p_wds, uint32_t copy_count, const VkCopyDescriptorSet *p_cds) { +bool cvdescriptorset::ValidateUpdateDescriptorSets(const debug_report_data *report_data, + const core_validation::layer_data *dev_data, uint32_t write_count, + const VkWriteDescriptorSet *p_wds, uint32_t copy_count, + const VkCopyDescriptorSet *p_cds) { bool skip_call = false; // Validate Write updates for (uint32_t i = 0; i < write_count; i++) { auto dest_set = p_wds[i].dstSet; - auto set_pair = set_map.find(dest_set); - if (set_pair == set_map.end()) { + auto set_node = core_validation::getSetNode(dev_data, dest_set); + if (!set_node) { skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast(dest_set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS", @@ -857,7 +858,7 @@ bool cvdescriptorset::ValidateUpdateDescriptorSets( reinterpret_cast(dest_set)); } else { std::string error_str; - if (!set_pair->second->ValidateWriteUpdate(report_data, &p_wds[i], &error_str)) { + if (!set_node->ValidateWriteUpdate(report_data, &p_wds[i], &error_str)) { skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast(dest_set), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", "vkUpdateDescriptorsSets() failed write update validation for Descriptor Set 0x%" PRIx64 @@ -870,15 +871,15 @@ bool cvdescriptorset::ValidateUpdateDescriptorSets( for (uint32_t i = 0; i < copy_count; ++i) { auto dst_set = p_cds[i].dstSet; auto src_set = p_cds[i].srcSet; - auto src_pair = set_map.find(src_set); - auto dst_pair = set_map.find(dst_set); - if (src_pair == set_map.end()) { + auto src_node = core_validation::getSetNode(dev_data, src_set); + auto dst_node = core_validation::getSetNode(dev_data, dst_set); + if (!src_node) { skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast(src_set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS", "Cannot call vkUpdateDescriptorSets() to copy from descriptor set 0x%" PRIxLEAST64 " that has not been allocated.", reinterpret_cast(src_set)); - } else if (dst_pair == set_map.end()) { + } else if (!dst_node) { skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast(dst_set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS", "Cannot call vkUpdateDescriptorSets() to copy to descriptor set 0x%" PRIxLEAST64 @@ -886,7 +887,7 @@ bool cvdescriptorset::ValidateUpdateDescriptorSets( reinterpret_cast(dst_set)); } else { std::string error_str; - if (!dst_pair->second->ValidateCopyUpdate(report_data, &p_cds[i], src_pair->second, &error_str)) { + if (!dst_node->ValidateCopyUpdate(report_data, &p_cds[i], src_node, &error_str)) { skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast(dst_set), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS", @@ -904,26 +905,26 @@ bool cvdescriptorset::ValidateUpdateDescriptorSets( // with the same set of updates. // This is split from the validate code to allow validation prior to calling down the chain, and then update after // calling down the chain. -void cvdescriptorset::PerformUpdateDescriptorSets( - const std::unordered_map &set_map, uint32_t write_count, - const VkWriteDescriptorSet *p_wds, uint32_t copy_count, const VkCopyDescriptorSet *p_cds) { +void cvdescriptorset::PerformUpdateDescriptorSets(const core_validation::layer_data *dev_data, uint32_t write_count, + const VkWriteDescriptorSet *p_wds, uint32_t copy_count, + const VkCopyDescriptorSet *p_cds) { // Write updates first uint32_t i = 0; for (i = 0; i < write_count; ++i) { auto dest_set = p_wds[i].dstSet; - auto set_pair = set_map.find(dest_set); - if (set_pair != set_map.end()) { - set_pair->second->PerformWriteUpdate(&p_wds[i]); + auto set_node = core_validation::getSetNode(dev_data, dest_set); + if (set_node) { + set_node->PerformWriteUpdate(&p_wds[i]); } } // Now copy updates for (i = 0; i < copy_count; ++i) { auto dst_set = p_cds[i].dstSet; auto src_set = p_cds[i].srcSet; - auto src_pair = set_map.find(src_set); - auto dst_pair = set_map.find(dst_set); - if (src_pair != set_map.end() && dst_pair != set_map.end()) { - dst_pair->second->PerformCopyUpdate(&p_cds[i], src_pair->second); + auto src_node = core_validation::getSetNode(dev_data, src_set); + auto dst_node = core_validation::getSetNode(dev_data, dst_set); + if (src_node && dst_node) { + dst_node->PerformCopyUpdate(&p_cds[i], src_node); } } } @@ -1286,7 +1287,7 @@ bool cvdescriptorset::ValidateAllocateDescriptorSets( void cvdescriptorset::PerformAllocateDescriptorSets( const VkDescriptorSetAllocateInfo *p_alloc_info, const VkDescriptorSet *descriptor_sets, const AllocateDescriptorSetsData *ds_data, std::unordered_map *pool_map, - std::unordered_map *set_map, + std::unordered_map *set_map, const core_validation::layer_data *dev_data, const std::unordered_map &layout_map, const std::unordered_map &buffer_map, const std::unordered_map &mem_obj_map, diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index bb5907ca..b11b5f87 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -253,30 +253,27 @@ struct AllocateDescriptorSetsData { }; // Helper functions for descriptor set functions that cross multiple sets // "Validate" will make sure an update is ok without actually performing it -bool ValidateUpdateDescriptorSets(const debug_report_data *, - const std::unordered_map &, uint32_t, +bool ValidateUpdateDescriptorSets(const debug_report_data *, const core_validation::layer_data *, uint32_t, const VkWriteDescriptorSet *, uint32_t, const VkCopyDescriptorSet *); // "Perform" does the update with the assumption that ValidateUpdateDescriptorSets() has passed for the given update -void PerformUpdateDescriptorSets(const std::unordered_map &, uint32_t, - const VkWriteDescriptorSet *, uint32_t, const VkCopyDescriptorSet *); +void PerformUpdateDescriptorSets(const core_validation::layer_data *, uint32_t, const VkWriteDescriptorSet *, uint32_t, + const VkCopyDescriptorSet *); // Validate that Allocation state is ok bool ValidateAllocateDescriptorSets(const debug_report_data *, const VkDescriptorSetAllocateInfo *, const std::unordered_map &, const std::unordered_map &, AllocateDescriptorSetsData *); // Update state based on allocating new descriptorsets -void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, const AllocateDescriptorSetsData *, - std::unordered_map *, - std::unordered_map *, - const std::unordered_map &, - const std::unordered_map &, - const std::unordered_map &, - const std::unordered_map &, - const std::unordered_map> &, - const std::unordered_map &, - const std::unordered_map &, - const std::unordered_map &, - const std::unordered_map &); +void PerformAllocateDescriptorSets( + const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, const AllocateDescriptorSetsData *, + std::unordered_map *, + std::unordered_map *, const core_validation::layer_data *, + const std::unordered_map &, + const std::unordered_map &, const std::unordered_map &, + const std::unordered_map &, + const std::unordered_map> &, + const std::unordered_map &, const std::unordered_map &, + const std::unordered_map &, const std::unordered_map &); /* * DescriptorSet class -- cgit v1.2.3 From e320fe3120d3cceff5ce8559176affaa1ec84922 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 07:46:52 -0600 Subject: layers: Add getBufferNode() helper Move core_validation bufferMap to use unique_ptr to BUFFER_NODE. Perform bufferMap look-ups using getBufferNode() helper function. Update DescriptorSet class to use getBufferNode() helper and store layer_data instead of bufferMap. --- layers/core_validation.cpp | 73 +++++++++++++++++++++++------------------- layers/core_validation_types.h | 11 ++++--- layers/descriptor_sets.cpp | 25 +++++++-------- layers/descriptor_sets.h | 7 ++-- 4 files changed, 61 insertions(+), 55 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 66d3abd2..5f60da49 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -127,7 +127,7 @@ struct layer_data { unordered_map imageViewMap; unordered_map imageMap; unordered_map bufferViewMap; - unordered_map bufferMap; + unordered_map> bufferMap; unordered_map pipelineMap; unordered_map commandPoolMap; unordered_map descriptorPoolMap; @@ -261,6 +261,15 @@ struct shader_module { // TODO : This can be much smarter, using separate locks for separate global data static std::mutex global_lock; +// Return buffer node ptr for specified buffer or else NULL +BUFFER_NODE *getBufferNode(const layer_data *my_data, const VkBuffer buffer) { + auto buff_it = my_data->bufferMap.find(buffer); + if (buff_it == my_data->bufferMap.end()) { + return nullptr; + } + return buff_it->second.get(); +} + static VkDeviceMemory *get_object_mem_binding(layer_data *my_data, uint64_t handle, VkDebugReportObjectTypeEXT type) { switch (type) { case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { @@ -270,9 +279,9 @@ static VkDeviceMemory *get_object_mem_binding(layer_data *my_data, uint64_t hand break; } case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: { - auto it = my_data->bufferMap.find(VkBuffer(handle)); - if (it != my_data->bufferMap.end()) - return &(*it).second.mem; + auto buff_node = getBufferNode(my_data, VkBuffer(handle)); + if (buff_node) + return &buff_node->mem; break; } default: @@ -326,9 +335,9 @@ static bool validate_image_usage_flags(layer_data *dev_data, VkImage image, VkFl static bool validate_buffer_usage_flags(layer_data *dev_data, VkBuffer buffer, VkFlags desired, VkBool32 strict, char const *func_name, char const *usage_string) { bool skipCall = false; - auto const buffer_node = dev_data->bufferMap.find(buffer); - if (buffer_node != dev_data->bufferMap.end()) { - skipCall = validate_usage_flags(dev_data, buffer_node->second.createInfo.usage, desired, strict, (uint64_t)buffer, + auto buffer_node = getBufferNode(dev_data, buffer); + if (buffer_node) { + skipCall = validate_usage_flags(dev_data, buffer_node->createInfo.usage, desired, strict, (uint64_t)buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "buffer", func_name, usage_string); } return skipCall; @@ -2623,7 +2632,6 @@ static bool validate_compute_pipeline(debug_report_data *report_data, PIPELINE_N return validate_pipeline_shader_stage(report_data, &pCreateInfo->stage, pPipeline, &module, &entrypoint, enabledFeatures, shaderModuleMap); } - // Return Set node ptr for specified set or else NULL cvdescriptorset::DescriptorSet *getSetNode(const layer_data *my_data, const VkDescriptorSet set) { auto set_it = my_data->setMap.find(set); @@ -4047,13 +4055,13 @@ static bool validateAndIncrementResources(layer_data *my_data, GLOBAL_CB_NODE *p bool skip_call = false; for (auto drawDataElement : pCB->drawData) { for (auto buffer : drawDataElement.buffers) { - auto buffer_data = my_data->bufferMap.find(buffer); - if (buffer_data == my_data->bufferMap.end()) { + auto buffer_node = getBufferNode(my_data, buffer); + if (!buffer_node) { skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t)(buffer), __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", "Cannot submit cmd buffer using deleted buffer 0x%" PRIx64 ".", (uint64_t)(buffer)); } else { - buffer_data->second.in_use.fetch_add(1); + buffer_node->in_use.fetch_add(1); } } } @@ -4132,9 +4140,9 @@ static void decrementResources(layer_data *my_data, VkCommandBuffer cmdBuffer) { GLOBAL_CB_NODE *pCB = getCBNode(my_data, cmdBuffer); for (auto drawDataElement : pCB->drawData) { for (auto buffer : drawDataElement.buffers) { - auto buffer_data = my_data->bufferMap.find(buffer); - if (buffer_data != my_data->bufferMap.end()) { - buffer_data->second.in_use.fetch_sub(1); + auto buffer_node = getBufferNode(my_data, buffer); + if (buffer_node) { + buffer_node->in_use.fetch_sub(1); } } } @@ -4940,13 +4948,13 @@ VKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool static bool validateIdleBuffer(const layer_data *my_data, VkBuffer buffer) { bool skip_call = false; - auto buffer_data = my_data->bufferMap.find(buffer); - if (buffer_data == my_data->bufferMap.end()) { + auto buffer_node = getBufferNode(my_data, buffer); + if (!buffer_node) { skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t)(buffer), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS", "Cannot free buffer 0x%" PRIxLEAST64 " that has not been allocated.", (uint64_t)(buffer)); } else { - if (buffer_data->second.in_use.load()) { + if (buffer_node->in_use.load()) { skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, (uint64_t)(buffer), __LINE__, DRAWSTATE_OBJECT_INUSE, "DS", "Cannot free buffer 0x%" PRIxLEAST64 " that is in use by a command buffer.", (uint64_t)(buffer)); @@ -5015,14 +5023,14 @@ VKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer, lock.lock(); } // Clean up memory binding and range information for buffer - const auto &bufferEntry = dev_data->bufferMap.find(buffer); - if (bufferEntry != dev_data->bufferMap.end()) { - const auto &memEntry = dev_data->memObjMap.find(bufferEntry->second.mem); + auto buff_it = dev_data->bufferMap.find(buffer); + if (buff_it != dev_data->bufferMap.end()) { + const auto &memEntry = dev_data->memObjMap.find(buff_it->second.get()->mem); if (memEntry != dev_data->memObjMap.end()) { - remove_memory_ranges(reinterpret_cast(buffer), bufferEntry->second.mem, memEntry->second.bufferRanges); + remove_memory_ranges(reinterpret_cast(buffer), buff_it->second.get()->mem, memEntry->second.bufferRanges); } clear_object_binding(dev_data, reinterpret_cast(buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT); - dev_data->bufferMap.erase(bufferEntry); + dev_data->bufferMap.erase(buff_it); } } @@ -5075,9 +5083,9 @@ BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceS uint64_t buffer_handle = (uint64_t)(buffer); bool skipCall = set_mem_binding(dev_data, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory"); - auto buffer_node = dev_data->bufferMap.find(buffer); - if (buffer_node != dev_data->bufferMap.end()) { - buffer_node->second.mem = mem; + auto buffer_node = getBufferNode(dev_data, buffer); + if (buffer_node) { + buffer_node->mem = mem; VkMemoryRequirements memRequirements; dev_data->device_dispatch_table->GetBufferMemoryRequirements(device, buffer, &memRequirements); @@ -5101,7 +5109,7 @@ BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceS memoryOffset, memRequirements.alignment); } // Validate device limits alignments - VkBufferUsageFlags usage = dev_data->bufferMap[buffer].createInfo.usage; + VkBufferUsageFlags usage = dev_data->bufferMap[buffer].get()->createInfo.usage; if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) { if (vk_safe_modulo(memoryOffset, dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment) != 0) { skipCall |= @@ -5414,7 +5422,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreat if (VK_SUCCESS == result) { std::lock_guard lock(global_lock); // TODO : This doesn't create deep copy of pQueueFamilyIndices so need to fix that if/when we want that data to be valid - dev_data->bufferMap.insert(std::make_pair(*pBuffer, BUFFER_NODE(pCreateInfo))); + dev_data->bufferMap.insert(std::make_pair(*pBuffer, unique_ptr(new BUFFER_NODE(pCreateInfo)))); } return result; } @@ -5882,7 +5890,7 @@ static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkD // All the updates are contained in a single cvdescriptorset function cvdescriptorset::PerformAllocateDescriptorSets( pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, &dev_data->setMap, dev_data, - dev_data->descriptorSetLayoutMap, dev_data->bufferMap, dev_data->memObjMap, dev_data->bufferViewMap, dev_data->samplerMap, + dev_data->descriptorSetLayoutMap, dev_data->memObjMap, dev_data->bufferViewMap, dev_data->samplerMap, dev_data->imageViewMap, dev_data->imageMap, dev_data->device_extensions.imageToSwapchainMap, dev_data->device_extensions.swapchainMap); } @@ -7697,11 +7705,10 @@ static bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, ui dev_data->phys_dev_properties.queue_family_properties.size()); } - auto buffer_data = dev_data->bufferMap.find(mem_barrier->buffer); - if (buffer_data != dev_data->bufferMap.end()) { - VkDeviceSize buffer_size = (buffer_data->second.createInfo.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO) - ? buffer_data->second.createInfo.size - : 0; + auto buffer_node = getBufferNode(dev_data, mem_barrier->buffer); + if (buffer_node) { + VkDeviceSize buffer_size = + (buffer_node->createInfo.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO) ? buffer_node->createInfo.size : 0; if (mem_barrier->offset >= buffer_size) { skip_call |= log_msg( dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 901c1870..a7b8d921 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -62,11 +62,6 @@ class BASE_NODE { std::atomic_int in_use; }; -namespace core_validation { -struct layer_data; -cvdescriptorset::DescriptorSet *getSetNode(const layer_data *, const VkDescriptorSet); -} - struct DESCRIPTOR_POOL_NODE { VkDescriptorPool pool; uint32_t maxSets; // Max descriptor sets allowed in this pool @@ -484,5 +479,11 @@ struct GLOBAL_CB_NODE : public BASE_NODE { ~GLOBAL_CB_NODE(); }; +// Fwd declarations of layer_data and helpers to look-up state from layer_data maps +namespace core_validation { +struct layer_data; +cvdescriptorset::DescriptorSet *getSetNode(const layer_data *, const VkDescriptorSet); +BUFFER_NODE *getBufferNode(const layer_data *, const VkBuffer); +} #endif // CORE_VALIDATION_TYPES_H_ diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 97e21b5a..060506db 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -264,7 +264,7 @@ cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t : required_descriptors_by_type{}, layout_nodes(count, nullptr) {} cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout, - const std::unordered_map *buffer_map, + const core_validation::layer_data *dev_data, const std::unordered_map *memory_map, const std::unordered_map *buffer_view_map, const std::unordered_map> *sampler_map, @@ -272,7 +272,7 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D const std::unordered_map *image_map, const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map) - : some_update_(false), set_(set), p_layout_(layout), buffer_map_(buffer_map), memory_map_(memory_map), + : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), memory_map_(memory_map), buffer_view_map_(buffer_view_map), sampler_map_(sampler_map), image_view_map_(image_view_map), image_map_(image_map), image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { // Foreach binding, create default descriptors of given type @@ -362,27 +362,27 @@ bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::unordered_set< if (GeneralBuffer == descriptors_[i]->GetClass()) { // Verify that buffers are valid auto buffer = static_cast(descriptors_[i].get())->GetBuffer(); - auto buffer_node = buffer_map_->find(buffer); - if (buffer_node == buffer_map_->end()) { + auto buffer_node = getBufferNode(device_data_, buffer); + if (!buffer_node) { std::stringstream error_str; error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i << " references invalid buffer " << buffer << "."; *error = error_str.str(); return false; } else { - auto mem_entry = memory_map_->find(buffer_node->second.mem); + auto mem_entry = memory_map_->find(buffer_node->mem); if (mem_entry == memory_map_->end()) { std::stringstream error_str; error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i - << " uses buffer " << buffer << " that references invalid memory " - << buffer_node->second.mem << "."; + << " uses buffer " << buffer << " that references invalid memory " << buffer_node->mem + << "."; *error = error_str.str(); return false; } } if (descriptors_[i]->IsDynamic()) { // Validate that dynamic offsets are within the buffer - auto buffer_size = buffer_node->second.createInfo.size; + auto buffer_size = buffer_node->createInfo.size; auto range = static_cast(descriptors_[i].get())->GetRange(); auto desc_offset = static_cast(descriptors_[i].get())->GetOffset(); auto dyn_offset = dynamic_offsets[dyn_offset_index++]; @@ -986,15 +986,15 @@ bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data // If there's an error, update the error string with details and return false, else return true bool cvdescriptorset::DescriptorSet::ValidateBufferUpdate(VkBuffer buffer, VkDescriptorType type, std::string *error) const { // First make sure that buffer is valid - auto buff_it = buffer_map_->find(buffer); - if (buff_it == buffer_map_->end()) { + auto buffer_node = getBufferNode(device_data_, buffer); + if (!buffer_node) { std::stringstream error_str; error_str << "Invalid VkBuffer: " << buffer; *error = error_str.str(); return false; } // Verify that usage bits set correctly for given type - auto usage = buff_it->second.createInfo.usage; + auto usage = buffer_node->createInfo.usage; std::string error_usage_bit; switch (type) { case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: @@ -1289,7 +1289,6 @@ void cvdescriptorset::PerformAllocateDescriptorSets( const AllocateDescriptorSetsData *ds_data, std::unordered_map *pool_map, std::unordered_map *set_map, const core_validation::layer_data *dev_data, const std::unordered_map &layout_map, - const std::unordered_map &buffer_map, const std::unordered_map &mem_obj_map, const std::unordered_map &buffer_view_map, const std::unordered_map> &sampler_map, @@ -1307,7 +1306,7 @@ void cvdescriptorset::PerformAllocateDescriptorSets( * global map and the pool's set. */ for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { - auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], &buffer_map, &mem_obj_map, + auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &mem_obj_map, &buffer_view_map, &sampler_map, &image_view_map, &image_map, &image_to_swapchain_map, &swapchain_map); diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index b11b5f87..479e3471 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -269,8 +269,7 @@ void PerformAllocateDescriptorSets( std::unordered_map *, std::unordered_map *, const core_validation::layer_data *, const std::unordered_map &, - const std::unordered_map &, const std::unordered_map &, - const std::unordered_map &, + const std::unordered_map &, const std::unordered_map &, const std::unordered_map> &, const std::unordered_map &, const std::unordered_map &, const std::unordered_map &, const std::unordered_map &); @@ -296,7 +295,7 @@ void PerformAllocateDescriptorSets( class DescriptorSet : public BASE_NODE { public: using BASE_NODE::in_use; - DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const std::unordered_map *, + DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const core_validation::layer_data *, const std::unordered_map *, const std::unordered_map *, const std::unordered_map> *, @@ -378,7 +377,7 @@ class DescriptorSet : public BASE_NODE { std::unordered_set bound_cmd_buffers_; std::vector> descriptors_; // Ptrs to object containers to verify bound data - const std::unordered_map *buffer_map_; + const core_validation::layer_data *device_data_; const std::unordered_map *memory_map_; const std::unordered_map *buffer_view_map_; const std::unordered_map> *sampler_map_; -- cgit v1.2.3 From dfd84b02f282a762e3ec24e86e75c35813799744 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 08:43:37 -0600 Subject: layers: Update getMemObjInfo helper Standardize core_validation use of getMemObjInfo() and update DescriptorSet class to use it as well. --- layers/core_validation.cpp | 213 +++++++++++++++++++---------------------- layers/core_validation_types.h | 4 + layers/descriptor_sets.cpp | 16 ++-- layers/descriptor_sets.h | 22 ++--- 4 files changed, 121 insertions(+), 134 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 5f60da49..571cb009 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -134,7 +134,7 @@ struct layer_data { unordered_map setMap; unordered_map descriptorSetLayoutMap; unordered_map pipelineLayoutMap; - unordered_map memObjMap; + unordered_map> memObjMap; unordered_map fenceMap; unordered_map queueMap; unordered_map eventMap; @@ -345,30 +345,19 @@ static bool validate_buffer_usage_flags(layer_data *dev_data, VkBuffer buffer, V // Return ptr to info in map container containing mem, or NULL if not found // Calls to this function should be wrapped in mutex -static DEVICE_MEM_INFO *get_mem_obj_info(layer_data *dev_data, const VkDeviceMemory mem) { - auto item = dev_data->memObjMap.find(mem); - if (item != dev_data->memObjMap.end()) { - return &(*item).second; - } else { +DEVICE_MEM_INFO *getMemObjInfo(const layer_data *dev_data, const VkDeviceMemory mem) { + auto mem_it = dev_data->memObjMap.find(mem); + if (mem_it == dev_data->memObjMap.end()) { return NULL; } + return mem_it->second.get(); } static void add_mem_obj_info(layer_data *my_data, void *object, const VkDeviceMemory mem, const VkMemoryAllocateInfo *pAllocateInfo) { assert(object != NULL); - memcpy(&my_data->memObjMap[mem].allocInfo, pAllocateInfo, sizeof(VkMemoryAllocateInfo)); - // TODO: Update for real hardware, actually process allocation info structures - my_data->memObjMap[mem].allocInfo.pNext = NULL; - my_data->memObjMap[mem].object = object; - my_data->memObjMap[mem].mem = mem; - my_data->memObjMap[mem].image = VK_NULL_HANDLE; - my_data->memObjMap[mem].memRange.offset = 0; - my_data->memObjMap[mem].memRange.size = 0; - my_data->memObjMap[mem].pData = 0; - my_data->memObjMap[mem].pDriverData = 0; - my_data->memObjMap[mem].valid = false; + my_data->memObjMap[mem] = unique_ptr(new DEVICE_MEM_INFO(object, mem, pAllocateInfo)); } static bool validate_memory_is_valid(layer_data *dev_data, VkDeviceMemory mem, const char *functionName, @@ -382,7 +371,7 @@ static bool validate_memory_is_valid(layer_data *dev_data, VkDeviceMemory mem, c functionName, (uint64_t)(image)); } } else { - DEVICE_MEM_INFO *pMemObj = get_mem_obj_info(dev_data, mem); + DEVICE_MEM_INFO *pMemObj = getMemObjInfo(dev_data, mem); if (pMemObj && !pMemObj->valid) { return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)(mem), __LINE__, MEMTRACK_INVALID_USAGE_FLAG, "MEM", @@ -400,7 +389,7 @@ static void set_memory_valid(layer_data *dev_data, VkDeviceMemory mem, bool vali image_node->second.valid = valid; } } else { - DEVICE_MEM_INFO *pMemObj = get_mem_obj_info(dev_data, mem); + DEVICE_MEM_INFO *pMemObj = getMemObjInfo(dev_data, mem); if (pMemObj) { pMemObj->valid = valid; } @@ -417,7 +406,7 @@ static bool update_cmd_buf_and_mem_references(layer_data *dev_data, const VkComm if (mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { // First update CB binding in MemObj mini CB list - DEVICE_MEM_INFO *pMemInfo = get_mem_obj_info(dev_data, mem); + DEVICE_MEM_INFO *pMemInfo = getMemObjInfo(dev_data, mem); if (pMemInfo) { pMemInfo->commandBufferBindings.insert(cb); // Now update CBInfo's Mem reference list @@ -435,7 +424,7 @@ static void clear_cmd_buf_and_mem_references(layer_data *dev_data, GLOBAL_CB_NOD if (pCBNode) { if (pCBNode->memObjs.size() > 0) { for (auto mem : pCBNode->memObjs) { - DEVICE_MEM_INFO *pInfo = get_mem_obj_info(dev_data, mem); + DEVICE_MEM_INFO *pInfo = getMemObjInfo(dev_data, mem); if (pInfo) { pInfo->commandBufferBindings.erase(pCBNode->commandBuffer); } @@ -502,7 +491,7 @@ static bool deleteMemObjInfo(layer_data *my_data, void *object, VkDeviceMemory m static bool freeMemObjInfo(layer_data *dev_data, void *object, VkDeviceMemory mem, bool internal) { bool skipCall = false; // Parse global list to find info w/ mem - DEVICE_MEM_INFO *pInfo = get_mem_obj_info(dev_data, mem); + DEVICE_MEM_INFO *pInfo = getMemObjInfo(dev_data, mem); if (pInfo) { if (pInfo->allocInfo.allocationSize == 0 && !internal) { // TODO: Verify against Valid Use section @@ -559,7 +548,7 @@ static bool clear_object_binding(layer_data *dev_data, uint64_t handle, VkDebugR bool skipCall = false; VkDeviceMemory *pMemBinding = get_object_mem_binding(dev_data, handle, type); if (pMemBinding) { - DEVICE_MEM_INFO *pMemObjInfo = get_mem_obj_info(dev_data, *pMemBinding); + DEVICE_MEM_INFO *pMemObjInfo = getMemObjInfo(dev_data, *pMemBinding); // TODO : Make sure this is a reasonable way to reset mem binding *pMemBinding = VK_NULL_HANDLE; if (pMemObjInfo) { @@ -593,9 +582,9 @@ static bool set_mem_binding(layer_data *dev_data, VkDeviceMemory mem, uint64_t h } else { VkDeviceMemory *pMemBinding = get_object_mem_binding(dev_data, handle, type); assert(pMemBinding); - DEVICE_MEM_INFO *pMemInfo = get_mem_obj_info(dev_data, mem); + DEVICE_MEM_INFO *pMemInfo = getMemObjInfo(dev_data, mem); if (pMemInfo) { - DEVICE_MEM_INFO *pPrevBinding = get_mem_obj_info(dev_data, *pMemBinding); + DEVICE_MEM_INFO *pPrevBinding = getMemObjInfo(dev_data, *pMemBinding); if (pPrevBinding != NULL) { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_REBIND_OBJECT, @@ -637,7 +626,7 @@ static bool set_sparse_mem_binding(layer_data *dev_data, VkDeviceMemory mem, uin } else { VkDeviceMemory *pMemBinding = get_object_mem_binding(dev_data, handle, type); assert(pMemBinding); - DEVICE_MEM_INFO *pInfo = get_mem_obj_info(dev_data, mem); + DEVICE_MEM_INFO *pInfo = getMemObjInfo(dev_data, mem); if (pInfo) { pInfo->objBindings.insert({handle, type}); // Need to set mem binding for this object @@ -665,8 +654,6 @@ static bool get_mem_binding_from_object(layer_data *dev_data, const uint64_t han // Print details of MemObjInfo list static void print_mem_list(layer_data *dev_data) { - DEVICE_MEM_INFO *pInfo = NULL; - // Early out if info is not requested if (!(dev_data->report_data->active_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)) { return; @@ -683,17 +670,17 @@ static void print_mem_list(layer_data *dev_data) { return; for (auto ii = dev_data->memObjMap.begin(); ii != dev_data->memObjMap.end(); ++ii) { - pInfo = &(*ii).second; + auto mem_info = (*ii).second.get(); log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, - __LINE__, MEMTRACK_NONE, "MEM", " ===MemObjInfo at 0x%p===", (void *)pInfo); + __LINE__, MEMTRACK_NONE, "MEM", " ===MemObjInfo at 0x%p===", (void *)mem_info); log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, - __LINE__, MEMTRACK_NONE, "MEM", " Mem object: 0x%" PRIxLEAST64, (uint64_t)(pInfo->mem)); + __LINE__, MEMTRACK_NONE, "MEM", " Mem object: 0x%" PRIxLEAST64, (uint64_t)(mem_info->mem)); log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__, MEMTRACK_NONE, "MEM", " Ref Count: " PRINTF_SIZE_T_SPECIFIER, - pInfo->commandBufferBindings.size() + pInfo->objBindings.size()); - if (0 != pInfo->allocInfo.allocationSize) { - string pAllocInfoMsg = vk_print_vkmemoryallocateinfo(&pInfo->allocInfo, "MEM(INFO): "); + mem_info->commandBufferBindings.size() + mem_info->objBindings.size()); + if (0 != mem_info->allocInfo.allocationSize) { + string pAllocInfoMsg = vk_print_vkmemoryallocateinfo(&mem_info->allocInfo, "MEM(INFO): "); log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__, MEMTRACK_NONE, "MEM", " Mem Alloc info:\n%s", pAllocInfoMsg.c_str()); } else { @@ -703,9 +690,9 @@ static void print_mem_list(layer_data *dev_data) { log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__, MEMTRACK_NONE, "MEM", " VK OBJECT Binding list of size " PRINTF_SIZE_T_SPECIFIER " elements:", - pInfo->objBindings.size()); - if (pInfo->objBindings.size() > 0) { - for (auto obj : pInfo->objBindings) { + mem_info->objBindings.size()); + if (mem_info->objBindings.size() > 0) { + for (auto obj : mem_info->objBindings) { log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__, MEMTRACK_NONE, "MEM", " VK OBJECT 0x%" PRIx64, obj.handle); } @@ -714,9 +701,9 @@ static void print_mem_list(layer_data *dev_data) { log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__, MEMTRACK_NONE, "MEM", " VK Command Buffer (CB) binding list of size " PRINTF_SIZE_T_SPECIFIER " elements", - pInfo->commandBufferBindings.size()); - if (pInfo->commandBufferBindings.size() > 0) { - for (auto cb : pInfo->commandBufferBindings) { + mem_info->commandBufferBindings.size()); + if (mem_info->commandBufferBindings.size() > 0) { + for (auto cb : mem_info->commandBufferBindings) { log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, __LINE__, MEMTRACK_NONE, "MEM", " VK CB 0x%p", cb); } @@ -3977,7 +3964,7 @@ VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCall DEVICE_MEM_INFO *pInfo = NULL; if (!dev_data->memObjMap.empty()) { for (auto ii = dev_data->memObjMap.begin(); ii != dev_data->memObjMap.end(); ++ii) { - pInfo = &(*ii).second; + pInfo = (*ii).second.get(); if (pInfo->allocInfo.allocationSize != 0) { // Valid Usage: All child objects created on device must have been destroyed prior to destroying device skipCall |= @@ -4612,8 +4599,9 @@ static bool validateMemRange(layer_data *my_data, VkDeviceMemory mem, VkDeviceSi auto mem_element = my_data->memObjMap.find(mem); if (mem_element != my_data->memObjMap.end()) { + auto mem_info = mem_element->second.get(); // It is an application error to call VkMapMemory on an object that is already mapped - if (mem_element->second.memRange.size != 0) { + if (mem_info->memRange.size != 0) { skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", "VkMapMemory: Attempting to map memory on an already-mapped object 0x%" PRIxLEAST64, (uint64_t)mem); @@ -4621,18 +4609,20 @@ static bool validateMemRange(layer_data *my_data, VkDeviceMemory mem, VkDeviceSi // Validate that offset + size is within object's allocationSize if (size == VK_WHOLE_SIZE) { - if (offset >= mem_element->second.allocInfo.allocationSize) { + if (offset >= mem_info->allocInfo.allocationSize) { skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, - "MEM", "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64, offset, - mem_element->second.allocInfo.allocationSize, mem_element->second.allocInfo.allocationSize); + "MEM", "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 + " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64, + offset, mem_info->allocInfo.allocationSize, mem_info->allocInfo.allocationSize); } } else { - if ((offset + size) > mem_element->second.allocInfo.allocationSize) { - skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, - "MEM", "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64, offset, - size + offset, mem_element->second.allocInfo.allocationSize); + if ((offset + size) > mem_info->allocInfo.allocationSize) { + skipCall = + log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, + (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", + "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64, offset, + size + offset, mem_info->allocInfo.allocationSize); } } } @@ -4640,29 +4630,27 @@ static bool validateMemRange(layer_data *my_data, VkDeviceMemory mem, VkDeviceSi } static void storeMemRanges(layer_data *my_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) { - auto mem_element = my_data->memObjMap.find(mem); - if (mem_element != my_data->memObjMap.end()) { - MemRange new_range; - new_range.offset = offset; - new_range.size = size; - mem_element->second.memRange = new_range; + auto mem_info = getMemObjInfo(my_data, mem); + if (mem_info) { + mem_info->memRange.offset = offset; + mem_info->memRange.size = size; } } static bool deleteMemRanges(layer_data *my_data, VkDeviceMemory mem) { bool skipCall = false; - auto mem_element = my_data->memObjMap.find(mem); - if (mem_element != my_data->memObjMap.end()) { - if (!mem_element->second.memRange.size) { + auto mem_info = getMemObjInfo(my_data, mem); + if (mem_info) { + if (!mem_info->memRange.size) { // Valid Usage: memory must currently be mapped skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM", "Unmapping Memory without memory being mapped: mem obj 0x%" PRIxLEAST64, (uint64_t)mem); } - mem_element->second.memRange.size = 0; - if (mem_element->second.pData) { - free(mem_element->second.pData); - mem_element->second.pData = 0; + mem_info->memRange.size = 0; + if (mem_info->pData) { + free(mem_info->pData); + mem_info->pData = 0; } } return skipCall; @@ -4671,20 +4659,20 @@ static bool deleteMemRanges(layer_data *my_data, VkDeviceMemory mem) { static char NoncoherentMemoryFillValue = 0xb; static void initializeAndTrackMemory(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize size, void **ppData) { - auto mem_element = dev_data->memObjMap.find(mem); - if (mem_element != dev_data->memObjMap.end()) { - mem_element->second.pDriverData = *ppData; - uint32_t index = mem_element->second.allocInfo.memoryTypeIndex; + auto mem_info = getMemObjInfo(dev_data, mem); + if (mem_info) { + mem_info->pDriverData = *ppData; + uint32_t index = mem_info->allocInfo.memoryTypeIndex; if (dev_data->phys_dev_mem_props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) { - mem_element->second.pData = 0; + mem_info->pData = 0; } else { if (size == VK_WHOLE_SIZE) { - size = mem_element->second.allocInfo.allocationSize; + size = mem_info->allocInfo.allocationSize; } size_t convSize = (size_t)(size); - mem_element->second.pData = malloc(2 * convSize); - memset(mem_element->second.pData, NoncoherentMemoryFillValue, 2 * convSize); - *ppData = static_cast(mem_element->second.pData) + (convSize / 2); + mem_info->pData = malloc(2 * convSize); + memset(mem_info->pData, NoncoherentMemoryFillValue, 2 * convSize); + *ppData = static_cast(mem_info->pData) + (convSize / 2); } } } @@ -5025,9 +5013,9 @@ VKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer, // Clean up memory binding and range information for buffer auto buff_it = dev_data->bufferMap.find(buffer); if (buff_it != dev_data->bufferMap.end()) { - const auto &memEntry = dev_data->memObjMap.find(buff_it->second.get()->mem); - if (memEntry != dev_data->memObjMap.end()) { - remove_memory_ranges(reinterpret_cast(buffer), buff_it->second.get()->mem, memEntry->second.bufferRanges); + auto mem_info = getMemObjInfo(dev_data, buff_it->second.get()->mem); + if (mem_info) { + remove_memory_ranges(reinterpret_cast(buffer), buff_it->second.get()->mem, mem_info->bufferRanges); } clear_object_binding(dev_data, reinterpret_cast(buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT); dev_data->bufferMap.erase(buff_it); @@ -5056,11 +5044,11 @@ VKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const Vk const auto &imageEntry = dev_data->imageMap.find(image); if (imageEntry != dev_data->imageMap.end()) { // Clean up memory mapping, bindings and range references for image - auto memEntry = dev_data->memObjMap.find(imageEntry->second.mem); - if (memEntry != dev_data->memObjMap.end()) { - remove_memory_ranges(reinterpret_cast(image), imageEntry->second.mem, memEntry->second.imageRanges); + auto mem_info = getMemObjInfo(dev_data, imageEntry->second.mem); + if (mem_info) { + remove_memory_ranges(reinterpret_cast(image), imageEntry->second.mem, mem_info->imageRanges); clear_object_binding(dev_data, reinterpret_cast(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT); - memEntry->second.image = VK_NULL_HANDLE; + mem_info->image = VK_NULL_HANDLE; } // Remove image from imageMap dev_data->imageMap.erase(imageEntry); @@ -5090,12 +5078,11 @@ BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceS dev_data->device_dispatch_table->GetBufferMemoryRequirements(device, buffer, &memRequirements); // Track and validate bound memory range information - const auto &memEntry = dev_data->memObjMap.find(mem); - if (memEntry != dev_data->memObjMap.end()) { + auto mem_info = getMemObjInfo(dev_data, mem); + if (mem_info) { const MEMORY_RANGE range = - insert_memory_ranges(buffer_handle, mem, memoryOffset, memRequirements, memEntry->second.bufferRanges); - skipCall |= - validate_memory_range(dev_data, memEntry->second.imageRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT); + insert_memory_ranges(buffer_handle, mem, memoryOffset, memRequirements, mem_info->bufferRanges); + skipCall |= validate_memory_range(dev_data, mem_info->imageRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT); } // Validate memory requirements alignment @@ -5890,9 +5877,8 @@ static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkD // All the updates are contained in a single cvdescriptorset function cvdescriptorset::PerformAllocateDescriptorSets( pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, &dev_data->setMap, dev_data, - dev_data->descriptorSetLayoutMap, dev_data->memObjMap, dev_data->bufferViewMap, dev_data->samplerMap, - dev_data->imageViewMap, dev_data->imageMap, dev_data->device_extensions.imageToSwapchainMap, - dev_data->device_extensions.swapchainMap); + dev_data->descriptorSetLayoutMap, dev_data->bufferViewMap, dev_data->samplerMap, dev_data->imageViewMap, dev_data->imageMap, + dev_data->device_extensions.imageToSwapchainMap, dev_data->device_extensions.swapchainMap); } VKAPI_ATTR VkResult VKAPI_CALL @@ -9284,10 +9270,10 @@ CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount, static bool ValidateMapImageLayouts(VkDevice device, VkDeviceMemory mem) { bool skip_call = false; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); - auto mem_data = dev_data->memObjMap.find(mem); - if ((mem_data != dev_data->memObjMap.end()) && (mem_data->second.image != VK_NULL_HANDLE)) { + auto mem_info = getMemObjInfo(dev_data, mem); + if ((mem_info) && (mem_info->image != VK_NULL_HANDLE)) { std::vector layouts; - if (FindLayouts(dev_data, mem_data->second.image, layouts)) { + if (FindLayouts(dev_data, mem_info->image, layouts)) { for (auto layout : layouts) { if (layout != VK_IMAGE_LAYOUT_PREINITIALIZED && layout != VK_IMAGE_LAYOUT_GENERAL) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, @@ -9309,7 +9295,7 @@ MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; std::unique_lock lock(global_lock); #if MTMERGESOURCE - DEVICE_MEM_INFO *pMemObj = get_mem_obj_info(dev_data, mem); + DEVICE_MEM_INFO *pMemObj = getMemObjInfo(dev_data, mem); if (pMemObj) { pMemObj->valid = true; if ((dev_data->phys_dev_mem_props.memoryTypes[pMemObj->allocInfo.memoryTypeIndex].propertyFlags & @@ -9355,20 +9341,20 @@ static bool validateMemoryIsMapped(layer_data *my_data, const char *funcName, ui const VkMappedMemoryRange *pMemRanges) { bool skipCall = false; for (uint32_t i = 0; i < memRangeCount; ++i) { - auto mem_element = my_data->memObjMap.find(pMemRanges[i].memory); - if (mem_element != my_data->memObjMap.end()) { - if (mem_element->second.memRange.offset > pMemRanges[i].offset) { - skipCall |= log_msg( - my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, - (uint64_t)pMemRanges[i].memory, __LINE__, MEMTRACK_INVALID_MAP, "MEM", - "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER ") is less than Memory Object's offset " - "(" PRINTF_SIZE_T_SPECIFIER ").", - funcName, static_cast(pMemRanges[i].offset), static_cast(mem_element->second.memRange.offset)); + auto mem_info = getMemObjInfo(my_data, pMemRanges[i].memory); + if (mem_info) { + if (mem_info->memRange.offset > pMemRanges[i].offset) { + skipCall |= + log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, + (uint64_t)pMemRanges[i].memory, __LINE__, MEMTRACK_INVALID_MAP, "MEM", + "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER ") is less than Memory Object's offset " + "(" PRINTF_SIZE_T_SPECIFIER ").", + funcName, static_cast(pMemRanges[i].offset), static_cast(mem_info->memRange.offset)); } const uint64_t my_dataTerminus = - (mem_element->second.memRange.size == VK_WHOLE_SIZE) ? mem_element->second.allocInfo.allocationSize : - (mem_element->second.memRange.offset + mem_element->second.memRange.size); + (mem_info->memRange.size == VK_WHOLE_SIZE) ? mem_info->allocInfo.allocationSize : + (mem_info->memRange.offset + mem_info->memRange.size); if (pMemRanges[i].size != VK_WHOLE_SIZE && (my_dataTerminus < (pMemRanges[i].offset + pMemRanges[i].size))) { skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pMemRanges[i].memory, __LINE__, @@ -9387,12 +9373,12 @@ static bool validateAndCopyNoncoherentMemoryToDriver(layer_data *my_data, uint32 const VkMappedMemoryRange *pMemRanges) { bool skipCall = false; for (uint32_t i = 0; i < memRangeCount; ++i) { - auto mem_element = my_data->memObjMap.find(pMemRanges[i].memory); - if (mem_element != my_data->memObjMap.end()) { - if (mem_element->second.pData) { - VkDeviceSize size = mem_element->second.memRange.size; + auto mem_info = getMemObjInfo(my_data, pMemRanges[i].memory); + if (mem_info) { + if (mem_info->pData) { + VkDeviceSize size = mem_info->memRange.size; VkDeviceSize half_size = (size / 2); - char *data = static_cast(mem_element->second.pData); + char *data = static_cast(mem_info->pData); for (auto j = 0; j < half_size; ++j) { if (data[j] != NoncoherentMemoryFillValue) { skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, @@ -9409,7 +9395,7 @@ static bool validateAndCopyNoncoherentMemoryToDriver(layer_data *my_data, uint32 (uint64_t)pMemRanges[i].memory); } } - memcpy(mem_element->second.pDriverData, static_cast(data + (size_t)(half_size)), (size_t)(size)); + memcpy(mem_info->pDriverData, static_cast(data + (size_t)(half_size)), (size_t)(size)); } } } @@ -9463,12 +9449,11 @@ VKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, V lock.lock(); // Track and validate bound memory range information - const auto &memEntry = dev_data->memObjMap.find(mem); - if (memEntry != dev_data->memObjMap.end()) { + auto mem_info = getMemObjInfo(dev_data, mem); + if (mem_info) { const MEMORY_RANGE range = - insert_memory_ranges(image_handle, mem, memoryOffset, memRequirements, memEntry->second.imageRanges); - skipCall |= - validate_memory_range(dev_data, memEntry->second.bufferRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT); + insert_memory_ranges(image_handle, mem, memoryOffset, memRequirements, mem_info->imageRanges); + skipCall |= validate_memory_range(dev_data, mem_info->bufferRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT); } print_mem_list(dev_data); @@ -9476,7 +9461,7 @@ VKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, V if (!skipCall) { result = dev_data->device_dispatch_table->BindImageMemory(device, image, mem, memoryOffset); lock.lock(); - dev_data->memObjMap[mem].image = image; + dev_data->memObjMap[mem].get()->image = image; image_node->second.mem = mem; image_node->second.memOffset = memoryOffset; image_node->second.memSize = memRequirements.size; diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index a7b8d921..1516f41b 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -174,6 +174,9 @@ struct DEVICE_MEM_INFO { VkImage image; // If memory is bound to image, this will have VkImage handle, else VK_NULL_HANDLE MemRange memRange; void *pData, *pDriverData; + DEVICE_MEM_INFO(void *disp_object, const VkDeviceMemory in_mem, const VkMemoryAllocateInfo *p_alloc_info) + : object(disp_object), valid(false), mem(in_mem), allocInfo(*p_alloc_info), image(VK_NULL_HANDLE), memRange{}, pData(0), + pDriverData(0){}; }; class SWAPCHAIN_NODE { @@ -484,6 +487,7 @@ namespace core_validation { struct layer_data; cvdescriptorset::DescriptorSet *getSetNode(const layer_data *, const VkDescriptorSet); BUFFER_NODE *getBufferNode(const layer_data *, const VkBuffer); +DEVICE_MEM_INFO *getMemObjInfo(const layer_data *, const VkDeviceMemory); } #endif // CORE_VALIDATION_TYPES_H_ diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 060506db..96133c5e 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -265,15 +265,14 @@ cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout, const core_validation::layer_data *dev_data, - const std::unordered_map *memory_map, const std::unordered_map *buffer_view_map, const std::unordered_map> *sampler_map, const std::unordered_map *image_view_map, const std::unordered_map *image_map, const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map) - : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), memory_map_(memory_map), - buffer_view_map_(buffer_view_map), sampler_map_(sampler_map), image_view_map_(image_view_map), image_map_(image_map), + : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), buffer_view_map_(buffer_view_map), + sampler_map_(sampler_map), image_view_map_(image_view_map), image_map_(image_map), image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { // Foreach binding, create default descriptors of given type for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) { @@ -370,8 +369,8 @@ bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::unordered_set< *error = error_str.str(); return false; } else { - auto mem_entry = memory_map_->find(buffer_node->mem); - if (mem_entry == memory_map_->end()) { + auto mem_entry = getMemObjInfo(device_data_, buffer_node->mem); + if (!mem_entry) { std::stringstream error_str; error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i << " uses buffer " << buffer << " that references invalid memory " << buffer_node->mem @@ -1289,7 +1288,6 @@ void cvdescriptorset::PerformAllocateDescriptorSets( const AllocateDescriptorSetsData *ds_data, std::unordered_map *pool_map, std::unordered_map *set_map, const core_validation::layer_data *dev_data, const std::unordered_map &layout_map, - const std::unordered_map &mem_obj_map, const std::unordered_map &buffer_view_map, const std::unordered_map> &sampler_map, const std::unordered_map &image_view_map, @@ -1306,9 +1304,9 @@ void cvdescriptorset::PerformAllocateDescriptorSets( * global map and the pool's set. */ for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { - auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &mem_obj_map, - &buffer_view_map, &sampler_map, &image_view_map, &image_map, - &image_to_swapchain_map, &swapchain_map); + auto new_ds = + new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &buffer_view_map, + &sampler_map, &image_view_map, &image_map, &image_to_swapchain_map, &swapchain_map); pool_state->sets.insert(new_ds); new_ds->in_use.store(0); diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 479e3471..193ef75e 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -264,15 +264,17 @@ bool ValidateAllocateDescriptorSets(const debug_report_data *, const VkDescripto const std::unordered_map &, AllocateDescriptorSetsData *); // Update state based on allocating new descriptorsets -void PerformAllocateDescriptorSets( - const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, const AllocateDescriptorSetsData *, - std::unordered_map *, - std::unordered_map *, const core_validation::layer_data *, - const std::unordered_map &, - const std::unordered_map &, const std::unordered_map &, - const std::unordered_map> &, - const std::unordered_map &, const std::unordered_map &, - const std::unordered_map &, const std::unordered_map &); +void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, const AllocateDescriptorSetsData *, + std::unordered_map *, + std::unordered_map *, + const core_validation::layer_data *, + const std::unordered_map &, + const std::unordered_map &, + const std::unordered_map> &, + const std::unordered_map &, + const std::unordered_map &, + const std::unordered_map &, + const std::unordered_map &); /* * DescriptorSet class @@ -296,7 +298,6 @@ class DescriptorSet : public BASE_NODE { public: using BASE_NODE::in_use; DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const core_validation::layer_data *, - const std::unordered_map *, const std::unordered_map *, const std::unordered_map> *, const std::unordered_map *, const std::unordered_map *, @@ -378,7 +379,6 @@ class DescriptorSet : public BASE_NODE { std::vector> descriptors_; // Ptrs to object containers to verify bound data const core_validation::layer_data *device_data_; - const std::unordered_map *memory_map_; const std::unordered_map *buffer_view_map_; const std::unordered_map> *sampler_map_; const std::unordered_map *image_view_map_; -- cgit v1.2.3 From f6a1232fbcbfe7af4974f70b0014c8b72a362633 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 09:43:11 -0600 Subject: layers: Add getBufferViewInfo() helper Add helper function to core_validation for bufferViewMap look-ups and use the helper in DescriptorSet class. --- layers/core_validation.cpp | 14 +++++++++++--- layers/core_validation_types.h | 1 + layers/descriptor_sets.cpp | 31 ++++++++++++++----------------- layers/descriptor_sets.h | 2 -- 4 files changed, 26 insertions(+), 22 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 571cb009..844503dc 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -126,7 +126,7 @@ struct layer_data { unordered_map> samplerMap; unordered_map imageViewMap; unordered_map imageMap; - unordered_map bufferViewMap; + unordered_map> bufferViewMap; unordered_map> bufferMap; unordered_map pipelineMap; unordered_map commandPoolMap; @@ -269,6 +269,14 @@ BUFFER_NODE *getBufferNode(const layer_data *my_data, const VkBuffer buffer) { } return buff_it->second.get(); } +// Return buffer node ptr for specified buffer or else NULL +VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *my_data, const VkBufferView buffer_view) { + auto bv_it = my_data->bufferViewMap.find(buffer_view); + if (bv_it == my_data->bufferViewMap.end()) { + return nullptr; + } + return bv_it->second.get(); +} static VkDeviceMemory *get_object_mem_binding(layer_data *my_data, uint64_t handle, VkDebugReportObjectTypeEXT type) { switch (type) { @@ -5420,7 +5428,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferV VkResult result = dev_data->device_dispatch_table->CreateBufferView(device, pCreateInfo, pAllocator, pView); if (VK_SUCCESS == result) { std::lock_guard lock(global_lock); - dev_data->bufferViewMap[*pView] = VkBufferViewCreateInfo(*pCreateInfo); + dev_data->bufferViewMap[*pView] = unique_ptr(new VkBufferViewCreateInfo(*pCreateInfo)); // In order to create a valid buffer view, the buffer must have been created with at least one of the // following flags: UNIFORM_TEXEL_BUFFER_BIT or STORAGE_TEXEL_BUFFER_BIT validate_buffer_usage_flags(dev_data, pCreateInfo->buffer, @@ -5877,7 +5885,7 @@ static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkD // All the updates are contained in a single cvdescriptorset function cvdescriptorset::PerformAllocateDescriptorSets( pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, &dev_data->setMap, dev_data, - dev_data->descriptorSetLayoutMap, dev_data->bufferViewMap, dev_data->samplerMap, dev_data->imageViewMap, dev_data->imageMap, + dev_data->descriptorSetLayoutMap, dev_data->samplerMap, dev_data->imageViewMap, dev_data->imageMap, dev_data->device_extensions.imageToSwapchainMap, dev_data->device_extensions.swapchainMap); } diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 1516f41b..fd71b61f 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -488,6 +488,7 @@ struct layer_data; cvdescriptorset::DescriptorSet *getSetNode(const layer_data *, const VkDescriptorSet); BUFFER_NODE *getBufferNode(const layer_data *, const VkBuffer); DEVICE_MEM_INFO *getMemObjInfo(const layer_data *, const VkDeviceMemory); +VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *, const VkBufferView); } #endif // CORE_VALIDATION_TYPES_H_ diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 96133c5e..193a8b74 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -265,15 +265,14 @@ cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout, const core_validation::layer_data *dev_data, - const std::unordered_map *buffer_view_map, const std::unordered_map> *sampler_map, const std::unordered_map *image_view_map, const std::unordered_map *image_map, const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map) - : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), buffer_view_map_(buffer_view_map), - sampler_map_(sampler_map), image_view_map_(image_view_map), image_map_(image_map), - image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { + : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), sampler_map_(sampler_map), + image_view_map_(image_view_map), image_map_(image_map), image_to_swapchain_map_(image_to_swapchain_map), + swapchain_map_(swapchain_map) { // Foreach binding, create default descriptors of given type for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) { auto type = p_layout_->GetTypeFromIndex(i); @@ -434,9 +433,9 @@ uint32_t cvdescriptorset::DescriptorSet::GetStorageUpdates(const std::unordered_ for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) { if (descriptors_[start_idx + i]->updated) { auto bufferview = static_cast(descriptors_[start_idx + i].get())->GetBufferView(); - const auto &buff_pair = buffer_view_map_->find(bufferview); - if (buff_pair != buffer_view_map_->end()) { - buffer_set->insert(buff_pair->second.buffer); + auto bv_info = getBufferViewInfo(device_data_, bufferview); + if (bv_info) { + buffer_set->insert(bv_info->buffer); num_updates++; } } @@ -1085,14 +1084,14 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: { for (uint32_t di = 0; di < update->descriptorCount; ++di) { auto buffer_view = update->pTexelBufferView[di]; - auto buffer_view_it = buffer_view_map_->find(buffer_view); - if (buffer_view_it == buffer_view_map_->end()) { + auto bv_info = getBufferViewInfo(device_data_, buffer_view); + if (!bv_info) { std::stringstream error_str; error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view; *error = error_str.str(); return false; } - auto buffer = buffer_view_it->second.buffer; + auto buffer = bv_info->buffer; if (!ValidateBufferUpdate(buffer, update->descriptorType, error)) { std::stringstream error_str; error_str << "Attempted write update to texel buffer descriptor failed due to: " << error->c_str(); @@ -1189,14 +1188,14 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri case TexelBuffer: { for (uint32_t di = 0; di < update->descriptorCount; ++di) { auto buffer_view = static_cast(src_set->descriptors_[index + di].get())->GetBufferView(); - auto bv_it = buffer_view_map_->find(buffer_view); - if (bv_it == buffer_view_map_->end()) { + auto bv_info = getBufferViewInfo(device_data_, buffer_view); + if (!bv_info) { std::stringstream error_str; error_str << "Attempted copy update to texel buffer descriptor with invalid buffer view: " << buffer_view; *error = error_str.str(); return false; } - auto buffer = bv_it->second.buffer; + auto buffer = bv_info->buffer; if (!ValidateBufferUpdate(buffer, type, error)) { std::stringstream error_str; error_str << "Attempted copy update to texel buffer descriptor failed due to: " << error->c_str(); @@ -1288,7 +1287,6 @@ void cvdescriptorset::PerformAllocateDescriptorSets( const AllocateDescriptorSetsData *ds_data, std::unordered_map *pool_map, std::unordered_map *set_map, const core_validation::layer_data *dev_data, const std::unordered_map &layout_map, - const std::unordered_map &buffer_view_map, const std::unordered_map> &sampler_map, const std::unordered_map &image_view_map, const std::unordered_map &image_map, @@ -1304,9 +1302,8 @@ void cvdescriptorset::PerformAllocateDescriptorSets( * global map and the pool's set. */ for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { - auto new_ds = - new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &buffer_view_map, - &sampler_map, &image_view_map, &image_map, &image_to_swapchain_map, &swapchain_map); + auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &sampler_map, + &image_view_map, &image_map, &image_to_swapchain_map, &swapchain_map); pool_state->sets.insert(new_ds); new_ds->in_use.store(0); diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 193ef75e..fcb409cc 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -269,7 +269,6 @@ void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const Vk std::unordered_map *, const core_validation::layer_data *, const std::unordered_map &, - const std::unordered_map &, const std::unordered_map> &, const std::unordered_map &, const std::unordered_map &, @@ -298,7 +297,6 @@ class DescriptorSet : public BASE_NODE { public: using BASE_NODE::in_use; DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const core_validation::layer_data *, - const std::unordered_map *, const std::unordered_map> *, const std::unordered_map *, const std::unordered_map *, const std::unordered_map *, -- cgit v1.2.3 From 50414339385babe11cfdf08b2b4d3bdd3ee73277 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 10:08:53 -0600 Subject: layers: Add getSamplerNode() helper Kill sampler_map_ in DescriptorSet and add getSamplerNode() helper and use it instead. --- layers/core_validation.cpp | 10 +++++++++- layers/core_validation_types.h | 1 + layers/descriptor_sets.cpp | 24 ++++++++++-------------- layers/descriptor_sets.h | 6 +----- 4 files changed, 21 insertions(+), 20 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 844503dc..2f4a5e82 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -261,6 +261,14 @@ struct shader_module { // TODO : This can be much smarter, using separate locks for separate global data static std::mutex global_lock; +// Return sampler node ptr for specified sampler or else NULL +SAMPLER_NODE *getSamplerNode(const layer_data *my_data, const VkSampler sampler) { + auto sampler_it = my_data->samplerMap.find(sampler); + if (sampler_it == my_data->samplerMap.end()) { + return nullptr; + } + return sampler_it->second.get(); +} // Return buffer node ptr for specified buffer or else NULL BUFFER_NODE *getBufferNode(const layer_data *my_data, const VkBuffer buffer) { auto buff_it = my_data->bufferMap.find(buffer); @@ -5885,7 +5893,7 @@ static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkD // All the updates are contained in a single cvdescriptorset function cvdescriptorset::PerformAllocateDescriptorSets( pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, &dev_data->setMap, dev_data, - dev_data->descriptorSetLayoutMap, dev_data->samplerMap, dev_data->imageViewMap, dev_data->imageMap, + dev_data->descriptorSetLayoutMap, dev_data->imageViewMap, dev_data->imageMap, dev_data->device_extensions.imageToSwapchainMap, dev_data->device_extensions.swapchainMap); } diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index fd71b61f..e915ade7 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -489,6 +489,7 @@ cvdescriptorset::DescriptorSet *getSetNode(const layer_data *, const VkDescripto BUFFER_NODE *getBufferNode(const layer_data *, const VkBuffer); DEVICE_MEM_INFO *getMemObjInfo(const layer_data *, const VkDeviceMemory); VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *, const VkBufferView); +SAMPLER_NODE *getSamplerNode(const layer_data *, const VkSampler); } #endif // CORE_VALIDATION_TYPES_H_ diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 193a8b74..ed25030f 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -265,14 +265,12 @@ cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout, const core_validation::layer_data *dev_data, - const std::unordered_map> *sampler_map, const std::unordered_map *image_view_map, const std::unordered_map *image_map, const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map) - : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), sampler_map_(sampler_map), - image_view_map_(image_view_map), image_map_(image_map), image_to_swapchain_map_(image_to_swapchain_map), - swapchain_map_(swapchain_map) { + : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), image_view_map_(image_view_map), + image_map_(image_map), image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { // Foreach binding, create default descriptors of given type for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) { auto type = p_layout_->GetTypeFromIndex(i); @@ -580,10 +578,9 @@ cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const VkSampler *immut) : updated = true; } } - -bool cvdescriptorset::ValidateSampler(const VkSampler sampler, - const std::unordered_map> *sampler_map) { - return (sampler_map->count(sampler) != 0); +// Validate given sampler. Currently this only checks to make sure it exists in the samplerMap +bool cvdescriptorset::ValidateSampler(const VkSampler sampler, const core_validation::layer_data *dev_data) { + return (getSamplerNode(dev_data, sampler) != nullptr); } bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type, @@ -1051,7 +1048,7 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc case VK_DESCRIPTOR_TYPE_SAMPLER: { for (uint32_t di = 0; di < update->descriptorCount; ++di) { if (!descriptors_[index + di].get()->IsImmutableSampler()) { - if (!ValidateSampler(update->pImageInfo[di].sampler, sampler_map_)) { + if (!ValidateSampler(update->pImageInfo[di].sampler, device_data_)) { std::stringstream error_str; error_str << "Attempted write update to sampler descriptor with invalid sampler: " << update->pImageInfo[di].sampler << "."; @@ -1131,7 +1128,7 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri for (uint32_t di = 0; di < update->descriptorCount; ++di) { if (!src_set->descriptors_[index + di]->IsImmutableSampler()) { auto update_sampler = static_cast(src_set->descriptors_[index + di].get())->GetSampler(); - if (!ValidateSampler(update_sampler, sampler_map_)) { + if (!ValidateSampler(update_sampler, device_data_)) { std::stringstream error_str; error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << "."; *error = error_str.str(); @@ -1149,7 +1146,7 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri // First validate sampler if (!img_samp_desc->IsImmutableSampler()) { auto update_sampler = img_samp_desc->GetSampler(); - if (!ValidateSampler(update_sampler, sampler_map_)) { + if (!ValidateSampler(update_sampler, device_data_)) { std::stringstream error_str; error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << "."; *error = error_str.str(); @@ -1287,7 +1284,6 @@ void cvdescriptorset::PerformAllocateDescriptorSets( const AllocateDescriptorSetsData *ds_data, std::unordered_map *pool_map, std::unordered_map *set_map, const core_validation::layer_data *dev_data, const std::unordered_map &layout_map, - const std::unordered_map> &sampler_map, const std::unordered_map &image_view_map, const std::unordered_map &image_map, const std::unordered_map &image_to_swapchain_map, @@ -1302,8 +1298,8 @@ void cvdescriptorset::PerformAllocateDescriptorSets( * global map and the pool's set. */ for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { - auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &sampler_map, - &image_view_map, &image_map, &image_to_swapchain_map, &swapchain_map); + auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &image_view_map, + &image_map, &image_to_swapchain_map, &swapchain_map); pool_state->sets.insert(new_ds); new_ds->in_use.store(0); diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index fcb409cc..eddbff32 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -160,7 +160,7 @@ class Descriptor { }; // Shared helper functions - These are useful because the shared sampler image descriptor type // performs common functions with both sampler and image descriptors so they can share their common functions -bool ValidateSampler(const VkSampler, const std::unordered_map> *); +bool ValidateSampler(const VkSampler, const core_validation::layer_data *); bool ValidateImageUpdate(VkImageView, VkImageLayout, VkDescriptorType, const std::unordered_map *, const std::unordered_map *, const std::unordered_map *, @@ -269,7 +269,6 @@ void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const Vk std::unordered_map *, const core_validation::layer_data *, const std::unordered_map &, - const std::unordered_map> &, const std::unordered_map &, const std::unordered_map &, const std::unordered_map &, @@ -297,7 +296,6 @@ class DescriptorSet : public BASE_NODE { public: using BASE_NODE::in_use; DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const core_validation::layer_data *, - const std::unordered_map> *, const std::unordered_map *, const std::unordered_map *, const std::unordered_map *, const std::unordered_map *); @@ -377,8 +375,6 @@ class DescriptorSet : public BASE_NODE { std::vector> descriptors_; // Ptrs to object containers to verify bound data const core_validation::layer_data *device_data_; - const std::unordered_map *buffer_view_map_; - const std::unordered_map> *sampler_map_; const std::unordered_map *image_view_map_; // TODO : For next 3 maps all we really need (currently) is an image to format mapping const std::unordered_map *image_map_; -- cgit v1.2.3 From 402540ef8a1ea7df6a48130409714cddcb803d07 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 10:54:09 -0600 Subject: layers: Add getImageViewData() helper Switch imageViewMap to store unique_ptrs. Add getImageViewDate() helper to core_validation and update DescriptorSet to use it. --- layers/core_validation.cpp | 79 +++++++++++++++++++++++------------------- layers/core_validation_types.h | 1 + layers/descriptor_sets.cpp | 28 +++++++-------- layers/descriptor_sets.h | 8 ++--- 4 files changed, 59 insertions(+), 57 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 2f4a5e82..e7aa6dbf 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -124,7 +124,7 @@ struct layer_data { unordered_set globalInFlightCmdBuffers; // Layer specific data unordered_map> samplerMap; - unordered_map imageViewMap; + unordered_map> imageViewMap; unordered_map imageMap; unordered_map> bufferViewMap; unordered_map> bufferMap; @@ -261,18 +261,26 @@ struct shader_module { // TODO : This can be much smarter, using separate locks for separate global data static std::mutex global_lock; +// Return ImageViewCreateInfo ptr for specified imageView or else NULL +VkImageViewCreateInfo *getImageViewData(const layer_data *dev_data, const VkImageView image_view) { + auto iv_it = dev_data->imageViewMap.find(image_view); + if (iv_it == dev_data->imageViewMap.end()) { + return nullptr; + } + return iv_it->second.get(); +} // Return sampler node ptr for specified sampler or else NULL -SAMPLER_NODE *getSamplerNode(const layer_data *my_data, const VkSampler sampler) { - auto sampler_it = my_data->samplerMap.find(sampler); - if (sampler_it == my_data->samplerMap.end()) { +SAMPLER_NODE *getSamplerNode(const layer_data *dev_data, const VkSampler sampler) { + auto sampler_it = dev_data->samplerMap.find(sampler); + if (sampler_it == dev_data->samplerMap.end()) { return nullptr; } return sampler_it->second.get(); } // Return buffer node ptr for specified buffer or else NULL -BUFFER_NODE *getBufferNode(const layer_data *my_data, const VkBuffer buffer) { - auto buff_it = my_data->bufferMap.find(buffer); - if (buff_it == my_data->bufferMap.end()) { +BUFFER_NODE *getBufferNode(const layer_data *dev_data, const VkBuffer buffer) { + auto buff_it = dev_data->bufferMap.find(buffer); + if (buff_it == dev_data->bufferMap.end()) { return nullptr; } return buff_it->second.get(); @@ -3385,10 +3393,10 @@ template void SetLayout(OBJECT *pObject, VkImage im } void SetLayout(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkImageView imageView, const VkImageLayout &layout) { - auto image_view_data = dev_data->imageViewMap.find(imageView); - assert(image_view_data != dev_data->imageViewMap.end()); - const VkImage &image = image_view_data->second.image; - const VkImageSubresourceRange &subRange = image_view_data->second.subresourceRange; + auto iv_data = getImageViewData(dev_data, imageView); + assert(iv_data); + const VkImage &image = iv_data->image; + const VkImageSubresourceRange &subRange = iv_data->subresourceRange; // TODO: Do not iterate over every possibility - consolidate where possible for (uint32_t j = 0; j < subRange.levelCount; j++) { uint32_t level = subRange.baseMipLevel + j; @@ -5523,9 +5531,8 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageVie if (VK_SUCCESS == result) { std::lock_guard lock(global_lock); - VkImageViewCreateInfo localCI = VkImageViewCreateInfo(*pCreateInfo); - ResolveRemainingLevelsLayers(dev_data, &localCI.subresourceRange, pCreateInfo->image); - dev_data->imageViewMap[*pView] = localCI; + dev_data->imageViewMap[*pView] = unique_ptr(new VkImageViewCreateInfo(*pCreateInfo)); + ResolveRemainingLevelsLayers(dev_data, &dev_data->imageViewMap[*pView].get()->subresourceRange, pCreateInfo->image); } return result; @@ -5891,10 +5898,10 @@ static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkD VkDescriptorSet *pDescriptorSets, const cvdescriptorset::AllocateDescriptorSetsData *common_data) { // All the updates are contained in a single cvdescriptorset function - cvdescriptorset::PerformAllocateDescriptorSets( - pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, &dev_data->setMap, dev_data, - dev_data->descriptorSetLayoutMap, dev_data->imageViewMap, dev_data->imageMap, - dev_data->device_extensions.imageToSwapchainMap, dev_data->device_extensions.swapchainMap); + cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, + &dev_data->setMap, dev_data, dev_data->descriptorSetLayoutMap, + dev_data->imageMap, dev_data->device_extensions.imageToSwapchainMap, + dev_data->device_extensions.swapchainMap); } VKAPI_ATTR VkResult VKAPI_CALL @@ -6676,10 +6683,10 @@ static bool markStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_N bool skip_call = false; for (auto imageView : pCB->updateImages) { - auto iv_data = dev_data->imageViewMap.find(imageView); - if (iv_data == dev_data->imageViewMap.end()) + auto iv_data = getImageViewData(dev_data, imageView); + if (!iv_data) continue; - VkImage image = iv_data->second.image; + VkImage image = iv_data->image; VkDeviceMemory mem; skip_call |= get_mem_binding_from_object(dev_data, (uint64_t)image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &mem); @@ -8126,14 +8133,14 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFrameb } for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { VkImageView view = pCreateInfo->pAttachments[i]; - auto view_data = dev_data->imageViewMap.find(view); - if (view_data == dev_data->imageViewMap.end()) { + auto view_data = getImageViewData(dev_data, view); + if (!view_data) { continue; } MT_FB_ATTACHMENT_INFO fb_info; - get_mem_binding_from_object(dev_data, (uint64_t)(view_data->second.image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, + get_mem_binding_from_object(dev_data, (uint64_t)(view_data->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &fb_info.mem); - fb_info.image = view_data->second.image; + fb_info.image = view_data->image; fbNode.attachments.push_back(fb_info); } } @@ -8258,19 +8265,19 @@ static bool ValidateDependencies(const layer_data *my_data, FRAMEBUFFER_NODE con overlapping_attachments[j].push_back(i); continue; } - auto view_data_i = my_data->imageViewMap.find(viewi); - auto view_data_j = my_data->imageViewMap.find(viewj); - if (view_data_i == my_data->imageViewMap.end() || view_data_j == my_data->imageViewMap.end()) { + auto view_data_i = getImageViewData(my_data, viewi); + auto view_data_j = getImageViewData(my_data, viewj); + if (!view_data_i || !view_data_j) { continue; } - if (view_data_i->second.image == view_data_j->second.image && - isRegionOverlapping(view_data_i->second.subresourceRange, view_data_j->second.subresourceRange)) { + if (view_data_i->image == view_data_j->image && + isRegionOverlapping(view_data_i->subresourceRange, view_data_j->subresourceRange)) { overlapping_attachments[i].push_back(j); overlapping_attachments[j].push_back(i); continue; } - auto image_data_i = my_data->imageMap.find(view_data_i->second.image); - auto image_data_j = my_data->imageMap.find(view_data_j->second.image); + auto image_data_i = my_data->imageMap.find(view_data_i->image); + auto image_data_j = my_data->imageMap.find(view_data_j->image); if (image_data_i == my_data->imageMap.end() || image_data_j == my_data->imageMap.end()) { continue; } @@ -8723,10 +8730,10 @@ static bool VerifyFramebufferAndRenderPassLayouts(layer_data *dev_data, GLOBAL_C } for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) { const VkImageView &image_view = framebufferInfo.pAttachments[i]; - auto image_data = dev_data->imageViewMap.find(image_view); - assert(image_data != dev_data->imageViewMap.end()); - const VkImage &image = image_data->second.image; - const VkImageSubresourceRange &subRange = image_data->second.subresourceRange; + auto image_data = getImageViewData(dev_data, image_view); + assert(image_data); + const VkImage &image = image_data->image; + const VkImageSubresourceRange &subRange = image_data->subresourceRange; IMAGE_CMD_BUF_LAYOUT_NODE newNode = {pRenderPassInfo->pAttachments[i].initialLayout, pRenderPassInfo->pAttachments[i].initialLayout}; // TODO: Do not iterate over every possibility - consolidate where possible diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index e915ade7..e6dcdc85 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -490,6 +490,7 @@ BUFFER_NODE *getBufferNode(const layer_data *, const VkBuffer); DEVICE_MEM_INFO *getMemObjInfo(const layer_data *, const VkDeviceMemory); VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *, const VkBufferView); SAMPLER_NODE *getSamplerNode(const layer_data *, const VkSampler); +VkImageViewCreateInfo *getImageViewData(const layer_data *, const VkImageView); } #endif // CORE_VALIDATION_TYPES_H_ diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index ed25030f..e3f6e9d4 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -265,12 +265,11 @@ cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout, const core_validation::layer_data *dev_data, - const std::unordered_map *image_view_map, const std::unordered_map *image_map, const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map) - : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), image_view_map_(image_view_map), - image_map_(image_map), image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { + : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), image_map_(image_map), + image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { // Foreach binding, create default descriptors of given type for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) { auto type = p_layout_->GetTypeFromIndex(i); @@ -584,13 +583,13 @@ bool cvdescriptorset::ValidateSampler(const VkSampler sampler, const core_valida } bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type, - const std::unordered_map *image_view_map, + const core_validation::layer_data *dev_data, const std::unordered_map *image_map, const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map, std::string *error) { - auto image_pair = image_view_map->find(image_view); - if (image_pair == image_view_map->end()) { + auto iv_data = getImageViewData(dev_data, image_view); + if (!iv_data) { std::stringstream error_str; error_str << "Invalid VkImageView: " << image_view; *error = error_str.str(); @@ -598,8 +597,8 @@ bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout } // Validate that imageLayout is compatible with aspect_mask and image format // and validate that image usage bits are correct for given usage - VkImageAspectFlags aspect_mask = image_pair->second.subresourceRange.aspectMask; - VkImage image = image_pair->second.image; + VkImageAspectFlags aspect_mask = iv_data->subresourceRange.aspectMask; + VkImage image = iv_data->image; VkFormat format = VK_FORMAT_MAX_ENUM; VkImageUsageFlags usage = 0; auto img_pair = image_map->find(image); @@ -1035,7 +1034,7 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc // Validate image auto image_view = update->pImageInfo[di].imageView; auto image_layout = update->pImageInfo[di].imageLayout; - if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, image_view_map_, image_map_, + if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, image_map_, image_to_swapchain_map_, swapchain_map_, error)) { std::stringstream error_str; error_str << "Attempted write update to combined image sampler descriptor failed due to: " << error->c_str(); @@ -1067,7 +1066,7 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc for (uint32_t di = 0; di < update->descriptorCount; ++di) { auto image_view = update->pImageInfo[di].imageView; auto image_layout = update->pImageInfo[di].imageLayout; - if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, image_view_map_, image_map_, + if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, image_map_, image_to_swapchain_map_, swapchain_map_, error)) { std::stringstream error_str; error_str << "Attempted write update to image descriptor failed due to: " << error->c_str(); @@ -1158,7 +1157,7 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri // Validate image auto image_view = img_samp_desc->GetImageView(); auto image_layout = img_samp_desc->GetImageLayout(); - if (!ValidateImageUpdate(image_view, image_layout, type, image_view_map_, image_map_, image_to_swapchain_map_, + if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, image_map_, image_to_swapchain_map_, swapchain_map_, error)) { std::stringstream error_str; error_str << "Attempted copy update to combined image sampler descriptor failed due to: " << error->c_str(); @@ -1172,7 +1171,7 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri auto img_desc = static_cast(src_set->descriptors_[index + di].get()); auto image_view = img_desc->GetImageView(); auto image_layout = img_desc->GetImageLayout(); - if (!ValidateImageUpdate(image_view, image_layout, type, image_view_map_, image_map_, image_to_swapchain_map_, + if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, image_map_, image_to_swapchain_map_, swapchain_map_, error)) { std::stringstream error_str; error_str << "Attempted copy update to image descriptor failed due to: " << error->c_str(); @@ -1284,7 +1283,6 @@ void cvdescriptorset::PerformAllocateDescriptorSets( const AllocateDescriptorSetsData *ds_data, std::unordered_map *pool_map, std::unordered_map *set_map, const core_validation::layer_data *dev_data, const std::unordered_map &layout_map, - const std::unordered_map &image_view_map, const std::unordered_map &image_map, const std::unordered_map &image_to_swapchain_map, const std::unordered_map &swapchain_map) { @@ -1298,8 +1296,8 @@ void cvdescriptorset::PerformAllocateDescriptorSets( * global map and the pool's set. */ for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { - auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &image_view_map, - &image_map, &image_to_swapchain_map, &swapchain_map); + auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &image_map, + &image_to_swapchain_map, &swapchain_map); pool_state->sets.insert(new_ds); new_ds->in_use.store(0); diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index eddbff32..16763f84 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -161,8 +161,7 @@ class Descriptor { // Shared helper functions - These are useful because the shared sampler image descriptor type // performs common functions with both sampler and image descriptors so they can share their common functions bool ValidateSampler(const VkSampler, const core_validation::layer_data *); -bool ValidateImageUpdate(VkImageView, VkImageLayout, VkDescriptorType, - const std::unordered_map *, +bool ValidateImageUpdate(VkImageView, VkImageLayout, VkDescriptorType, const core_validation::layer_data *, const std::unordered_map *, const std::unordered_map *, const std::unordered_map *, std::string *); @@ -269,7 +268,6 @@ void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const Vk std::unordered_map *, const core_validation::layer_data *, const std::unordered_map &, - const std::unordered_map &, const std::unordered_map &, const std::unordered_map &, const std::unordered_map &); @@ -296,8 +294,7 @@ class DescriptorSet : public BASE_NODE { public: using BASE_NODE::in_use; DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const core_validation::layer_data *, - const std::unordered_map *, const std::unordered_map *, - const std::unordered_map *, + const std::unordered_map *, const std::unordered_map *, const std::unordered_map *); ~DescriptorSet(); // A number of common Get* functions that return data based on layout from which this set was created @@ -375,7 +372,6 @@ class DescriptorSet : public BASE_NODE { std::vector> descriptors_; // Ptrs to object containers to verify bound data const core_validation::layer_data *device_data_; - const std::unordered_map *image_view_map_; // TODO : For next 3 maps all we really need (currently) is an image to format mapping const std::unordered_map *image_map_; const std::unordered_map *image_to_swapchain_map_; -- cgit v1.2.3 From 920ff191e83225ae7d8cecc6ed8f6c7f38487450 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 11:49:22 -0600 Subject: layers: Add getImageNode() helper Add getImageNode() helper to core_validation and use it. Also update DescriptorSet class to use the helper and kill its image_map member. --- layers/core_validation.cpp | 126 ++++++++++++++++++++++------------------- layers/core_validation_types.h | 1 + layers/descriptor_sets.cpp | 33 +++++------ layers/descriptor_sets.h | 6 +- 4 files changed, 86 insertions(+), 80 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index e7aa6dbf..a117ed72 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -125,7 +125,7 @@ struct layer_data { // Layer specific data unordered_map> samplerMap; unordered_map> imageViewMap; - unordered_map imageMap; + unordered_map> imageMap; unordered_map> bufferViewMap; unordered_map> bufferMap; unordered_map pipelineMap; @@ -277,6 +277,14 @@ SAMPLER_NODE *getSamplerNode(const layer_data *dev_data, const VkSampler sampler } return sampler_it->second.get(); } +// Return image node ptr for specified image or else NULL +IMAGE_NODE *getImageNode(const layer_data *dev_data, const VkImage image) { + auto img_it = dev_data->imageMap.find(image); + if (img_it == dev_data->imageMap.end()) { + return nullptr; + } + return img_it->second.get(); +} // Return buffer node ptr for specified buffer or else NULL BUFFER_NODE *getBufferNode(const layer_data *dev_data, const VkBuffer buffer) { auto buff_it = dev_data->bufferMap.find(buffer); @@ -297,9 +305,9 @@ VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *my_data, const VkBuf static VkDeviceMemory *get_object_mem_binding(layer_data *my_data, uint64_t handle, VkDebugReportObjectTypeEXT type) { switch (type) { case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { - auto it = my_data->imageMap.find(VkImage(handle)); - if (it != my_data->imageMap.end()) - return &(*it).second.mem; + auto img_node = getImageNode(my_data, VkImage(handle)); + if (img_node) + return &img_node->mem; break; } case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: { @@ -345,9 +353,9 @@ static bool validate_usage_flags(layer_data *my_data, VkFlags actual, VkFlags de static bool validate_image_usage_flags(layer_data *dev_data, VkImage image, VkFlags desired, VkBool32 strict, char const *func_name, char const *usage_string) { bool skipCall = false; - auto const image_node = dev_data->imageMap.find(image); - if (image_node != dev_data->imageMap.end()) { - skipCall = validate_usage_flags(dev_data, image_node->second.createInfo.usage, desired, strict, (uint64_t)image, + auto const image_node = getImageNode(dev_data, image); + if (image_node) { + skipCall = validate_usage_flags(dev_data, image_node->createInfo.usage, desired, strict, (uint64_t)image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "image", func_name, usage_string); } return skipCall; @@ -387,8 +395,8 @@ static void add_mem_obj_info(layer_data *my_data, void *object, const VkDeviceMe static bool validate_memory_is_valid(layer_data *dev_data, VkDeviceMemory mem, const char *functionName, VkImage image = VK_NULL_HANDLE) { if (mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { - auto const image_node = dev_data->imageMap.find(image); - if (image_node != dev_data->imageMap.end() && !image_node->second.valid) { + auto const image_node = getImageNode(dev_data, image); + if (image_node && !image_node->valid) { return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)(mem), __LINE__, MEMTRACK_INVALID_USAGE_FLAG, "MEM", "%s: Cannot read invalid swapchain image 0x%" PRIx64 ", please fill the memory before using.", @@ -408,9 +416,9 @@ static bool validate_memory_is_valid(layer_data *dev_data, VkDeviceMemory mem, c static void set_memory_valid(layer_data *dev_data, VkDeviceMemory mem, bool valid, VkImage image = VK_NULL_HANDLE) { if (mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) { - auto image_node = dev_data->imageMap.find(image); - if (image_node != dev_data->imageMap.end()) { - image_node->second.valid = valid; + auto image_node = getImageNode(dev_data, image); + if (image_node) { + image_node->valid = valid; } } else { DEVICE_MEM_INFO *pMemObj = getMemObjInfo(dev_data, mem); @@ -620,9 +628,9 @@ static bool set_mem_binding(layer_data *dev_data, VkDeviceMemory mem, uint64_t h // For image objects, make sure default memory state is correctly set // TODO : What's the best/correct way to handle this? if (VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT == type) { - auto const image_node = dev_data->imageMap.find(VkImage(handle)); - if (image_node != dev_data->imageMap.end()) { - VkImageCreateInfo ici = image_node->second.createInfo; + auto const image_node = getImageNode(dev_data, VkImage(handle)); + if (image_node) { + VkImageCreateInfo ici = image_node->createInfo; if (ici.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { // TODO:: More memory state transition stuff. } @@ -3311,13 +3319,13 @@ bool FindLayouts(const layer_data *my_data, VkImage image, std::vectorimageSubresourceMap.find(image); if (sub_data == my_data->imageSubresourceMap.end()) return false; - auto imgIt = my_data->imageMap.find(image); - if (imgIt == my_data->imageMap.end()) + auto img_node = getImageNode(my_data, image); + if (!img_node) return false; bool ignoreGlobal = false; // TODO: Make this robust for >1 aspect mask. Now it will just say ignore // potential errors in this case. - if (sub_data->second.size() >= (imgIt->second.createInfo.arrayLayers * imgIt->second.createInfo.mipLevels + 1)) { + if (sub_data->second.size() >= (img_node->createInfo.arrayLayers * img_node->createInfo.mipLevels + 1)) { ignoreGlobal = true; } for (auto imgsubpair : sub_data->second) { @@ -5068,9 +5076,9 @@ VKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const Vk const auto &imageEntry = dev_data->imageMap.find(image); if (imageEntry != dev_data->imageMap.end()) { // Clean up memory mapping, bindings and range references for image - auto mem_info = getMemObjInfo(dev_data, imageEntry->second.mem); + auto mem_info = getMemObjInfo(dev_data, imageEntry->second.get()->mem); if (mem_info) { - remove_memory_ranges(reinterpret_cast(image), imageEntry->second.mem, mem_info->imageRanges); + remove_memory_ranges(reinterpret_cast(image), imageEntry->second.get()->mem, mem_info->imageRanges); clear_object_binding(dev_data, reinterpret_cast(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT); mem_info->image = VK_NULL_HANDLE; } @@ -5465,7 +5473,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateI IMAGE_LAYOUT_NODE image_node; image_node.layout = pCreateInfo->initialLayout; image_node.format = pCreateInfo->format; - dev_data->imageMap.insert(std::make_pair(*pImage, IMAGE_NODE(pCreateInfo))); + dev_data->imageMap.insert(std::make_pair(*pImage, unique_ptr(new IMAGE_NODE(pCreateInfo)))); ImageSubresourcePair subpair = {*pImage, false, VkImageSubresource()}; dev_data->imageSubresourceMap[*pImage].push_back(subpair); dev_data->imageLayoutMap[subpair] = image_node; @@ -5476,18 +5484,18 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateI static void ResolveRemainingLevelsLayers(layer_data *dev_data, VkImageSubresourceRange *range, VkImage image) { /* expects global_lock to be held by caller */ - auto image_node_it = dev_data->imageMap.find(image); - if (image_node_it != dev_data->imageMap.end()) { + auto image_node = getImageNode(dev_data, image); + if (image_node) { /* If the caller used the special values VK_REMAINING_MIP_LEVELS and * VK_REMAINING_ARRAY_LAYERS, resolve them now in our internal state to * the actual values. */ if (range->levelCount == VK_REMAINING_MIP_LEVELS) { - range->levelCount = image_node_it->second.createInfo.mipLevels - range->baseMipLevel; + range->levelCount = image_node->createInfo.mipLevels - range->baseMipLevel; } if (range->layerCount == VK_REMAINING_ARRAY_LAYERS) { - range->layerCount = image_node_it->second.createInfo.arrayLayers - range->baseArrayLayer; + range->layerCount = image_node->createInfo.arrayLayers - range->baseArrayLayer; } } } @@ -5500,13 +5508,13 @@ static void ResolveRemainingLevelsLayers(layer_data *dev_data, uint32_t *levels, *levels = range.levelCount; *layers = range.layerCount; - auto image_node_it = dev_data->imageMap.find(image); - if (image_node_it != dev_data->imageMap.end()) { + auto image_node = getImageNode(dev_data, image); + if (image_node) { if (range.levelCount == VK_REMAINING_MIP_LEVELS) { - *levels = image_node_it->second.createInfo.mipLevels - range.baseMipLevel; + *levels = image_node->createInfo.mipLevels - range.baseMipLevel; } if (range.layerCount == VK_REMAINING_ARRAY_LAYERS) { - *layers = image_node_it->second.createInfo.arrayLayers - range.baseArrayLayer; + *layers = image_node->createInfo.arrayLayers - range.baseArrayLayer; } } } @@ -5900,7 +5908,7 @@ static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkD // All the updates are contained in a single cvdescriptorset function cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, &dev_data->setMap, dev_data, dev_data->descriptorSetLayoutMap, - dev_data->imageMap, dev_data->device_extensions.imageToSwapchainMap, + dev_data->device_extensions.imageToSwapchainMap, dev_data->device_extensions.swapchainMap); } @@ -7581,11 +7589,11 @@ static bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, ui } for (uint32_t i = 0; i < imageMemBarrierCount; ++i) { auto mem_barrier = &pImageMemBarriers[i]; - auto image_data = dev_data->imageMap.find(mem_barrier->image); - if (image_data != dev_data->imageMap.end()) { + auto image_data = getImageNode(dev_data, mem_barrier->image); + if (image_data) { uint32_t src_q_f_index = mem_barrier->srcQueueFamilyIndex; uint32_t dst_q_f_index = mem_barrier->dstQueueFamilyIndex; - if (image_data->second.createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { + if (image_data->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) { // srcQueueFamilyIndex and dstQueueFamilyIndex must both // be VK_QUEUE_FAMILY_IGNORED if ((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) { @@ -7635,14 +7643,14 @@ static bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, ui "PREINITIALIZED.", funcName); } - auto image_data = dev_data->imageMap.find(mem_barrier->image); + auto image_data = getImageNode(dev_data, mem_barrier->image); VkFormat format = VK_FORMAT_UNDEFINED; uint32_t arrayLayers = 0, mipLevels = 0; bool imageFound = false; - if (image_data != dev_data->imageMap.end()) { - format = image_data->second.createInfo.format; - arrayLayers = image_data->second.createInfo.arrayLayers; - mipLevels = image_data->second.createInfo.mipLevels; + if (image_data) { + format = image_data->createInfo.format; + arrayLayers = image_data->createInfo.arrayLayers; + mipLevels = image_data->createInfo.mipLevels; imageFound = true; } else if (dev_data->device_extensions.wsi_enabled) { auto imageswap_data = dev_data->device_extensions.imageToSwapchainMap.find(mem_barrier->image); @@ -8276,14 +8284,13 @@ static bool ValidateDependencies(const layer_data *my_data, FRAMEBUFFER_NODE con overlapping_attachments[j].push_back(i); continue; } - auto image_data_i = my_data->imageMap.find(view_data_i->image); - auto image_data_j = my_data->imageMap.find(view_data_j->image); - if (image_data_i == my_data->imageMap.end() || image_data_j == my_data->imageMap.end()) { + auto image_data_i = getImageNode(my_data, view_data_i->image); + auto image_data_j = getImageNode(my_data, view_data_j->image); + if (!image_data_i || !image_data_j) { continue; } - if (image_data_i->second.mem == image_data_j->second.mem && - isRangeOverlapping(image_data_i->second.memOffset, image_data_i->second.memSize, image_data_j->second.memOffset, - image_data_j->second.memSize)) { + if (image_data_i->mem == image_data_j->mem && isRangeOverlapping(image_data_i->memOffset, image_data_i->memSize, + image_data_j->memOffset, image_data_j->memSize)) { overlapping_attachments[i].push_back(j); overlapping_attachments[j].push_back(i); } @@ -9461,8 +9468,8 @@ VKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, V VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; bool skipCall = false; std::unique_lock lock(global_lock); - auto image_node = dev_data->imageMap.find(image); - if (image_node != dev_data->imageMap.end()) { + auto image_node = getImageNode(dev_data, image); + if (image_node) { // Track objects tied to memory uint64_t image_handle = reinterpret_cast(image); skipCall = set_mem_binding(dev_data, mem, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory"); @@ -9485,9 +9492,9 @@ VKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, V result = dev_data->device_dispatch_table->BindImageMemory(device, image, mem, memoryOffset); lock.lock(); dev_data->memObjMap[mem].get()->image = image; - image_node->second.mem = mem; - image_node->second.memOffset = memoryOffset; - image_node->second.memSize = memRequirements.size; + image_node->mem = mem; + image_node->memOffset = memoryOffset; + image_node->memSize = memRequirements.size; lock.unlock(); } } else { @@ -9724,16 +9731,19 @@ GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pCoun IMAGE_LAYOUT_NODE image_layout_node; image_layout_node.layout = VK_IMAGE_LAYOUT_UNDEFINED; image_layout_node.format = swapchain_node->createInfo.imageFormat; + // Add imageMap entries for each swapchain image + VkImageCreateInfo image_ci = {}; + image_ci.mipLevels = 1; + image_ci.arrayLayers = swapchain_node->createInfo.imageArrayLayers; + image_ci.usage = swapchain_node->createInfo.imageUsage; + image_ci.format = swapchain_node->createInfo.imageFormat; + image_ci.extent.width = swapchain_node->createInfo.imageExtent.width; + image_ci.extent.height = swapchain_node->createInfo.imageExtent.height; + image_ci.sharingMode = swapchain_node->createInfo.imageSharingMode; + dev_data->imageMap[pSwapchainImages[i]] = unique_ptr(new IMAGE_NODE(&image_ci)); auto &image_node = dev_data->imageMap[pSwapchainImages[i]]; - image_node.createInfo.mipLevels = 1; - image_node.createInfo.arrayLayers = swapchain_node->createInfo.imageArrayLayers; - image_node.createInfo.usage = swapchain_node->createInfo.imageUsage; - image_node.createInfo.format = swapchain_node->createInfo.imageFormat; - image_node.createInfo.extent.width = swapchain_node->createInfo.imageExtent.width; - image_node.createInfo.extent.height = swapchain_node->createInfo.imageExtent.height; - image_node.createInfo.sharingMode = swapchain_node->createInfo.imageSharingMode; - image_node.valid = false; - image_node.mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY; + image_node->valid = false; + image_node->mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY; swapchain_node->images.push_back(pSwapchainImages[i]); ImageSubresourcePair subpair = {pSwapchainImages[i], false, VkImageSubresource()}; dev_data->imageSubresourceMap[pSwapchainImages[i]].push_back(subpair); diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index e6dcdc85..4b979881 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -487,6 +487,7 @@ namespace core_validation { struct layer_data; cvdescriptorset::DescriptorSet *getSetNode(const layer_data *, const VkDescriptorSet); BUFFER_NODE *getBufferNode(const layer_data *, const VkBuffer); +IMAGE_NODE *getImageNode(const layer_data *, const VkImage); DEVICE_MEM_INFO *getMemObjInfo(const layer_data *, const VkDeviceMemory); VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *, const VkBufferView); SAMPLER_NODE *getSamplerNode(const layer_data *, const VkSampler); diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index e3f6e9d4..9039a122 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -265,11 +265,10 @@ cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout, const core_validation::layer_data *dev_data, - const std::unordered_map *image_map, const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map) - : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), image_map_(image_map), - image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) { + : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), image_to_swapchain_map_(image_to_swapchain_map), + swapchain_map_(swapchain_map) { // Foreach binding, create default descriptors of given type for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) { auto type = p_layout_->GetTypeFromIndex(i); @@ -584,7 +583,6 @@ bool cvdescriptorset::ValidateSampler(const VkSampler sampler, const core_valida bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type, const core_validation::layer_data *dev_data, - const std::unordered_map *image_map, const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map, std::string *error) { @@ -601,10 +599,10 @@ bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout VkImage image = iv_data->image; VkFormat format = VK_FORMAT_MAX_ENUM; VkImageUsageFlags usage = 0; - auto img_pair = image_map->find(image); - if (img_pair != image_map->end()) { - format = img_pair->second.createInfo.format; - usage = img_pair->second.createInfo.usage; + auto image_node = getImageNode(dev_data, image); + if (image_node) { + format = image_node->createInfo.format; + usage = image_node->createInfo.usage; } else { // Also need to check the swapchains. auto swapchain_pair = image_to_swapchain_map->find(image); @@ -1034,8 +1032,8 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc // Validate image auto image_view = update->pImageInfo[di].imageView; auto image_layout = update->pImageInfo[di].imageLayout; - if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, image_map_, - image_to_swapchain_map_, swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, image_to_swapchain_map_, + swapchain_map_, error)) { std::stringstream error_str; error_str << "Attempted write update to combined image sampler descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1066,8 +1064,8 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc for (uint32_t di = 0; di < update->descriptorCount; ++di) { auto image_view = update->pImageInfo[di].imageView; auto image_layout = update->pImageInfo[di].imageLayout; - if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, image_map_, - image_to_swapchain_map_, swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, image_to_swapchain_map_, + swapchain_map_, error)) { std::stringstream error_str; error_str << "Attempted write update to image descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1157,8 +1155,8 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri // Validate image auto image_view = img_samp_desc->GetImageView(); auto image_layout = img_samp_desc->GetImageLayout(); - if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, image_map_, image_to_swapchain_map_, - swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, image_to_swapchain_map_, swapchain_map_, + error)) { std::stringstream error_str; error_str << "Attempted copy update to combined image sampler descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1171,8 +1169,8 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri auto img_desc = static_cast(src_set->descriptors_[index + di].get()); auto image_view = img_desc->GetImageView(); auto image_layout = img_desc->GetImageLayout(); - if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, image_map_, image_to_swapchain_map_, - swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, image_to_swapchain_map_, swapchain_map_, + error)) { std::stringstream error_str; error_str << "Attempted copy update to image descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1283,7 +1281,6 @@ void cvdescriptorset::PerformAllocateDescriptorSets( const AllocateDescriptorSetsData *ds_data, std::unordered_map *pool_map, std::unordered_map *set_map, const core_validation::layer_data *dev_data, const std::unordered_map &layout_map, - const std::unordered_map &image_map, const std::unordered_map &image_to_swapchain_map, const std::unordered_map &swapchain_map) { auto pool_state = (*pool_map)[p_alloc_info->descriptorPool]; @@ -1296,7 +1293,7 @@ void cvdescriptorset::PerformAllocateDescriptorSets( * global map and the pool's set. */ for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { - auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &image_map, + auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &image_to_swapchain_map, &swapchain_map); pool_state->sets.insert(new_ds); diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 16763f84..c775c736 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -162,7 +162,7 @@ class Descriptor { // performs common functions with both sampler and image descriptors so they can share their common functions bool ValidateSampler(const VkSampler, const core_validation::layer_data *); bool ValidateImageUpdate(VkImageView, VkImageLayout, VkDescriptorType, const core_validation::layer_data *, - const std::unordered_map *, const std::unordered_map *, + const std::unordered_map *, const std::unordered_map *, std::string *); class SamplerDescriptor : public Descriptor { @@ -268,7 +268,6 @@ void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const Vk std::unordered_map *, const core_validation::layer_data *, const std::unordered_map &, - const std::unordered_map &, const std::unordered_map &, const std::unordered_map &); @@ -294,7 +293,7 @@ class DescriptorSet : public BASE_NODE { public: using BASE_NODE::in_use; DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const core_validation::layer_data *, - const std::unordered_map *, const std::unordered_map *, + const std::unordered_map *, const std::unordered_map *); ~DescriptorSet(); // A number of common Get* functions that return data based on layout from which this set was created @@ -373,7 +372,6 @@ class DescriptorSet : public BASE_NODE { // Ptrs to object containers to verify bound data const core_validation::layer_data *device_data_; // TODO : For next 3 maps all we really need (currently) is an image to format mapping - const std::unordered_map *image_map_; const std::unordered_map *image_to_swapchain_map_; const std::unordered_map *swapchain_map_; }; -- cgit v1.2.3 From e926298faf8f17577c470e115cd74ac73ba7da9e Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 11:56:40 -0600 Subject: layers: Remove unneeded layout_map --- layers/core_validation.cpp | 3 +-- layers/descriptor_sets.cpp | 1 - layers/descriptor_sets.h | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index a117ed72..f0dede6c 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5907,8 +5907,7 @@ static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkD const cvdescriptorset::AllocateDescriptorSetsData *common_data) { // All the updates are contained in a single cvdescriptorset function cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, - &dev_data->setMap, dev_data, dev_data->descriptorSetLayoutMap, - dev_data->device_extensions.imageToSwapchainMap, + &dev_data->setMap, dev_data, dev_data->device_extensions.imageToSwapchainMap, dev_data->device_extensions.swapchainMap); } diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 9039a122..795f5d71 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -1280,7 +1280,6 @@ void cvdescriptorset::PerformAllocateDescriptorSets( const VkDescriptorSetAllocateInfo *p_alloc_info, const VkDescriptorSet *descriptor_sets, const AllocateDescriptorSetsData *ds_data, std::unordered_map *pool_map, std::unordered_map *set_map, const core_validation::layer_data *dev_data, - const std::unordered_map &layout_map, const std::unordered_map &image_to_swapchain_map, const std::unordered_map &swapchain_map) { auto pool_state = (*pool_map)[p_alloc_info->descriptorPool]; diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index c775c736..365dedf8 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -267,7 +267,6 @@ void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const Vk std::unordered_map *, std::unordered_map *, const core_validation::layer_data *, - const std::unordered_map &, const std::unordered_map &, const std::unordered_map &); -- cgit v1.2.3 From b6cb17cbade092a74b25c40b9042fb4cd804b167 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 12:13:32 -0600 Subject: layers: Add getSwapchainFromImage() helper Add getSwapchainFromImage() to core_validation and use it from DescriptorSet class. --- layers/core_validation.cpp | 17 ++++++++++++----- layers/core_validation_types.h | 1 + layers/descriptor_sets.cpp | 26 ++++++++------------------ layers/descriptor_sets.h | 4 ---- 4 files changed, 21 insertions(+), 27 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index f0dede6c..4c63a803 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -293,6 +293,14 @@ BUFFER_NODE *getBufferNode(const layer_data *dev_data, const VkBuffer buffer) { } return buff_it->second.get(); } +// Return swapchain for specified image or else NULL +VkSwapchainKHR getSwapchainFromImage(const layer_data *dev_data, const VkImage image) { + auto img_it = dev_data->device_extensions.imageToSwapchainMap.find(image); + if (img_it == dev_data->device_extensions.imageToSwapchainMap.end()) { + return VK_NULL_HANDLE; + } + return img_it->second; +} // Return buffer node ptr for specified buffer or else NULL VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *my_data, const VkBufferView buffer_view) { auto bv_it = my_data->bufferViewMap.find(buffer_view); @@ -5907,8 +5915,7 @@ static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkD const cvdescriptorset::AllocateDescriptorSetsData *common_data) { // All the updates are contained in a single cvdescriptorset function cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, - &dev_data->setMap, dev_data, dev_data->device_extensions.imageToSwapchainMap, - dev_data->device_extensions.swapchainMap); + &dev_data->setMap, dev_data, dev_data->device_extensions.swapchainMap); } VKAPI_ATTR VkResult VKAPI_CALL @@ -7652,9 +7659,9 @@ static bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, ui mipLevels = image_data->createInfo.mipLevels; imageFound = true; } else if (dev_data->device_extensions.wsi_enabled) { - auto imageswap_data = dev_data->device_extensions.imageToSwapchainMap.find(mem_barrier->image); - if (imageswap_data != dev_data->device_extensions.imageToSwapchainMap.end()) { - auto swapchain_data = dev_data->device_extensions.swapchainMap.find(imageswap_data->second); + auto imageswap_data = getSwapchainFromImage(dev_data, mem_barrier->image); + if (imageswap_data) { + auto swapchain_data = dev_data->device_extensions.swapchainMap.find(imageswap_data); if (swapchain_data != dev_data->device_extensions.swapchainMap.end()) { format = swapchain_data->second->createInfo.imageFormat; arrayLayers = swapchain_data->second->createInfo.imageArrayLayers; diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 4b979881..1d601f43 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -492,6 +492,7 @@ DEVICE_MEM_INFO *getMemObjInfo(const layer_data *, const VkDeviceMemory); VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *, const VkBufferView); SAMPLER_NODE *getSamplerNode(const layer_data *, const VkSampler); VkImageViewCreateInfo *getImageViewData(const layer_data *, const VkImageView); +VkSwapchainKHR getSwapchainFromImage(const layer_data *, const VkImage); } #endif // CORE_VALIDATION_TYPES_H_ diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 795f5d71..2393d308 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -265,10 +265,8 @@ cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout, const core_validation::layer_data *dev_data, - const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map) - : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), image_to_swapchain_map_(image_to_swapchain_map), - swapchain_map_(swapchain_map) { + : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), swapchain_map_(swapchain_map) { // Foreach binding, create default descriptors of given type for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) { auto type = p_layout_->GetTypeFromIndex(i); @@ -583,7 +581,6 @@ bool cvdescriptorset::ValidateSampler(const VkSampler sampler, const core_valida bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type, const core_validation::layer_data *dev_data, - const std::unordered_map *image_to_swapchain_map, const std::unordered_map *swapchain_map, std::string *error) { auto iv_data = getImageViewData(dev_data, image_view); @@ -605,9 +602,8 @@ bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout usage = image_node->createInfo.usage; } else { // Also need to check the swapchains. - auto swapchain_pair = image_to_swapchain_map->find(image); - if (swapchain_pair != image_to_swapchain_map->end()) { - VkSwapchainKHR swapchain = swapchain_pair->second; + auto swapchain = getSwapchainFromImage(dev_data, image); + if (swapchain) { auto swapchain_pair = swapchain_map->find(swapchain); if (swapchain_pair != swapchain_map->end()) { format = swapchain_pair->second->createInfo.imageFormat; @@ -1032,8 +1028,7 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc // Validate image auto image_view = update->pImageInfo[di].imageView; auto image_layout = update->pImageInfo[di].imageLayout; - if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, image_to_swapchain_map_, - swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, swapchain_map_, error)) { std::stringstream error_str; error_str << "Attempted write update to combined image sampler descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1064,8 +1059,7 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc for (uint32_t di = 0; di < update->descriptorCount; ++di) { auto image_view = update->pImageInfo[di].imageView; auto image_layout = update->pImageInfo[di].imageLayout; - if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, image_to_swapchain_map_, - swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, swapchain_map_, error)) { std::stringstream error_str; error_str << "Attempted write update to image descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1155,8 +1149,7 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri // Validate image auto image_view = img_samp_desc->GetImageView(); auto image_layout = img_samp_desc->GetImageLayout(); - if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, image_to_swapchain_map_, swapchain_map_, - error)) { + if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, swapchain_map_, error)) { std::stringstream error_str; error_str << "Attempted copy update to combined image sampler descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1169,8 +1162,7 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri auto img_desc = static_cast(src_set->descriptors_[index + di].get()); auto image_view = img_desc->GetImageView(); auto image_layout = img_desc->GetImageLayout(); - if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, image_to_swapchain_map_, swapchain_map_, - error)) { + if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, swapchain_map_, error)) { std::stringstream error_str; error_str << "Attempted copy update to image descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1280,7 +1272,6 @@ void cvdescriptorset::PerformAllocateDescriptorSets( const VkDescriptorSetAllocateInfo *p_alloc_info, const VkDescriptorSet *descriptor_sets, const AllocateDescriptorSetsData *ds_data, std::unordered_map *pool_map, std::unordered_map *set_map, const core_validation::layer_data *dev_data, - const std::unordered_map &image_to_swapchain_map, const std::unordered_map &swapchain_map) { auto pool_state = (*pool_map)[p_alloc_info->descriptorPool]; /* Account for sets and individual descriptors allocated from pool */ @@ -1292,8 +1283,7 @@ void cvdescriptorset::PerformAllocateDescriptorSets( * global map and the pool's set. */ for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { - auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, - &image_to_swapchain_map, &swapchain_map); + auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &swapchain_map); pool_state->sets.insert(new_ds); new_ds->in_use.store(0); diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 365dedf8..88bcef23 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -162,7 +162,6 @@ class Descriptor { // performs common functions with both sampler and image descriptors so they can share their common functions bool ValidateSampler(const VkSampler, const core_validation::layer_data *); bool ValidateImageUpdate(VkImageView, VkImageLayout, VkDescriptorType, const core_validation::layer_data *, - const std::unordered_map *, const std::unordered_map *, std::string *); class SamplerDescriptor : public Descriptor { @@ -267,7 +266,6 @@ void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const Vk std::unordered_map *, std::unordered_map *, const core_validation::layer_data *, - const std::unordered_map &, const std::unordered_map &); /* @@ -292,7 +290,6 @@ class DescriptorSet : public BASE_NODE { public: using BASE_NODE::in_use; DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const core_validation::layer_data *, - const std::unordered_map *, const std::unordered_map *); ~DescriptorSet(); // A number of common Get* functions that return data based on layout from which this set was created @@ -371,7 +368,6 @@ class DescriptorSet : public BASE_NODE { // Ptrs to object containers to verify bound data const core_validation::layer_data *device_data_; // TODO : For next 3 maps all we really need (currently) is an image to format mapping - const std::unordered_map *image_to_swapchain_map_; const std::unordered_map *swapchain_map_; }; } -- cgit v1.2.3 From 07286c1f26b9bc37f84cccbcfcff77e0b9ef7a38 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 12:41:47 -0600 Subject: layers: Added getSwapchainNode() helper Added getSwapchainNode() helper to core_validation and update DescriptorSet class to use it. --- layers/core_validation.cpp | 39 +++++++++++++++++++++++---------------- layers/core_validation_types.h | 1 + layers/descriptor_sets.cpp | 33 ++++++++++++++++----------------- layers/descriptor_sets.h | 11 +++-------- 4 files changed, 43 insertions(+), 41 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 4c63a803..53b416f4 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -293,6 +293,14 @@ BUFFER_NODE *getBufferNode(const layer_data *dev_data, const VkBuffer buffer) { } return buff_it->second.get(); } +// Return swapchain node for specified swapchain or else NULL +SWAPCHAIN_NODE *getSwapchainNode(const layer_data *dev_data, const VkSwapchainKHR swapchain) { + auto swp_it = dev_data->device_extensions.swapchainMap.find(swapchain); + if (swp_it == dev_data->device_extensions.swapchainMap.end()) { + return nullptr; + } + return swp_it->second; +} // Return swapchain for specified image or else NULL VkSwapchainKHR getSwapchainFromImage(const layer_data *dev_data, const VkImage image) { auto img_it = dev_data->device_extensions.imageToSwapchainMap.find(image); @@ -5915,7 +5923,7 @@ static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkD const cvdescriptorset::AllocateDescriptorSetsData *common_data) { // All the updates are contained in a single cvdescriptorset function cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap, - &dev_data->setMap, dev_data, dev_data->device_extensions.swapchainMap); + &dev_data->setMap, dev_data); } VKAPI_ATTR VkResult VKAPI_CALL @@ -7661,10 +7669,10 @@ static bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, ui } else if (dev_data->device_extensions.wsi_enabled) { auto imageswap_data = getSwapchainFromImage(dev_data, mem_barrier->image); if (imageswap_data) { - auto swapchain_data = dev_data->device_extensions.swapchainMap.find(imageswap_data); - if (swapchain_data != dev_data->device_extensions.swapchainMap.end()) { - format = swapchain_data->second->createInfo.imageFormat; - arrayLayers = swapchain_data->second->createInfo.imageArrayLayers; + auto swapchain_data = getSwapchainNode(dev_data, imageswap_data); + if (swapchain_data) { + format = swapchain_data->createInfo.imageFormat; + arrayLayers = swapchain_data->createInfo.imageArrayLayers; mipLevels = 1; imageFound = true; } @@ -9681,10 +9689,10 @@ DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocatio bool skipCall = false; std::unique_lock lock(global_lock); - auto swapchain_data = dev_data->device_extensions.swapchainMap.find(swapchain); - if (swapchain_data != dev_data->device_extensions.swapchainMap.end()) { - if (swapchain_data->second->images.size() > 0) { - for (auto swapchain_image : swapchain_data->second->images) { + auto swapchain_data = getSwapchainNode(dev_data, swapchain); + if (swapchain_data) { + if (swapchain_data->images.size() > 0) { + for (auto swapchain_image : swapchain_data->images) { auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image); if (image_sub != dev_data->imageSubresourceMap.end()) { for (auto imgsubpair : image_sub->second) { @@ -9700,7 +9708,7 @@ DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocatio dev_data->imageMap.erase(swapchain_image); } } - delete swapchain_data->second; + delete swapchain_data; dev_data->device_extensions.swapchainMap.erase(swapchain); } lock.unlock(); @@ -9719,8 +9727,8 @@ GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pCoun return result; std::lock_guard lock(global_lock); const size_t count = *pCount; - auto swapchain_node = dev_data->device_extensions.swapchainMap[swapchain]; - if (!swapchain_node->images.empty()) { + auto swapchain_node = getSwapchainNode(dev_data, swapchain); + if (swapchain_node && !swapchain_node->images.empty()) { // TODO : Not sure I like the memcmp here, but it works const bool mismatch = (swapchain_node->images.size() != count || memcmp(&swapchain_node->images[0], pSwapchainImages, sizeof(swapchain_node->images[0]) * count)); @@ -9783,10 +9791,9 @@ VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInf } VkDeviceMemory mem; for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { - auto swapchain_data = dev_data->device_extensions.swapchainMap.find(pPresentInfo->pSwapchains[i]); - if (swapchain_data != dev_data->device_extensions.swapchainMap.end() && - pPresentInfo->pImageIndices[i] < swapchain_data->second->images.size()) { - VkImage image = swapchain_data->second->images[pPresentInfo->pImageIndices[i]]; + auto swapchain_data = getSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]); + if (swapchain_data && pPresentInfo->pImageIndices[i] < swapchain_data->images.size()) { + VkImage image = swapchain_data->images[pPresentInfo->pImageIndices[i]]; #if MTMERGESOURCE skip_call |= get_mem_binding_from_object(dev_data, (uint64_t)(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &mem); diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 1d601f43..9ec81357 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -493,6 +493,7 @@ VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *, const VkBufferView SAMPLER_NODE *getSamplerNode(const layer_data *, const VkSampler); VkImageViewCreateInfo *getImageViewData(const layer_data *, const VkImageView); VkSwapchainKHR getSwapchainFromImage(const layer_data *, const VkImage); +SWAPCHAIN_NODE *getSwapchainNode(const layer_data *, const VkSwapchainKHR); } #endif // CORE_VALIDATION_TYPES_H_ diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 2393d308..8ccd334e 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -264,9 +264,8 @@ cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t : required_descriptors_by_type{}, layout_nodes(count, nullptr) {} cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout, - const core_validation::layer_data *dev_data, - const std::unordered_map *swapchain_map) - : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data), swapchain_map_(swapchain_map) { + const core_validation::layer_data *dev_data) + : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data) { // Foreach binding, create default descriptors of given type for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) { auto type = p_layout_->GetTypeFromIndex(i); @@ -581,7 +580,6 @@ bool cvdescriptorset::ValidateSampler(const VkSampler sampler, const core_valida bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type, const core_validation::layer_data *dev_data, - const std::unordered_map *swapchain_map, std::string *error) { auto iv_data = getImageViewData(dev_data, image_view); if (!iv_data) { @@ -604,9 +602,9 @@ bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout // Also need to check the swapchains. auto swapchain = getSwapchainFromImage(dev_data, image); if (swapchain) { - auto swapchain_pair = swapchain_map->find(swapchain); - if (swapchain_pair != swapchain_map->end()) { - format = swapchain_pair->second->createInfo.imageFormat; + auto swapchain_node = getSwapchainNode(dev_data, swapchain); + if (swapchain_node) { + format = swapchain_node->createInfo.imageFormat; } } } @@ -1028,7 +1026,7 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc // Validate image auto image_view = update->pImageInfo[di].imageView; auto image_layout = update->pImageInfo[di].imageLayout; - if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, error)) { std::stringstream error_str; error_str << "Attempted write update to combined image sampler descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1059,7 +1057,7 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc for (uint32_t di = 0; di < update->descriptorCount; ++di) { auto image_view = update->pImageInfo[di].imageView; auto image_layout = update->pImageInfo[di].imageLayout; - if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, error)) { std::stringstream error_str; error_str << "Attempted write update to image descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1149,7 +1147,7 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri // Validate image auto image_view = img_samp_desc->GetImageView(); auto image_layout = img_samp_desc->GetImageLayout(); - if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, error)) { std::stringstream error_str; error_str << "Attempted copy update to combined image sampler descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1162,7 +1160,7 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri auto img_desc = static_cast(src_set->descriptors_[index + di].get()); auto image_view = img_desc->GetImageView(); auto image_layout = img_desc->GetImageLayout(); - if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, error)) { std::stringstream error_str; error_str << "Attempted copy update to image descriptor failed due to: " << error->c_str(); *error = error_str.str(); @@ -1268,11 +1266,12 @@ bool cvdescriptorset::ValidateAllocateDescriptorSets( return skip_call; } // Decrement allocated sets from the pool and insert new sets into set_map -void cvdescriptorset::PerformAllocateDescriptorSets( - const VkDescriptorSetAllocateInfo *p_alloc_info, const VkDescriptorSet *descriptor_sets, - const AllocateDescriptorSetsData *ds_data, std::unordered_map *pool_map, - std::unordered_map *set_map, const core_validation::layer_data *dev_data, - const std::unordered_map &swapchain_map) { +void cvdescriptorset::PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *p_alloc_info, + const VkDescriptorSet *descriptor_sets, + const AllocateDescriptorSetsData *ds_data, + std::unordered_map *pool_map, + std::unordered_map *set_map, + const core_validation::layer_data *dev_data) { auto pool_state = (*pool_map)[p_alloc_info->descriptorPool]; /* Account for sets and individual descriptors allocated from pool */ pool_state->availableSets -= p_alloc_info->descriptorSetCount; @@ -1283,7 +1282,7 @@ void cvdescriptorset::PerformAllocateDescriptorSets( * global map and the pool's set. */ for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { - auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data, &swapchain_map); + auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data); pool_state->sets.insert(new_ds); new_ds->in_use.store(0); diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 88bcef23..1b7ebb4a 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -161,8 +161,7 @@ class Descriptor { // Shared helper functions - These are useful because the shared sampler image descriptor type // performs common functions with both sampler and image descriptors so they can share their common functions bool ValidateSampler(const VkSampler, const core_validation::layer_data *); -bool ValidateImageUpdate(VkImageView, VkImageLayout, VkDescriptorType, const core_validation::layer_data *, - const std::unordered_map *, std::string *); +bool ValidateImageUpdate(VkImageView, VkImageLayout, VkDescriptorType, const core_validation::layer_data *, std::string *); class SamplerDescriptor : public Descriptor { public: @@ -265,8 +264,7 @@ bool ValidateAllocateDescriptorSets(const debug_report_data *, const VkDescripto void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, const AllocateDescriptorSetsData *, std::unordered_map *, std::unordered_map *, - const core_validation::layer_data *, - const std::unordered_map &); + const core_validation::layer_data *); /* * DescriptorSet class @@ -289,8 +287,7 @@ void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const Vk class DescriptorSet : public BASE_NODE { public: using BASE_NODE::in_use; - DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const core_validation::layer_data *, - const std::unordered_map *); + DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const core_validation::layer_data *); ~DescriptorSet(); // A number of common Get* functions that return data based on layout from which this set was created uint32_t GetTotalDescriptorCount() const { return p_layout_ ? p_layout_->GetTotalDescriptorCount() : 0; }; @@ -367,8 +364,6 @@ class DescriptorSet : public BASE_NODE { std::vector> descriptors_; // Ptrs to object containers to verify bound data const core_validation::layer_data *device_data_; - // TODO : For next 3 maps all we really need (currently) is an image to format mapping - const std::unordered_map *swapchain_map_; }; } #endif // CORE_VALIDATION_DESCRIPTOR_SETS_H_ -- cgit v1.2.3 From 50619b9017896f33b5f428f4dad7be303f53a4b6 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 12:45:31 -0600 Subject: layers: Update swapchainMap to use unique_ptr --- layers/core_validation.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 53b416f4..a281d804 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -102,7 +102,7 @@ struct CMD_POOL_INFO { struct devExts { bool wsi_enabled; - unordered_map swapchainMap; + unordered_map> swapchainMap; unordered_map imageToSwapchainMap; }; @@ -299,7 +299,7 @@ SWAPCHAIN_NODE *getSwapchainNode(const layer_data *dev_data, const VkSwapchainKH if (swp_it == dev_data->device_extensions.swapchainMap.end()) { return nullptr; } - return swp_it->second; + return swp_it->second.get(); } // Return swapchain for specified image or else NULL VkSwapchainKHR getSwapchainFromImage(const layer_data *dev_data, const VkImage image) { @@ -9675,9 +9675,8 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapc VkResult result = dev_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); if (VK_SUCCESS == result) { - SWAPCHAIN_NODE *psc_node = new SWAPCHAIN_NODE(pCreateInfo); std::lock_guard lock(global_lock); - dev_data->device_extensions.swapchainMap[*pSwapchain] = psc_node; + dev_data->device_extensions.swapchainMap[*pSwapchain] = unique_ptr(new SWAPCHAIN_NODE(pCreateInfo)); } return result; @@ -9708,7 +9707,6 @@ DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocatio dev_data->imageMap.erase(swapchain_image); } } - delete swapchain_data; dev_data->device_extensions.swapchainMap.erase(swapchain); } lock.unlock(); -- cgit v1.2.3 From 67c0cc3e076ebb99072c4613ef89e288956c6878 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 12:48:25 -0600 Subject: layers: Remove unneccessary consts --- layers/core_validation.cpp | 16 ++++++++-------- layers/core_validation_types.h | 18 +++++++++--------- 2 files changed, 17 insertions(+), 17 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index a281d804..1f0d8989 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -262,7 +262,7 @@ struct shader_module { static std::mutex global_lock; // Return ImageViewCreateInfo ptr for specified imageView or else NULL -VkImageViewCreateInfo *getImageViewData(const layer_data *dev_data, const VkImageView image_view) { +VkImageViewCreateInfo *getImageViewData(const layer_data *dev_data, VkImageView image_view) { auto iv_it = dev_data->imageViewMap.find(image_view); if (iv_it == dev_data->imageViewMap.end()) { return nullptr; @@ -270,7 +270,7 @@ VkImageViewCreateInfo *getImageViewData(const layer_data *dev_data, const VkImag return iv_it->second.get(); } // Return sampler node ptr for specified sampler or else NULL -SAMPLER_NODE *getSamplerNode(const layer_data *dev_data, const VkSampler sampler) { +SAMPLER_NODE *getSamplerNode(const layer_data *dev_data, VkSampler sampler) { auto sampler_it = dev_data->samplerMap.find(sampler); if (sampler_it == dev_data->samplerMap.end()) { return nullptr; @@ -278,7 +278,7 @@ SAMPLER_NODE *getSamplerNode(const layer_data *dev_data, const VkSampler sampler return sampler_it->second.get(); } // Return image node ptr for specified image or else NULL -IMAGE_NODE *getImageNode(const layer_data *dev_data, const VkImage image) { +IMAGE_NODE *getImageNode(const layer_data *dev_data, VkImage image) { auto img_it = dev_data->imageMap.find(image); if (img_it == dev_data->imageMap.end()) { return nullptr; @@ -286,7 +286,7 @@ IMAGE_NODE *getImageNode(const layer_data *dev_data, const VkImage image) { return img_it->second.get(); } // Return buffer node ptr for specified buffer or else NULL -BUFFER_NODE *getBufferNode(const layer_data *dev_data, const VkBuffer buffer) { +BUFFER_NODE *getBufferNode(const layer_data *dev_data, VkBuffer buffer) { auto buff_it = dev_data->bufferMap.find(buffer); if (buff_it == dev_data->bufferMap.end()) { return nullptr; @@ -294,7 +294,7 @@ BUFFER_NODE *getBufferNode(const layer_data *dev_data, const VkBuffer buffer) { return buff_it->second.get(); } // Return swapchain node for specified swapchain or else NULL -SWAPCHAIN_NODE *getSwapchainNode(const layer_data *dev_data, const VkSwapchainKHR swapchain) { +SWAPCHAIN_NODE *getSwapchainNode(const layer_data *dev_data, VkSwapchainKHR swapchain) { auto swp_it = dev_data->device_extensions.swapchainMap.find(swapchain); if (swp_it == dev_data->device_extensions.swapchainMap.end()) { return nullptr; @@ -302,7 +302,7 @@ SWAPCHAIN_NODE *getSwapchainNode(const layer_data *dev_data, const VkSwapchainKH return swp_it->second.get(); } // Return swapchain for specified image or else NULL -VkSwapchainKHR getSwapchainFromImage(const layer_data *dev_data, const VkImage image) { +VkSwapchainKHR getSwapchainFromImage(const layer_data *dev_data, VkImage image) { auto img_it = dev_data->device_extensions.imageToSwapchainMap.find(image); if (img_it == dev_data->device_extensions.imageToSwapchainMap.end()) { return VK_NULL_HANDLE; @@ -310,7 +310,7 @@ VkSwapchainKHR getSwapchainFromImage(const layer_data *dev_data, const VkImage i return img_it->second; } // Return buffer node ptr for specified buffer or else NULL -VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *my_data, const VkBufferView buffer_view) { +VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *my_data, VkBufferView buffer_view) { auto bv_it = my_data->bufferViewMap.find(buffer_view); if (bv_it == my_data->bufferViewMap.end()) { return nullptr; @@ -2668,7 +2668,7 @@ static bool validate_compute_pipeline(debug_report_data *report_data, PIPELINE_N &module, &entrypoint, enabledFeatures, shaderModuleMap); } // Return Set node ptr for specified set or else NULL -cvdescriptorset::DescriptorSet *getSetNode(const layer_data *my_data, const VkDescriptorSet set) { +cvdescriptorset::DescriptorSet *getSetNode(const layer_data *my_data, VkDescriptorSet set) { auto set_it = my_data->setMap.find(set); if (set_it == my_data->setMap.end()) { return NULL; diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 9ec81357..13aa21f2 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -485,15 +485,15 @@ struct GLOBAL_CB_NODE : public BASE_NODE { // Fwd declarations of layer_data and helpers to look-up state from layer_data maps namespace core_validation { struct layer_data; -cvdescriptorset::DescriptorSet *getSetNode(const layer_data *, const VkDescriptorSet); -BUFFER_NODE *getBufferNode(const layer_data *, const VkBuffer); -IMAGE_NODE *getImageNode(const layer_data *, const VkImage); -DEVICE_MEM_INFO *getMemObjInfo(const layer_data *, const VkDeviceMemory); -VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *, const VkBufferView); -SAMPLER_NODE *getSamplerNode(const layer_data *, const VkSampler); -VkImageViewCreateInfo *getImageViewData(const layer_data *, const VkImageView); -VkSwapchainKHR getSwapchainFromImage(const layer_data *, const VkImage); -SWAPCHAIN_NODE *getSwapchainNode(const layer_data *, const VkSwapchainKHR); +cvdescriptorset::DescriptorSet *getSetNode(const layer_data *, VkDescriptorSet); +BUFFER_NODE *getBufferNode(const layer_data *, VkBuffer); +IMAGE_NODE *getImageNode(const layer_data *, VkImage); +DEVICE_MEM_INFO *getMemObjInfo(const layer_data *, VkDeviceMemory); +VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *, VkBufferView); +SAMPLER_NODE *getSamplerNode(const layer_data *, VkSampler); +VkImageViewCreateInfo *getImageViewData(const layer_data *, VkImageView); +VkSwapchainKHR getSwapchainFromImage(const layer_data *, VkImage); +SWAPCHAIN_NODE *getSwapchainNode(const layer_data *, VkSwapchainKHR); } #endif // CORE_VALIDATION_TYPES_H_ -- cgit v1.2.3 From 5a0755a401c4e38dfc605bc3679435f1d1258d51 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 2 Jun 2016 13:02:17 -0600 Subject: layers: Clean up poolMap access Remove some unneeded passing of poolMap around and use getPoolNode() function in DescriptorSet class. --- layers/core_validation.cpp | 7 +++--- layers/core_validation_types.h | 3 +++ layers/descriptor_sets.cpp | 51 +++++++++++++++++++++--------------------- layers/descriptor_sets.h | 4 +--- 4 files changed, 32 insertions(+), 33 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 1f0d8989..49324b82 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -2037,7 +2037,7 @@ static FRAMEBUFFER_NODE *getFramebuffer(layer_data *my_data, VkFramebuffer frame return &it->second; } -static cvdescriptorset::DescriptorSetLayout const *getDescriptorSetLayout(layer_data const *my_data, VkDescriptorSetLayout dsLayout) { +cvdescriptorset::DescriptorSetLayout const *getDescriptorSetLayout(layer_data const *my_data, VkDescriptorSetLayout dsLayout) { auto it = my_data->descriptorSetLayoutMap.find(dsLayout); if (it == my_data->descriptorSetLayoutMap.end()) { return nullptr; @@ -3166,7 +3166,7 @@ static void deletePipelines(layer_data *my_data) { // Block of code at start here specifically for managing/tracking DSs // Return Pool node ptr for specified pool or else NULL -static DESCRIPTOR_POOL_NODE *getPoolNode(const layer_data *dev_data, const VkDescriptorPool pool) { +DESCRIPTOR_POOL_NODE *getPoolNode(const layer_data *dev_data, const VkDescriptorPool pool) { auto pool_it = dev_data->descriptorPoolMap.find(pool); if (pool_it == dev_data->descriptorPoolMap.end()) { return NULL; @@ -5914,8 +5914,7 @@ ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescript static bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, cvdescriptorset::AllocateDescriptorSetsData *common_data) { // All state checks for AllocateDescriptorSets is done in single function - return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data->report_data, pAllocateInfo, dev_data->descriptorSetLayoutMap, - dev_data->descriptorPoolMap, common_data); + return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data->report_data, pAllocateInfo, dev_data, common_data); } // Allocation state was good and call down chain was made so update state based on allocating descriptor sets static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo, diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 13aa21f2..ce51dba4 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -54,6 +54,7 @@ // Fwd declarations namespace cvdescriptorset { +class DescriptorSetLayout; class DescriptorSet; }; @@ -486,6 +487,8 @@ struct GLOBAL_CB_NODE : public BASE_NODE { namespace core_validation { struct layer_data; cvdescriptorset::DescriptorSet *getSetNode(const layer_data *, VkDescriptorSet); +cvdescriptorset::DescriptorSetLayout const *getDescriptorSetLayout(layer_data const *, VkDescriptorSetLayout); +DESCRIPTOR_POOL_NODE *getPoolNode(const layer_data *, const VkDescriptorPool); BUFFER_NODE *getBufferNode(const layer_data *, VkBuffer); IMAGE_NODE *getImageNode(const layer_data *, VkImage); DEVICE_MEM_INFO *getMemObjInfo(const layer_data *, VkDeviceMemory); diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 8ccd334e..a8e88cf8 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -1209,32 +1209,32 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri return true; } // Verify that the state at allocate time is correct, but don't actually allocate the sets yet -bool cvdescriptorset::ValidateAllocateDescriptorSets( - const debug_report_data *report_data, const VkDescriptorSetAllocateInfo *p_alloc_info, - const std::unordered_map &set_layout_map, - const std::unordered_map &pool_map, AllocateDescriptorSetsData *ds_data) { +bool cvdescriptorset::ValidateAllocateDescriptorSets(const debug_report_data *report_data, + const VkDescriptorSetAllocateInfo *p_alloc_info, + const core_validation::layer_data *dev_data, + AllocateDescriptorSetsData *ds_data) { bool skip_call = false; for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) { - auto layout_it = set_layout_map.find(p_alloc_info->pSetLayouts[i]); - if (layout_it == set_layout_map.end()) { + auto layout = getDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]); + if (!layout) { skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, reinterpret_cast(p_alloc_info->pSetLayouts[i]), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", reinterpret_cast(p_alloc_info->pSetLayouts[i])); } else { - ds_data->layout_nodes[i] = layout_it->second; + ds_data->layout_nodes[i] = layout; // Count total descriptors required per type - for (uint32_t j = 0; j < layout_it->second->GetBindingCount(); ++j) { - const auto &binding_layout = layout_it->second->GetDescriptorSetLayoutBindingPtrFromIndex(j); + for (uint32_t j = 0; j < layout->GetBindingCount(); ++j) { + const auto &binding_layout = layout->GetDescriptorSetLayoutBindingPtrFromIndex(j); uint32_t typeIndex = static_cast(binding_layout->descriptorType); ds_data->required_descriptors_by_type[typeIndex] += binding_layout->descriptorCount; } } } - auto pool_it = pool_map.find(p_alloc_info->descriptorPool); - if (pool_it == pool_map.end()) { + auto pool_node = getPoolNode(dev_data, p_alloc_info->descriptorPool); + if (!pool_node) { skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, reinterpret_cast(p_alloc_info->descriptorPool), __LINE__, DRAWSTATE_INVALID_POOL, "DS", @@ -1242,24 +1242,23 @@ bool cvdescriptorset::ValidateAllocateDescriptorSets( reinterpret_cast(p_alloc_info->descriptorPool)); } else { // Make sure pool has all the available descriptors before calling down chain // Track number of descriptorSets allowable in this pool - if (pool_it->second->availableSets < p_alloc_info->descriptorSetCount) { - skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, - reinterpret_cast(pool_it->second->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, - "DS", "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64 - ". This pool only has %d descriptorSets remaining.", - p_alloc_info->descriptorSetCount, reinterpret_cast(pool_it->second->pool), - pool_it->second->availableSets); + if (pool_node->availableSets < p_alloc_info->descriptorSetCount) { + skip_call |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, + reinterpret_cast(pool_node->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS", + "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64 + ". This pool only has %d descriptorSets remaining.", + p_alloc_info->descriptorSetCount, reinterpret_cast(pool_node->pool), pool_node->availableSets); } // Determine whether descriptor counts are satisfiable for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) { - if (ds_data->required_descriptors_by_type[i] > pool_it->second->availableDescriptorTypeCount[i]) { - skip_call |= - log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, - reinterpret_cast(pool_it->second->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, - "DS", "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64 - ". This pool only has %d descriptors of this type remaining.", - ds_data->required_descriptors_by_type[i], string_VkDescriptorType(VkDescriptorType(i)), - reinterpret_cast(pool_it->second->pool), pool_it->second->availableDescriptorTypeCount[i]); + if (ds_data->required_descriptors_by_type[i] > pool_node->availableDescriptorTypeCount[i]) { + skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT, + reinterpret_cast(pool_node->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, + "DS", "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64 + ". This pool only has %d descriptors of this type remaining.", + ds_data->required_descriptors_by_type[i], string_VkDescriptorType(VkDescriptorType(i)), + reinterpret_cast(pool_node->pool), pool_node->availableDescriptorTypeCount[i]); } } } diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 1b7ebb4a..d53d97f5 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -257,9 +257,7 @@ void PerformUpdateDescriptorSets(const core_validation::layer_data *, uint32_t, const VkCopyDescriptorSet *); // Validate that Allocation state is ok bool ValidateAllocateDescriptorSets(const debug_report_data *, const VkDescriptorSetAllocateInfo *, - const std::unordered_map &, - const std::unordered_map &, - AllocateDescriptorSetsData *); + const core_validation::layer_data *, AllocateDescriptorSetsData *); // Update state based on allocating new descriptorsets void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, const AllocateDescriptorSetsData *, std::unordered_map *, -- cgit v1.2.3 From 849ffee6d36b3f7c6e6723c4b62f56822c3741e5 Mon Sep 17 00:00:00 2001 From: Mark Lobodzinski Date: Thu, 19 May 2016 15:27:18 -0600 Subject: layers: Add default layer error message config Allows layers to output error messages even if no vk_layer_settings.txt config file is present. Sets defaults to LOG_MSG, error, stdout. A layer settings file will override any default values. If no settings file is present and an app creates a debug callback, the default callbacks will be removed and unregistered. Change-Id: I49f37189665816df58c258b9e9629f2bf76751c8 --- include/vulkan/vk_layer.h | 20 +++-- layers/core_validation.cpp | 2 +- layers/device_limits.cpp | 2 +- layers/image.cpp | 2 +- layers/parameter_validation.cpp | 2 +- layers/swapchain.cpp | 2 +- layers/threading.cpp | 2 +- layers/vk_layer_config.cpp | 168 ++++++++++++++++-------------------- layers/vk_layer_config.h | 26 +++++- layers/vk_layer_logging.h | 183 +++++++++++++++++++++++----------------- layers/vk_layer_utils.cpp | 29 +++++-- vk-layer-generate.py | 3 +- 12 files changed, 245 insertions(+), 196 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/include/vulkan/vk_layer.h b/include/vulkan/vk_layer.h index cf16b2b7..6f49e07f 100644 --- a/include/vulkan/vk_layer.h +++ b/include/vulkan/vk_layer.h @@ -234,22 +234,28 @@ typedef struct VkLayerInstanceDispatchTable_ { CreateDisplayPlaneSurfaceKHR; } VkLayerInstanceDispatchTable; + // LL node for tree of dbg callback functions typedef struct VkLayerDbgFunctionNode_ { VkDebugReportCallbackEXT msgCallback; PFN_vkDebugReportCallbackEXT pfnMsgCallback; VkFlags msgFlags; void *pUserData; + bool default_callback; struct VkLayerDbgFunctionNode_ *pNext; } VkLayerDbgFunctionNode; -typedef enum VkLayerDbgAction_ { - VK_DBG_LAYER_ACTION_IGNORE = 0x0, - VK_DBG_LAYER_ACTION_CALLBACK = 0x1, - VK_DBG_LAYER_ACTION_LOG_MSG = 0x2, - VK_DBG_LAYER_ACTION_BREAK = 0x4, - VK_DBG_LAYER_ACTION_DEBUG_OUTPUT = 0x8, -} VkLayerDbgAction; +// TODO: Move debug action definitions out of this header file +// Definitions for Debug Actions +typedef enum VkLayerDbgActionBits { + VK_DBG_LAYER_ACTION_IGNORE = 0x00000000, + VK_DBG_LAYER_ACTION_CALLBACK = 0x00000001, + VK_DBG_LAYER_ACTION_LOG_MSG = 0x00000002, + VK_DBG_LAYER_ACTION_BREAK = 0x00000004, + VK_DBG_LAYER_ACTION_DEBUG_OUTPUT = 0x00000008, + VK_DBG_LAYER_ACTION_DEFAULT = 0x40000000, +} VkLayerDbgActionBits; +typedef VkFlags VkLayerDbgActionFlags; // ------------------------------------------------------------------------------------------------ // CreateInstance and CreateDevice support structures diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 49324b82..b602b7cd 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -9857,7 +9857,7 @@ CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCre VkResult res = pTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); if (VK_SUCCESS == res) { std::lock_guard lock(global_lock); - res = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback); + res = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); } return res; } diff --git a/layers/device_limits.cpp b/layers/device_limits.cpp index df52cf31..374911b4 100644 --- a/layers/device_limits.cpp +++ b/layers/device_limits.cpp @@ -647,7 +647,7 @@ CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCre layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); VkResult res = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); if (VK_SUCCESS == res) { - res = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback); + res = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); } return res; } diff --git a/layers/image.cpp b/layers/image.cpp index 81140e9d..1fb7d5a0 100644 --- a/layers/image.cpp +++ b/layers/image.cpp @@ -90,7 +90,7 @@ CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCre layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); VkResult res = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); if (res == VK_SUCCESS) { - res = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback); + res = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); } return res; } diff --git a/layers/parameter_validation.cpp b/layers/parameter_validation.cpp index c70142bb..fe9e391c 100644 --- a/layers/parameter_validation.cpp +++ b/layers/parameter_validation.cpp @@ -111,7 +111,7 @@ CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCre if (result == VK_SUCCESS) { layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map); - result = layer_create_msg_callback(data->report_data, pCreateInfo, pAllocator, pMsgCallback); + result = layer_create_msg_callback(data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); } return result; diff --git a/layers/swapchain.cpp b/layers/swapchain.cpp index 1642468d..96691f14 100644 --- a/layers/swapchain.cpp +++ b/layers/swapchain.cpp @@ -2099,7 +2099,7 @@ CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCre my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); if (VK_SUCCESS == result) { std::lock_guard lock(global_lock); - result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback); + result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); } return result; } diff --git a/layers/threading.cpp b/layers/threading.cpp index f5d37eba..c69a8b62 100644 --- a/layers/threading.cpp +++ b/layers/threading.cpp @@ -285,7 +285,7 @@ CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCre VkResult result = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback); if (VK_SUCCESS == result) { - result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback); + result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback); } finishReadObject(my_data, instance); return result; diff --git a/layers/vk_layer_config.cpp b/layers/vk_layer_config.cpp index d67f4053..049ffdcc 100644 --- a/layers/vk_layer_config.cpp +++ b/layers/vk_layer_config.cpp @@ -19,6 +19,7 @@ * Author: Jon Ashburn * Author: Courtney Goeltzenleuchter * Author: Tobin Ehlis + * Author: Mark Lobodzinski **************************************************************************/ #include #include @@ -48,50 +49,10 @@ class ConfigFile { static ConfigFile g_configFileObj; -static VkLayerDbgAction stringToDbgAction(const char *_enum) { - // only handles single enum values - if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_IGNORE")) - return VK_DBG_LAYER_ACTION_IGNORE; - else if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_LOG_MSG")) - return VK_DBG_LAYER_ACTION_LOG_MSG; -#ifdef WIN32 - else if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_DEBUG_OUTPUT")) - return VK_DBG_LAYER_ACTION_DEBUG_OUTPUT; -#endif - else if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_BREAK")) - return VK_DBG_LAYER_ACTION_BREAK; - return (VkLayerDbgAction)0; -} - -static VkFlags stringToDbgReportFlags(const char *_enum) { - // only handles single enum values - if (!strcmp(_enum, "VK_DEBUG_REPORT_INFO")) - return VK_DEBUG_REPORT_INFORMATION_BIT_EXT; - else if (!strcmp(_enum, "VK_DEBUG_REPORT_WARN")) - return VK_DEBUG_REPORT_WARNING_BIT_EXT; - else if (!strcmp(_enum, "VK_DEBUG_REPORT_PERF_WARN")) - return VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; - else if (!strcmp(_enum, "VK_DEBUG_REPORT_ERROR")) - return VK_DEBUG_REPORT_ERROR_BIT_EXT; - else if (!strcmp(_enum, "VK_DEBUG_REPORT_DEBUG")) - return VK_DEBUG_REPORT_DEBUG_BIT_EXT; - return (VkFlags)0; -} - -static unsigned int convertStringEnumVal(const char *_enum) { - unsigned int ret; - - ret = stringToDbgAction(_enum); - if (ret) - return ret; - - return stringToDbgReportFlags(_enum); -} - const char *getLayerOption(const char *_option) { return g_configFileObj.getOption(_option); } // If option is NULL or stdout, return stdout, otherwise try to open option -// as a filename. If successful, return file handle, otherwise stdout +// as a filename. If successful, return file handle, otherwise stdout FILE *getLayerLogOutput(const char *_option, const char *layerName) { FILE *log_output = NULL; if (!_option || !strcmp("stdout", _option)) @@ -110,64 +71,84 @@ FILE *getLayerLogOutput(const char *_option, const char *layerName) { return log_output; } -VkDebugReportFlagsEXT getLayerOptionFlags(const char *_option, uint32_t optionDefault) { - VkDebugReportFlagsEXT flags = optionDefault; - const char *option = (g_configFileObj.getOption(_option)); - - /* parse comma-separated options */ - while (option) { - const char *p = strchr(option, ','); - size_t len; - - if (p) - len = p - option; - else - len = strlen(option); - - if (len > 0) { - if (strncmp(option, "warn", len) == 0) { - flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT; - } else if (strncmp(option, "info", len) == 0) { - flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT; - } else if (strncmp(option, "perf", len) == 0) { - flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; - } else if (strncmp(option, "error", len) == 0) { - flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT; - } else if (strncmp(option, "debug", len) == 0) { - flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT; - } +// Map option strings to flag enum values +VkFlags GetLayerOptionFlags(std::string _option, std::unordered_map const &enum_data, + uint32_t option_default) { + VkDebugReportFlagsEXT flags = option_default; + std::string option_list = g_configFileObj.getOption(_option.c_str()); + + while (option_list.length() != 0) { + + // Find length of option string + std::size_t option_length = option_list.find(","); + if (option_length == option_list.npos) { + option_length = option_list.size(); } - if (!p) - break; + // Get first option in list + const std::string option = option_list.substr(0, option_length); - option = p + 1; - } - return flags; -} + auto enum_value = enum_data.find(option); + if (enum_value != enum_data.end()) { + flags |= enum_value->second; + } -bool getLayerOptionEnum(const char *_option, uint32_t *optionDefault) { - bool res; - const char *option = (g_configFileObj.getOption(_option)); - if (option != NULL) { - *optionDefault = convertStringEnumVal(option); - res = false; - } else { - res = true; + // Remove first option from option_list + option_list.erase(0, option_length); + // Remove possible comma separator + std::size_t char_position = option_list.find(","); + if (char_position == 0) { + option_list.erase(char_position, 1); + } + // Remove possible space + char_position = option_list.find(" "); + if (char_position == 0) { + option_list.erase(char_position, 1); + } } - return res; -} - -void setLayerOptionEnum(const char *_option, const char *_valEnum) { - unsigned int val = convertStringEnumVal(_valEnum); - char strVal[24]; - snprintf(strVal, 24, "%u", val); - g_configFileObj.setOption(_option, strVal); + return flags; } void setLayerOption(const char *_option, const char *_val) { g_configFileObj.setOption(_option, _val); } -ConfigFile::ConfigFile() : m_fileIsParsed(false) {} +// Constructor for ConfigFile. Initialize layers to log error messages to stdout by default. If a vk_layer_settings file is present, +// its settings will override the defaults. +ConfigFile::ConfigFile() : m_fileIsParsed(false) { + m_valueMap["lunarg_device_limits.report_flags"] = "error"; + m_valueMap["lunarg_core_validation.report_flags"] = "error"; + m_valueMap["lunarg_image.report_flags"] = "error"; + m_valueMap["lunarg_object_tracker.report_flags"] = "error"; + m_valueMap["lunarg_parameter_validation.report_flags"] = "error"; + m_valueMap["lunarg_swapchain.report_flags"] = "error"; + m_valueMap["google_threading.report_flags"] = "error"; + +#ifdef WIN32 + // For Windows, enable message logging AND OutputDebugString + m_valueMap["lunarg_device_limits.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"; + m_valueMap["lunarg_core_validation.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"; + m_valueMap["lunarg_image.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"; + m_valueMap["lunarg_object_tracker.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"; + m_valueMap["lunarg_parameter_validation.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"; + m_valueMap["lunarg_swapchain.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"; + m_valueMap["google_threading.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"; +#else // WIN32 + m_valueMap["lunarg_device_limits.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG"; + m_valueMap["lunarg_core_validation.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG"; + m_valueMap["lunarg_image.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG"; + m_valueMap["lunarg_object_tracker.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG"; + m_valueMap["lunarg_parameter_validation.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG"; + m_valueMap["lunarg_swapchain.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG"; + m_valueMap["google_threading.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG"; +#endif // WIN32 + + m_valueMap["lunarg_device_limits.log_filename"] = "stdout"; + m_valueMap["lunarg_core_validation.log_filename"] = "stdout"; + m_valueMap["lunarg_image.log_filename"] = "stdout"; + m_valueMap["lunarg_object_tracker.log_filename"] = "stdout"; + m_valueMap["lunarg_parameter_validation.log_filename"] = "stdout"; + m_valueMap["lunarg_swapchain.log_filename"] = "stdout"; + m_valueMap["google_threading.log_filename"] = "stdout"; +} ConfigFile::~ConfigFile() {} @@ -178,7 +159,7 @@ const char *ConfigFile::getOption(const std::string &_option) { } if ((it = m_valueMap.find(_option)) == m_valueMap.end()) - return NULL; + return ""; else return it->second.c_str(); } @@ -196,11 +177,12 @@ void ConfigFile::parseFile(const char *filename) { char buf[MAX_CHARS_PER_LINE]; m_fileIsParsed = true; - m_valueMap.clear(); file.open(filename); - if (!file.good()) + if (!file.good()) { return; + } + // read tokens from the file and form option, value pairs file.getline(buf, MAX_CHARS_PER_LINE); diff --git a/layers/vk_layer_config.h b/layers/vk_layer_config.h index 92865f69..8530a977 100644 --- a/layers/vk_layer_config.h +++ b/layers/vk_layer_config.h @@ -15,9 +15,12 @@ * limitations under the License. * * Author: Jon Ashburn + * Author: Mark Lobodzinski **************************************************************************/ #pragma once #include "vulkan/vulkan.h" +#include "vulkan/vk_layer.h" +#include #include #include @@ -25,14 +28,31 @@ extern "C" { #endif +const std::unordered_map debug_actions_option_definitions = { + {std::string("VK_DBG_LAYER_ACTION_IGNORE"), VK_DBG_LAYER_ACTION_IGNORE}, + {std::string("VK_DBG_LAYER_ACTION_CALLBACK"), VK_DBG_LAYER_ACTION_CALLBACK}, + {std::string("VK_DBG_LAYER_ACTION_LOG_MSG"), VK_DBG_LAYER_ACTION_LOG_MSG}, + {std::string("VK_DBG_LAYER_ACTION_BREAK"), VK_DBG_LAYER_ACTION_BREAK}, +#if WIN32 + {std::string("VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"), VK_DBG_LAYER_ACTION_DEBUG_OUTPUT}, +#endif + {std::string("VK_DBG_LAYER_ACTION_DEFAULT"), VK_DBG_LAYER_ACTION_DEFAULT}}; + +const std::unordered_map report_flags_option_definitions = { + {std::string("warn"), VK_DEBUG_REPORT_WARNING_BIT_EXT}, + {std::string("info"), VK_DEBUG_REPORT_INFORMATION_BIT_EXT}, + {std::string("perf"), VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT}, + {std::string("error"), VK_DEBUG_REPORT_ERROR_BIT_EXT}, + {std::string("debug"), VK_DEBUG_REPORT_DEBUG_BIT_EXT}}; + const char *getLayerOption(const char *_option); FILE *getLayerLogOutput(const char *_option, const char *layerName); -VkDebugReportFlagsEXT getLayerOptionFlags(const char *_option, uint32_t optionDefault); -bool getLayerOptionEnum(const char *_option, uint32_t *optionDefault); +VkFlags GetLayerOptionFlags(std::string _option, std::unordered_map const &enum_data, + uint32_t option_default); void setLayerOption(const char *_option, const char *_val); -void setLayerOptionEnum(const char *_option, const char *_valEnum); void print_msg_flags(VkFlags msgFlags, char *msg_flags); + #ifdef __cplusplus } #endif diff --git a/layers/vk_layer_logging.h b/layers/vk_layer_logging.h index 49470b18..cb4c44c7 100644 --- a/layers/vk_layer_logging.h +++ b/layers/vk_layer_logging.h @@ -32,9 +32,11 @@ #include #include #include +#include typedef struct _debug_report_data { - VkLayerDbgFunctionNode *g_pDbgFunctionHead; + VkLayerDbgFunctionNode *debug_callback_list; + VkLayerDbgFunctionNode *default_debug_callback_list; VkFlags active_flags; bool g_DEBUG_REPORT; } debug_report_data; @@ -42,12 +44,78 @@ typedef struct _debug_report_data { template debug_report_data *get_my_data_ptr(void *data_key, std::unordered_map &data_map); +// Forward Declarations +static inline bool debug_report_log_msg(const debug_report_data *debug_data, VkFlags msgFlags, + VkDebugReportObjectTypeEXT objectType, uint64_t srcObject, size_t location, int32_t msgCode, + const char *pLayerPrefix, const char *pMsg); + +// Add a debug message callback node structure to the specified callback linked list +static inline void AddDebugMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head, + VkLayerDbgFunctionNode *new_node) { + + new_node->pNext = *list_head; + *list_head = new_node; +} + +// Remove specified debug message callback node structure from the specified callback linked list +static inline void RemoveDebugMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head, + VkDebugReportCallbackEXT callback) { + VkLayerDbgFunctionNode *cur_callback = *list_head; + VkLayerDbgFunctionNode *prev_callback = cur_callback; + bool matched = false; + + debug_data->active_flags = 0; + while (cur_callback) { + if (cur_callback->msgCallback == callback) { + matched = true; + prev_callback->pNext = cur_callback->pNext; + if (*list_head == cur_callback) { + *list_head = cur_callback->pNext; + } + debug_report_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, + reinterpret_cast(cur_callback->msgCallback), 0, VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT, + "DebugReport", "Destroyed callback"); + } else { + matched = false; + debug_data->active_flags |= cur_callback->msgFlags; + } + prev_callback = cur_callback; + cur_callback = cur_callback->pNext; + if (matched) { + free(prev_callback); + } + } +} + +// Removes all debug callback function nodes from the specified callback linked lists and frees their resources +static inline void RemoveAllMessageCallbacks(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head) { + VkLayerDbgFunctionNode *current_callback = *list_head; + VkLayerDbgFunctionNode *prev_callback = current_callback; + + while (current_callback) { + prev_callback = current_callback->pNext; + debug_report_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, + (uint64_t)current_callback->msgCallback, 0, VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT, "DebugReport", + "Debug Report callbacks not removed before DestroyInstance"); + free(current_callback); + current_callback = prev_callback; + } + *list_head = NULL; +} + // Utility function to handle reporting -static inline bool debug_report_log_msg(const debug_report_data *debug_data, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType, - uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, - const char *pMsg) { +static inline bool debug_report_log_msg(const debug_report_data *debug_data, VkFlags msgFlags, + VkDebugReportObjectTypeEXT objectType, uint64_t srcObject, size_t location, int32_t msgCode, + const char *pLayerPrefix, const char *pMsg) { bool bail = false; - VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead; + VkLayerDbgFunctionNode *pTrav = NULL; + + if (debug_data->debug_callback_list != NULL) { + pTrav = debug_data->debug_callback_list; + } else { + pTrav = debug_data->default_debug_callback_list; + } + while (pTrav) { if (pTrav->msgFlags & msgFlags) { if (pTrav->pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg, pTrav->pUserData)) { @@ -77,7 +145,7 @@ debug_report_create_instance(VkLayerInstanceDispatchTable *table, VkInstance ins memset(debug_data, 0, sizeof(debug_report_data)); for (uint32_t i = 0; i < extension_count; i++) { - /* TODO: Check other property fields */ + // TODO: Check other property fields if (strcmp(ppEnabledExtensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) { debug_data->g_DEBUG_REPORT = true; } @@ -86,42 +154,32 @@ debug_report_create_instance(VkLayerInstanceDispatchTable *table, VkInstance ins } static inline void layer_debug_report_destroy_instance(debug_report_data *debug_data) { - VkLayerDbgFunctionNode *pTrav; - VkLayerDbgFunctionNode *pTravNext; - - if (!debug_data) { - return; - } - - pTrav = debug_data->g_pDbgFunctionHead; - /* Clear out any leftover callbacks */ - while (pTrav) { - pTravNext = pTrav->pNext; - - debug_report_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, - (uint64_t)pTrav->msgCallback, 0, VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT, "DebugReport", - "Debug Report callbacks not removed before DestroyInstance"); - - free(pTrav); - pTrav = pTravNext; + if (debug_data) { + RemoveAllMessageCallbacks(debug_data, &debug_data->default_debug_callback_list); + RemoveAllMessageCallbacks(debug_data, &debug_data->debug_callback_list); + free(debug_data); } - debug_data->g_pDbgFunctionHead = NULL; - - free(debug_data); } static inline debug_report_data *layer_debug_report_create_device(debug_report_data *instance_debug_data, VkDevice device) { - /* DEBUG_REPORT shares data between Instance and Device, - * so just return instance's data pointer */ + // DEBUG_REPORT shares data between Instance and Device, + // so just return instance's data pointer return instance_debug_data; } -static inline void layer_debug_report_destroy_device(VkDevice device) { /* Nothing to do since we're using instance data record */ } +static inline void layer_debug_report_destroy_device(VkDevice device) { + // Nothing to do since we're using instance data record +} -static inline VkResult layer_create_msg_callback(debug_report_data *debug_data, +static inline void layer_destroy_msg_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback, + const VkAllocationCallbacks *pAllocator) { + RemoveDebugMessageCallback(debug_data, &debug_data->debug_callback_list, callback); + RemoveDebugMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback); +} + +static inline VkResult layer_create_msg_callback(debug_report_data *debug_data, bool default_callback, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) { - /* TODO: Use app allocator */ VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode)); if (!pNewDbgFuncNode) return VK_ERROR_OUT_OF_HOST_MEMORY; @@ -133,9 +191,12 @@ static inline VkResult layer_create_msg_callback(debug_report_data *debug_data, pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback; pNewDbgFuncNode->msgFlags = pCreateInfo->flags; pNewDbgFuncNode->pUserData = pCreateInfo->pUserData; - pNewDbgFuncNode->pNext = debug_data->g_pDbgFunctionHead; - debug_data->g_pDbgFunctionHead = pNewDbgFuncNode; + if (default_callback) { + AddDebugMessageCallback(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode); + } else { + AddDebugMessageCallback(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode); + } debug_data->active_flags |= pCreateInfo->flags; debug_report_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, @@ -143,36 +204,6 @@ static inline VkResult layer_create_msg_callback(debug_report_data *debug_data, return VK_SUCCESS; } -static inline void layer_destroy_msg_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback, - const VkAllocationCallbacks *pAllocator) { - VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead; - VkLayerDbgFunctionNode *pPrev = pTrav; - bool matched; - - debug_data->active_flags = 0; - while (pTrav) { - if (pTrav->msgCallback == callback) { - matched = true; - pPrev->pNext = pTrav->pNext; - if (debug_data->g_pDbgFunctionHead == pTrav) { - debug_data->g_pDbgFunctionHead = pTrav->pNext; - } - debug_report_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, - (uint64_t)pTrav->msgCallback, 0, VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT, "DebugReport", - "Destroyed callback"); - } else { - matched = false; - debug_data->active_flags |= pTrav->msgFlags; - } - pPrev = pTrav; - pTrav = pTrav->pNext; - if (matched) { - /* TODO: Use pAllocator */ - free(pPrev); - } - } -} - static inline PFN_vkVoidFunction debug_report_get_instance_proc_addr(debug_report_data *debug_data, const char *funcName) { if (!debug_data || !debug_data->g_DEBUG_REPORT) { return NULL; @@ -253,7 +284,7 @@ static VkResult layer_enable_tmp_callbacks(debug_report_data *debug_data, uint32 VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) { VkResult rtn = VK_SUCCESS; for (uint32_t i = 0; i < num_callbacks; i++) { - rtn = layer_create_msg_callback(debug_data, &infos[i], NULL, &callbacks[i]); + rtn = layer_create_msg_callback(debug_data, false, &infos[i], NULL, &callbacks[i]); if (rtn != VK_SUCCESS) { for (uint32_t j = 0; j < i; j++) { layer_destroy_msg_callback(debug_data, callbacks[j], NULL); @@ -273,14 +304,12 @@ static void layer_disable_tmp_callbacks(debug_report_data *debug_data, uint32_t } } -/* - * Checks if the message will get logged. - * Allows layer to defer collecting & formating data if the - * message will be discarded. - */ +// Checks if the message will get logged. +// Allows layer to defer collecting & formating data if the +// message will be discarded. static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msgFlags) { if (!debug_data || !(debug_data->active_flags & msgFlags)) { - /* message is not wanted */ + // Message is not wanted return false; } @@ -302,11 +331,9 @@ static inline int vasprintf(char **strp, char const *fmt, va_list ap) { } #endif -/* - * Output log message via DEBUG_REPORT - * Takes format and variable arg list so that output string - * is only computed if a message needs to be logged - */ +// Output log message via DEBUG_REPORT +// Takes format and variable arg list so that output string +// is only computed if a message needs to be logged #ifndef WIN32 static inline bool log_msg(const debug_report_data *debug_data, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType, uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *format, ...) @@ -316,7 +343,7 @@ static inline bool log_msg(const debug_report_data *debug_data, VkFlags msgFlags uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *format, ...) { if (!debug_data || !(debug_data->active_flags & msgFlags)) { - /* message is not wanted */ + // Message is not wanted return false; } @@ -324,7 +351,7 @@ static inline bool log_msg(const debug_report_data *debug_data, VkFlags msgFlags va_start(argptr, format); char *str; if (-1 == vasprintf(&str, format, argptr)) { - /* on failure, glibc vasprintf leaves str undefined */ + // On failure, glibc vasprintf leaves str undefined str = nullptr; } va_end(argptr); diff --git a/layers/vk_layer_utils.cpp b/layers/vk_layer_utils.cpp index 1c362706..d028ca65 100644 --- a/layers/vk_layer_utils.cpp +++ b/layers/vk_layer_utils.cpp @@ -604,11 +604,20 @@ VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) { return result; } +// Debug callbacks get created in three ways: +// o Application-defined debug callbacks +// o Through settings in a vk_layer_settings.txt file +// o By default, if neither an app-defined debug callback nor a vk_layer_settings.txt file is present +// +// At layer initialization time, default logging callbacks are created to output layer error messages. +// If a vk_layer_settings.txt file is present its settings will override any default settings. +// +// If a vk_layer_settings.txt file is present and an application defines a debug callback, both callbacks +// will be active. If no vk_layer_settings.txt file is present, creating an application-defined debug +// callback will cause the default callbacks to be unregisterd and removed. void layer_debug_actions(debug_report_data *report_data, std::vector &logging_callback, - const VkAllocationCallbacks *pAllocator, const char *layer_identifier) { + const VkAllocationCallbacks *pAllocator, const char *layer_identifier) { - uint32_t report_flags = 0; - uint32_t debug_action = 0; VkDebugReportCallbackEXT callback = VK_NULL_HANDLE; std::string report_flags_key = layer_identifier; @@ -618,9 +627,11 @@ void layer_debug_actions(debug_report_data *report_data, std::vectorreport_data,') + r_body.append(' false,') r_body.append(' pCreateInfo,') r_body.append(' pAllocator,') r_body.append(' pCallback);') @@ -311,7 +312,7 @@ class Subcommand(object): r_body.append(' VkResult result = instance_dispatch_table(instance)->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);') r_body.append(' if (VK_SUCCESS == result) {') r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);') - r_body.append(' result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pCallback);') + r_body.append(' result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pCallback);') r_body.append(' }') r_body.append(' return result;') r_body.append('}') -- cgit v1.2.3 From a2f7158ec4016adbca53bed110654edfb3a4c945 Mon Sep 17 00:00:00 2001 From: Tony Barbour Date: Mon, 6 Jun 2016 10:55:04 -0600 Subject: layers: Initialize write_in_use in eventMap entries Change-Id: Ic296788beb078f19a35b93b99df5dbf677c95122 --- layers/core_validation.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index b602b7cd..809023af 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -9662,6 +9662,7 @@ CreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAlloc std::lock_guard lock(global_lock); dev_data->eventMap[*pEvent].needsSignaled = false; dev_data->eventMap[*pEvent].in_use.store(0); + dev_data->eventMap[*pEvent].write_in_use = 0; dev_data->eventMap[*pEvent].stageMask = VkPipelineStageFlags(0); } return result; -- cgit v1.2.3 From f99171e3401949aa86e0c0cca31fca3c9b229b5d Mon Sep 17 00:00:00 2001 From: Jan-Harald Fredriksen Date: Wed, 8 Jun 2016 14:20:50 +0200 Subject: layers: PR629, Remove subpass warnings The validation layer checks for dependency between subpasses using the same attachments, but it also issues warnings if there are "only" implicit dependencies between two subpasses. This is explicitly allowed by the spec and should not cause validation warnings. Change-Id: I1039955d6d445e1ee234116c6da2e4dbaf9c7dd9 --- layers/core_validation.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 809023af..949276b6 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -8199,15 +8199,10 @@ static bool CheckDependencyExists(const layer_data *my_data, const int subpass, auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]); auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]); if (prev_elem == node.prev.end() && next_elem == node.next.end()) { - // If no dependency exits an implicit dependency still might. If so, warn and if not throw an error. + // If no dependency exits an implicit dependency still might. If not, throw an error. std::unordered_set processed_nodes; - if (FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) || - FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes)) { - skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, - __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", - "A dependency between subpasses %d and %d must exist but only an implicit one is specified.", - subpass, dependent_subpasses[k]); - } else { + if (!(FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) || + FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes))) { skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", "A dependency between subpasses %d and %d must exist but one is not specified.", subpass, -- cgit v1.2.3 From 7fc7916db5da17cb54667dcd1630eca9d58e860e Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Wed, 8 Jun 2016 09:51:34 +1200 Subject: layers: remove tracking of last queue and fence for CB Unused. Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 4 ---- layers/core_validation_types.h | 2 -- 2 files changed, 6 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 949276b6..07f151db 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3675,8 +3675,6 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { pCB->activeRenderPass = nullptr; pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE; pCB->activeSubpass = 0; - pCB->lastSubmittedFence = VK_NULL_HANDLE; - pCB->lastSubmittedQueue = VK_NULL_HANDLE; pCB->destroyedSets.clear(); pCB->updatedSets.clear(); pCB->destroyedFramebuffers.clear(); @@ -4582,8 +4580,6 @@ QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, V if (pCBNode) { pCBNode->semaphores = semaphoreList; pCBNode->submitCount++; // increment submit count - pCBNode->lastSubmittedFence = fence; - pCBNode->lastSubmittedQueue = queue; skipCall |= validatePrimaryCommandBufferState(dev_data, pCBNode); // Call submit-time functions to validate/update state for (auto &function : pCBNode->validate_functions) { diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index ce51dba4..7fef3e3c 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -441,8 +441,6 @@ struct GLOBAL_CB_NODE : public BASE_NODE { std::vector scissors; VkRenderPassBeginInfo activeRenderPassBeginInfo; uint64_t fenceId; - VkFence lastSubmittedFence; - VkQueue lastSubmittedQueue; RENDER_PASS_NODE *activeRenderPass; VkSubpassContents activeSubpassContents; uint32_t activeSubpass; -- cgit v1.2.3 From b1e628eccd9de88fa4ff46f7d104c41982f8cadc Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 10 Jun 2016 10:06:42 +1200 Subject: layers: Unify fence checks for queue functions Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 07f151db..01c125fd 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -4506,19 +4506,18 @@ static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NO return skipCall; } -VKAPI_ATTR VkResult VKAPI_CALL -QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) { +static bool +ValidateFenceForSubmit(layer_data *dev_data, VkFence fence) +{ bool skipCall = false; - layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map); - VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; - std::unique_lock lock(global_lock); - // First verify that fence is not in use + if (fence != VK_NULL_HANDLE) { - if ((submitCount != 0) && dev_data->fenceMap[fence].in_use.load()) { + if (dev_data->fenceMap[fence].in_use.load()) { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, (uint64_t)(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", "Fence 0x%" PRIx64 " is already in use by another submission.", (uint64_t)(fence)); } + if (!dev_data->fenceMap[fence].needsSignaled) { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, reinterpret_cast(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", @@ -4526,6 +4525,19 @@ QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, V reinterpret_cast(fence)); } } + + return skipCall; +} + +VKAPI_ATTR VkResult VKAPI_CALL +QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) { + bool skipCall = false; + layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map); + VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; + std::unique_lock lock(global_lock); + + skipCall |= ValidateFenceForSubmit(dev_data, fence); + // TODO : Review these old print functions and clean up as appropriate print_mem_list(dev_data); printCBList(dev_data); @@ -9548,21 +9560,8 @@ QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *p bool skip_call = false; std::unique_lock lock(global_lock); // First verify that fence is not in use + skip_call |= ValidateFenceForSubmit(dev_data, fence); if (fence != VK_NULL_HANDLE) { - auto fence_data = dev_data->fenceMap.find(fence); - if ((bindInfoCount != 0) && fence_data->second.in_use.load()) { - skip_call |= - log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, - reinterpret_cast(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", - "Fence 0x%" PRIx64 " is already in use by another submission.", reinterpret_cast(fence)); - } - if (!fence_data->second.needsSignaled) { - skip_call |= - log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, - reinterpret_cast(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", - "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", - reinterpret_cast(fence)); - } trackCommandBuffers(dev_data, queue, 0, nullptr, fence); } for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) { -- cgit v1.2.3 From 20f5d77ec2df63f69c818afad21b21f94f537701 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 10 Jun 2016 15:21:43 +1200 Subject: layers: Add helpers for getting fence and queue nodes Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 01c125fd..1ebd4a51 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -318,6 +318,22 @@ VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *my_data, VkBufferVie return bv_it->second.get(); } +FENCE_NODE *getFenceNode(layer_data *dev_data, VkFence fence) { + auto it = dev_data->fenceMap.find(fence); + if (it == dev_data->fenceMap.end()) { + return nullptr; + } + return &it->second; +} + +QUEUE_NODE *getQueueNode(layer_data *dev_data, VkQueue queue) { + auto it = dev_data->queueMap.find(queue); + if (it == dev_data->queueMap.end()) { + return nullptr; + } + return &it->second; +} + static VkDeviceMemory *get_object_mem_binding(layer_data *my_data, uint64_t handle, VkDebugReportObjectTypeEXT type) { switch (type) { case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: { -- cgit v1.2.3 From 9d7cfa74ea05b82310bf89b2dec24782e04f0fb9 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 10 Jun 2016 15:22:37 +1200 Subject: layers: Add members to FENCE_NODE and QUEUE_NODE to hold the handles We'd like to be able to get back to them from the tracking struct. Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 2 ++ layers/core_validation.h | 2 ++ 2 files changed, 4 insertions(+) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 1ebd4a51..7dbbd343 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -4841,6 +4841,7 @@ VKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyI auto result = dev_data->queues.emplace(*pQueue); if (result.second == true) { QUEUE_NODE *pQNode = &dev_data->queueMap[*pQueue]; + pQNode->queue = *pQueue; pQNode->device = device; } } @@ -5593,6 +5594,7 @@ CreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAlloc if (VK_SUCCESS == result) { std::lock_guard lock(global_lock); auto &fence_node = dev_data->fenceMap[*pFence]; + fence_node.fence = *pFence; fence_node.createInfo = *pCreateInfo; fence_node.needsSignaled = true; if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) { diff --git a/layers/core_validation.h b/layers/core_validation.h index 00420e48..26c3edc9 100644 --- a/layers/core_validation.h +++ b/layers/core_validation.h @@ -212,6 +212,7 @@ class FENCE_NODE : public BASE_NODE { public: using BASE_NODE::in_use; + VkFence fence; VkSwapchainKHR swapchain; // Swapchain that this fence is submitted against or NULL bool firstTimeFlag; // Fence was created in signaled state, avoid warnings for first use VkFenceCreateInfo createInfo; @@ -241,6 +242,7 @@ class EVENT_NODE : public BASE_NODE { class QUEUE_NODE { public: + VkQueue queue; VkDevice device; std::vector lastFences; #if MTMERGE -- cgit v1.2.3 From 33f842e263f11cbfd6211f0188a8c4b4dfd76da6 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 10 Jun 2016 15:25:12 +1200 Subject: layers: Note broken behavior around stealing tracking from other queues Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 7dbbd343..779addb7 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -4305,6 +4305,12 @@ static void updateTrackedCommandBuffers(layer_data *dev_data, VkQueue queue, VkQ fence_node->second.queues.insert(other_queue_data->first); } } + // TODO: Stealing the untracked CBs out of the signaling queue isn't really + // correct. A subsequent submission + wait, or a QWI on that queue, or + // another semaphore dependency to a third queue may /all/ provide + // suitable proof that the work we're stealing here has completed on the + // device, but we've lost that information by moving the tracking between + // queues. if (fence != VK_NULL_HANDLE) { auto fence_data = dev_data->fenceMap.find(fence); if (fence_data == dev_data->fenceMap.end()) { -- cgit v1.2.3 From f2ccbd9add820c5cba7c5a2e1e5aa8c85997053d Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Fri, 10 Jun 2016 15:25:45 +1200 Subject: layers: Fix mistracking of semaphores associated with submissions When a command buffer is simultaneously inflight multiple times, each can have different semaphores associated. Storing the set of semaphores on the GLOBAL_CB_NODE caused us to get confused and emit bogus errors. Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 167 ++++++++++++++++++++--------------------- layers/core_validation.h | 4 +- layers/core_validation_types.h | 1 - 3 files changed, 84 insertions(+), 88 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 779addb7..bfb934d4 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3695,7 +3695,6 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { pCB->updatedSets.clear(); pCB->destroyedFramebuffers.clear(); pCB->waitedEvents.clear(); - pCB->semaphores.clear(); pCB->events.clear(); pCB->waitedEventsBeforeQueryReset.clear(); pCB->queryToStateMap.clear(); @@ -4100,7 +4099,7 @@ static bool ValidateCmdBufImageLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB } // Track which resources are in-flight by atomically incrementing their "in_use" count -static bool validateAndIncrementResources(layer_data *my_data, GLOBAL_CB_NODE *pCB) { +static bool validateAndIncrementResources(layer_data *my_data, GLOBAL_CB_NODE *pCB, std::vector const &semaphores) { bool skip_call = false; for (auto drawDataElement : pCB->drawData) { for (auto buffer : drawDataElement.buffers) { @@ -4126,7 +4125,7 @@ static bool validateAndIncrementResources(layer_data *my_data, GLOBAL_CB_NODE *p } } } - for (auto semaphore : pCB->semaphores) { + for (auto semaphore : semaphores) { auto semaphoreNode = my_data->semaphoreMap.find(semaphore); if (semaphoreNode == my_data->semaphoreMap.end()) { skip_call |= @@ -4185,8 +4184,8 @@ static inline void removeInFlightCmdBuffer(layer_data *dev_data, VkCommandBuffer } } -static void decrementResources(layer_data *my_data, VkCommandBuffer cmdBuffer) { - GLOBAL_CB_NODE *pCB = getCBNode(my_data, cmdBuffer); +static void decrementResources(layer_data *my_data, CB_SUBMISSION *submission) { + GLOBAL_CB_NODE *pCB = getCBNode(my_data, submission->cb); for (auto drawDataElement : pCB->drawData) { for (auto buffer : drawDataElement.buffers) { auto buffer_node = getBufferNode(my_data, buffer); @@ -4200,7 +4199,7 @@ static void decrementResources(layer_data *my_data, VkCommandBuffer cmdBuffer) { set->in_use.fetch_sub(1); } } - for (auto semaphore : pCB->semaphores) { + for (auto semaphore : submission->semaphores) { auto semaphoreNode = my_data->semaphoreMap.find(semaphore); if (semaphoreNode != my_data->semaphoreMap.end()) { semaphoreNode->second.in_use.fetch_sub(1); @@ -4241,12 +4240,12 @@ static bool decrementResources(layer_data *my_data, uint32_t fenceCount, const V } decrementResources(my_data, static_cast(fence_data->second.priorFences.size()), fence_data->second.priorFences.data()); - for (auto cmdBuffer : fence_data->second.cmdBuffers) { - decrementResources(my_data, cmdBuffer); - skip_call |= cleanInFlightCmdBuffer(my_data, cmdBuffer); - removeInFlightCmdBuffer(my_data, cmdBuffer); + for (auto & submission : fence_data->second.submissions) { + decrementResources(my_data, &submission); + skip_call |= cleanInFlightCmdBuffer(my_data, submission.cb); + removeInFlightCmdBuffer(my_data, submission.cb); } - fence_data->second.cmdBuffers.clear(); + fence_data->second.submissions.clear(); fence_data->second.priorFences.clear(); } for (auto fence_pair : fence_pairs) { @@ -4273,12 +4272,12 @@ static bool decrementResources(layer_data *my_data, VkQueue queue) { bool skip_call = false; auto queue_data = my_data->queueMap.find(queue); if (queue_data != my_data->queueMap.end()) { - for (auto cmdBuffer : queue_data->second.untrackedCmdBuffers) { - decrementResources(my_data, cmdBuffer); - skip_call |= cleanInFlightCmdBuffer(my_data, cmdBuffer); - removeInFlightCmdBuffer(my_data, cmdBuffer); + for (auto & submission : queue_data->second.untrackedSubmissions) { + decrementResources(my_data, &submission); + skip_call |= cleanInFlightCmdBuffer(my_data, submission.cb); + removeInFlightCmdBuffer(my_data, submission.cb); } - queue_data->second.untrackedCmdBuffers.clear(); + queue_data->second.untrackedSubmissions.clear(); skip_call |= decrementResources(my_data, static_cast(queue_data->second.lastFences.size()), queue_data->second.lastFences.data()); } @@ -4316,15 +4315,15 @@ static void updateTrackedCommandBuffers(layer_data *dev_data, VkQueue queue, VkQ if (fence_data == dev_data->fenceMap.end()) { return; } - for (auto cmdbuffer : other_queue_data->second.untrackedCmdBuffers) { - fence_data->second.cmdBuffers.push_back(cmdbuffer); + for (auto cmdbuffer : other_queue_data->second.untrackedSubmissions) { + fence_data->second.submissions.push_back(cmdbuffer); } - other_queue_data->second.untrackedCmdBuffers.clear(); + other_queue_data->second.untrackedSubmissions.clear(); } else { - for (auto cmdbuffer : other_queue_data->second.untrackedCmdBuffers) { - queue_data->second.untrackedCmdBuffers.push_back(cmdbuffer); + for (auto cmdbuffer : other_queue_data->second.untrackedSubmissions) { + queue_data->second.untrackedSubmissions.push_back(cmdbuffer); } - other_queue_data->second.untrackedCmdBuffers.clear(); + other_queue_data->second.untrackedSubmissions.clear(); } for (auto eventStagePair : other_queue_data->second.eventToStageMap) { queue_data->second.eventToStageMap[eventStagePair.first] = eventStagePair.second; @@ -4342,51 +4341,24 @@ static void updateTrackedCommandBuffers(layer_data *dev_data, VkQueue queue, VkQ // waited on, prior fences on that queue are also considered to have been waited on. When a fence is // waited on (either via a queue, device or fence), we free the cmd buffers for that fence and // recursively call with the prior fences. -static void trackCommandBuffers(layer_data *my_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, - VkFence fence) { - auto queue_data = my_data->queueMap.find(queue); - if (fence != VK_NULL_HANDLE) { - vector prior_fences; - auto fence_data = my_data->fenceMap.find(fence); - if (fence_data == my_data->fenceMap.end()) { - return; - } - fence_data->second.cmdBuffers.clear(); - if (queue_data != my_data->queueMap.end()) { - prior_fences = queue_data->second.lastFences; - queue_data->second.lastFences.clear(); - queue_data->second.lastFences.push_back(fence); - for (auto cmdbuffer : queue_data->second.untrackedCmdBuffers) { - fence_data->second.cmdBuffers.push_back(cmdbuffer); - } - queue_data->second.untrackedCmdBuffers.clear(); - } - fence_data->second.priorFences = prior_fences; - fence_data->second.needsSignaled = true; - fence_data->second.queues.insert(queue); - fence_data->second.in_use.fetch_add(1); - for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { - const VkSubmitInfo *submit = &pSubmits[submit_idx]; - for (uint32_t i = 0; i < submit->commandBufferCount; ++i) { - for (auto secondaryCmdBuffer : my_data->commandBufferMap[submit->pCommandBuffers[i]]->secondaryCommandBuffers) { - fence_data->second.cmdBuffers.push_back(secondaryCmdBuffer); - } - fence_data->second.cmdBuffers.push_back(submit->pCommandBuffers[i]); - } - } - } else { - if (queue_data != my_data->queueMap.end()) { - for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { - const VkSubmitInfo *submit = &pSubmits[submit_idx]; - for (uint32_t i = 0; i < submit->commandBufferCount; ++i) { - for (auto secondaryCmdBuffer : my_data->commandBufferMap[submit->pCommandBuffers[i]]->secondaryCommandBuffers) { - queue_data->second.untrackedCmdBuffers.push_back(secondaryCmdBuffer); - } - queue_data->second.untrackedCmdBuffers.push_back(submit->pCommandBuffers[i]); - } - } - } - } + + +// Submit a fence to a queue, delimiting previous fences and previous untracked +// work by it. +static void +SubmitFence(QUEUE_NODE *pQueue, FENCE_NODE *pFence) +{ + assert(!pFence->priorFences.size()); + assert(!pFence->submissions.size()); + + std::swap(pFence->priorFences, pQueue->lastFences); + std::swap(pFence->submissions, pQueue->untrackedSubmissions); + + pFence->queues.insert(pQueue->queue); + pFence->needsSignaled = true; + pFence->in_use.fetch_add(1); + + pQueue->lastFences.push_back(pFence->fence); } static void markCommandBuffersInFlight(layer_data *my_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, @@ -4501,12 +4473,12 @@ static bool validateCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB return skipCall; } -static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB) { +static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, std::vector const &semaphores) { // Track in-use for resources off of primary and any secondary CBs - bool skipCall = validateAndIncrementResources(dev_data, pCB); + bool skipCall = validateAndIncrementResources(dev_data, pCB, semaphores); if (!pCB->secondaryCommandBuffers.empty()) { for (auto secondaryCmdBuffer : pCB->secondaryCommandBuffers) { - skipCall |= validateAndIncrementResources(dev_data, dev_data->commandBufferMap[secondaryCmdBuffer]); + skipCall |= validateAndIncrementResources(dev_data, dev_data->commandBufferMap[secondaryCmdBuffer], semaphores); GLOBAL_CB_NODE *pSubCB = getCBNode(dev_data, secondaryCmdBuffer); if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) && !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) { @@ -4529,28 +4501,29 @@ static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NO } static bool -ValidateFenceForSubmit(layer_data *dev_data, VkFence fence) +ValidateFenceForSubmit(layer_data *dev_data, FENCE_NODE *pFence) { bool skipCall = false; - if (fence != VK_NULL_HANDLE) { - if (dev_data->fenceMap[fence].in_use.load()) { + if (pFence) { + if (pFence->in_use.load()) { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, - (uint64_t)(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", - "Fence 0x%" PRIx64 " is already in use by another submission.", (uint64_t)(fence)); + (uint64_t)(pFence->fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", + "Fence 0x%" PRIx64 " is already in use by another submission.", (uint64_t)(pFence->fence)); } - if (!dev_data->fenceMap[fence].needsSignaled) { + if (!pFence->needsSignaled) { skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, - reinterpret_cast(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", + reinterpret_cast(pFence->fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", - reinterpret_cast(fence)); + reinterpret_cast(pFence->fence)); } } return skipCall; } + VKAPI_ATTR VkResult VKAPI_CALL QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) { bool skipCall = false; @@ -4558,13 +4531,25 @@ QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, V VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; std::unique_lock lock(global_lock); - skipCall |= ValidateFenceForSubmit(dev_data, fence); + auto pQueue = getQueueNode(dev_data, queue); + auto pFence = getFenceNode(dev_data, fence); + skipCall |= ValidateFenceForSubmit(dev_data, pFence); // TODO : Review these old print functions and clean up as appropriate print_mem_list(dev_data); printCBList(dev_data); - // Update cmdBuffer-related data structs and mark fence in-use - trackCommandBuffers(dev_data, queue, submitCount, pSubmits, fence); + + // Mark the fence in-use. + if (pFence) { + SubmitFence(pQueue, pFence); + } + + // If a fence is supplied, all the command buffers for this call will be + // delimited by that fence. Otherwise, they go in the untracked portion of + // the queue, and may end up being delimited by a fence supplied in a + // subsequent submission. + auto & submitTarget = pFence ? pFence->submissions : pQueue->untrackedSubmissions; + // Now verify each individual submit std::unordered_set processed_other_queues; for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { @@ -4608,13 +4593,20 @@ QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, V } } } + + // TODO: just add one submission per VkSubmitInfo! for (uint32_t i = 0; i < submit->commandBufferCount; i++) { auto pCBNode = getCBNode(dev_data, submit->pCommandBuffers[i]); skipCall |= ValidateCmdBufImageLayouts(dev_data, pCBNode); if (pCBNode) { - pCBNode->semaphores = semaphoreList; + + submitTarget.emplace_back(pCBNode->commandBuffer, semaphoreList); + for (auto secondaryCmdBuffer : pCBNode->secondaryCommandBuffers) { + submitTarget.emplace_back(secondaryCmdBuffer, semaphoreList); + } + pCBNode->submitCount++; // increment submit count - skipCall |= validatePrimaryCommandBufferState(dev_data, pCBNode); + skipCall |= validatePrimaryCommandBufferState(dev_data, pCBNode, semaphoreList); // Call submit-time functions to validate/update state for (auto &function : pCBNode->validate_functions) { skipCall |= function(); @@ -9583,11 +9575,16 @@ QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *p VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; bool skip_call = false; std::unique_lock lock(global_lock); + auto pFence = getFenceNode(dev_data, fence); + auto pQueue = getQueueNode(dev_data, queue); + // First verify that fence is not in use - skip_call |= ValidateFenceForSubmit(dev_data, fence); + skip_call |= ValidateFenceForSubmit(dev_data, pFence); + if (fence != VK_NULL_HANDLE) { - trackCommandBuffers(dev_data, queue, 0, nullptr, fence); + SubmitFence(pQueue, pFence); } + for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) { const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx]; // Track objects tied to memory diff --git a/layers/core_validation.h b/layers/core_validation.h index 26c3edc9..d3e7cd4d 100644 --- a/layers/core_validation.h +++ b/layers/core_validation.h @@ -217,7 +217,7 @@ class FENCE_NODE : public BASE_NODE { bool firstTimeFlag; // Fence was created in signaled state, avoid warnings for first use VkFenceCreateInfo createInfo; std::unordered_set queues; - std::vector cmdBuffers; + std::vector submissions; bool needsSignaled; std::vector priorFences; @@ -250,7 +250,7 @@ class QUEUE_NODE { std::list pQueueCommandBuffers; std::list pMemRefList; #endif - std::vector untrackedCmdBuffers; + std::vector untrackedSubmissions; std::unordered_map eventToStageMap; std::unordered_map queryToStateMap; // 0 is unavailable, 1 is available }; diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index 25d1e8cb..616a2e2c 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -453,7 +453,6 @@ struct GLOBAL_CB_NODE : public BASE_NODE { std::unordered_set destroyedFramebuffers; std::unordered_set waitedEvents; std::vector writeEventsBeforeWait; - std::vector semaphores; std::vector events; std::unordered_map> waitedEventsBeforeQueryReset; std::unordered_map queryToStateMap; // 0 is unavailable, 1 is available -- cgit v1.2.3 From dda1e861321cfda600472dd22df3a84bc7e57c15 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Mon, 13 Jun 2016 09:59:34 +1200 Subject: layers: Fix test fallout in CommandBufferTwoSubmits This test was accidentally triggering the fence reuse case as well, and blindly continuing past that error. It doesn't need to use the fence at all, so don't supply one. Also tweak the layer to not run into the assert if the caller elected to skip -- QueueSubmit still has validation and updates tangled together, but this improves it slightly. Signed-off-by: Chris Forbes --- layers/core_validation.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index bfb934d4..8d97dc21 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -4535,6 +4535,10 @@ QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, V auto pFence = getFenceNode(dev_data, fence); skipCall |= ValidateFenceForSubmit(dev_data, pFence); + if (skipCall) { + return VK_ERROR_VALIDATION_FAILED_EXT; + } + // TODO : Review these old print functions and clean up as appropriate print_mem_list(dev_data); printCBList(dev_data); -- cgit v1.2.3 From b3dd9b1367e59333e39687c838cf966cbdd7c47d Mon Sep 17 00:00:00 2001 From: Mark Lobodzinski Date: Mon, 13 Jun 2016 16:56:26 -0600 Subject: layers: Fix Windows Dota2 crash One of the event tracking lists was not getting cleared upon a reset, resulting in an invalid reference on reuse. Change-Id: I45d932822f27197266b363634d6cdccc785209d3 --- layers/core_validation.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 8d97dc21..2dbfd0ab 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -3696,6 +3696,7 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { pCB->destroyedFramebuffers.clear(); pCB->waitedEvents.clear(); pCB->events.clear(); + pCB->writeEventsBeforeWait.clear(); pCB->waitedEventsBeforeQueryReset.clear(); pCB->queryToStateMap.clear(); pCB->activeQueries.clear(); -- cgit v1.2.3 From efab294f76f083a03528364f68400ab415cdf74f Mon Sep 17 00:00:00 2001 From: Mark Lobodzinski Date: Tue, 14 Jun 2016 12:11:29 -0600 Subject: layers: LX539, Validate mem types Bind[Image|Buffer]Memory did not validate that the memoryPropertyType matched the memory_requirements memory type flags for the buffer or image. Change-Id: I7007588d78408689c34df66a17cc9201a37569b1 --- layers/core_validation.cpp | 20 ++++++++++++++++++-- layers/core_validation_error_enums.h | 1 + 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 2dbfd0ab..5f254f75 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5138,6 +5138,20 @@ VKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const Vk } } +static bool ValidateMemoryTypes(const layer_data *dev_data, const DEVICE_MEM_INFO *mem_info, const uint32_t memory_type_bits, + const char *funcName) { + bool skip_call = false; + if (((1 << mem_info->allocInfo.memoryTypeIndex) & memory_type_bits) == 0) { + skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, + reinterpret_cast(mem_info->mem), __LINE__, MEMTRACK_INVALID_MEM_TYPE, "MT", + "%s(): MemoryRequirements->memoryTypeBits (0x%X) for this object type are not compatible with the memory " + "type (0x%X) of this memory object 0x%" PRIx64 ".", + funcName, memory_type_bits, mem_info->allocInfo.memoryTypeIndex, + reinterpret_cast(mem_info->mem)); + } + return skip_call; +} + VKAPI_ATTR VkResult VKAPI_CALL BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) { layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); @@ -5159,6 +5173,7 @@ BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceS const MEMORY_RANGE range = insert_memory_ranges(buffer_handle, mem, memoryOffset, memRequirements, mem_info->bufferRanges); skipCall |= validate_memory_range(dev_data, mem_info->imageRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT); + skipCall |= ValidateMemoryTypes(dev_data, mem_info, memRequirements.memoryTypeBits, "BindBufferMemory"); } // Validate memory requirements alignment @@ -7818,10 +7833,10 @@ bool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCo if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_EVENT, "DS", "Submitting cmdbuffer with call to VkCmdWaitEvents " - "using srcStageMask 0x%x which must be the bitwise " + "using srcStageMask 0x%X which must be the bitwise " "OR of the stageMask parameters used in calls to " "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if " - "used with vkSetEvent but instead is 0x%x.", + "used with vkSetEvent but instead is 0x%X.", sourceStageMask, stageMask); } return skip_call; @@ -9521,6 +9536,7 @@ VKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, V const MEMORY_RANGE range = insert_memory_ranges(image_handle, mem, memoryOffset, memRequirements, mem_info->imageRanges); skipCall |= validate_memory_range(dev_data, mem_info->bufferRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT); + skipCall |= ValidateMemoryTypes(dev_data, mem_info, memRequirements.memoryTypeBits, "vkBindImageMemory"); } print_mem_list(dev_data); diff --git a/layers/core_validation_error_enums.h b/layers/core_validation_error_enums.h index e6d0ed37..3904bdf1 100644 --- a/layers/core_validation_error_enums.h +++ b/layers/core_validation_error_enums.h @@ -39,6 +39,7 @@ enum MEM_TRACK_ERROR { MEMTRACK_REBIND_OBJECT, // Non-sparse object bindings are immutable MEMTRACK_INVALID_USAGE_FLAG, // Usage flags specified at image/buffer create conflict w/ use of object MEMTRACK_INVALID_MAP, // Size flag specified at alloc is too small for mapping range + MEMTRACK_INVALID_MEM_TYPE, // Memory Type mismatch }; // Draw State ERROR codes -- cgit v1.2.3 From 03f0a3823838cf90d265ec9ef2d2e313eb698a0f Mon Sep 17 00:00:00 2001 From: Mark Lobodzinski Date: Thu, 16 Jun 2016 13:23:02 -0600 Subject: layers: GH576, Validate attachment image usage Framebuffer attachment images are created with IMAGE_USAGE flags. These flags are now validated against their attachment location in subpass description structures. Also added a check for a preserve attachment being set to UNUSED and fixed a few typos in the attachment index checking stuff. Change-Id: Id62d3539c490ce8f381d7ae606402980f11946fa --- layers/core_validation.cpp | 112 +++++++++++++++++++++++++++-------- layers/core_validation_error_enums.h | 4 ++ 2 files changed, 92 insertions(+), 24 deletions(-) (limited to 'layers/core_validation.cpp') diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 5f254f75..b3635a0b 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -8178,11 +8178,67 @@ CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelin dev_data->device_dispatch_table->CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot); } +static bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentReference *attachments, + const VkFramebufferCreateInfo *fbci, VkImageUsageFlagBits usage_flag) { + bool skip_call = false; + + for (uint32_t attach = 0; attach < count; attach++) { + if (attachments[attach].attachment != VK_ATTACHMENT_UNUSED) { + // Attachment counts are verified elsewhere, but prevent an invalid access + if (attachments[attach].attachment < fbci->attachmentCount) { + const VkImageView *image_view = &fbci->pAttachments[attachments[attach].attachment]; + VkImageViewCreateInfo *ivci = getImageViewData(dev_data, *image_view); + if (ivci != nullptr) { + const VkImageCreateInfo *ici = &getImageNode(dev_data, ivci->image)->createInfo; + if (ici != nullptr) { + if ((ici->usage & usage_flag) == 0) { + skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, + (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_USAGE, "DS", + "vkCreateFramebuffer: Framebuffer Attachment (%d) conflicts with the image's " + "IMAGE_USAGE flags (%s).", + attachments[attach].attachment, string_VkImageUsageFlagBits(usage_flag)); + } + } + } + } + } + } + return skip_call; +} + +static bool ValidateAttachmentImageUsage(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) { + bool skip_call = false; + + const VkRenderPassCreateInfo *rpci = getRenderPass(dev_data, pCreateInfo->renderPass)->pCreateInfo; + if (rpci != nullptr) { + for (uint32_t subpass = 0; subpass < rpci->subpassCount; subpass++) { + // Verify input attachments: + skip_call |= MatchUsage(dev_data, rpci->pSubpasses[subpass].inputAttachmentCount, + rpci->pSubpasses[subpass].pInputAttachments, pCreateInfo, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT); + // Verify color attachments: + skip_call |= MatchUsage(dev_data, rpci->pSubpasses[subpass].colorAttachmentCount, + rpci->pSubpasses[subpass].pColorAttachments, pCreateInfo, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + // Verify depth/stencil attachments: + if (rpci->pSubpasses[subpass].pDepthStencilAttachment != nullptr) { + skip_call |= MatchUsage(dev_data, 1, rpci->pSubpasses[subpass].pDepthStencilAttachment, pCreateInfo, + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + } + } + } + return skip_call; +} + VKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) { + bool skip_call = false; + VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); - VkResult result = dev_data->device_dispatch_table->CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer); + + skip_call |= ValidateAttachmentImageUsage(dev_data, pCreateInfo); + if (skip_call == false) { + result = dev_data->device_dispatch_table->CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer); + } if (VK_SUCCESS == result) { // Shadow create info and store in map std::lock_guard lock(global_lock); @@ -8668,22 +8724,28 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderP } // TODO: Maybe fill list and then copy instead of locking std::unordered_map &attachment_first_read = render_pass->attachment_first_read; - std::unordered_map &attachment_first_layout = - render_pass->attachment_first_layout; + std::unordered_map &attachment_first_layout = render_pass->attachment_first_layout; for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) { const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i]; if (subpass.pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS) { - skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, - __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", - "Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS.", i); + skip_call |= + log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, + DRAWSTATE_INVALID_RENDERPASS, "DS", + "CreateRenderPass: Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS.", i); } for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) { uint32_t attachment = subpass.pPreserveAttachments[j]; - if (attachment >= pCreateInfo->attachmentCount) { - skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, - __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", - "Preserve attachment %d cannot be greater than the total number of attachments %d.", - attachment, pCreateInfo->attachmentCount); + if (attachment == VK_ATTACHMENT_UNUSED) { + skip_call |= + log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, + DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS", + "CreateRenderPass: Preserve attachment (%d) must not be VK_ATTACHMENT_UNUSED.", j); + } else if (attachment >= pCreateInfo->attachmentCount) { + skip_call |= log_msg( + dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, + DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS", + "CreateRenderPass: Preserve attachment %d cannot be greater than the total number of attachments %d.", + attachment, pCreateInfo->attachmentCount); } } for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) { @@ -8691,19 +8753,21 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderP if (subpass.pResolveAttachments) { attachment = subpass.pResolveAttachments[j].attachment; if (attachment >= pCreateInfo->attachmentCount && attachment != VK_ATTACHMENT_UNUSED) { - skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, - __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", - "Color attachment %d cannot be greater than the total number of attachments %d.", - attachment, pCreateInfo->attachmentCount); + skip_call |= log_msg( + dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, + DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS", + "CreateRenderPass: Resolve attachment %d cannot be greater than the total number of attachments %d.", + attachment, pCreateInfo->attachmentCount); continue; } } attachment = subpass.pColorAttachments[j].attachment; - if (attachment >= pCreateInfo->attachmentCount) { - skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, - __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", - "Color attachment %d cannot be greater than the total number of attachments %d.", - attachment, pCreateInfo->attachmentCount); + if (attachment >= pCreateInfo->attachmentCount && attachment != VK_ATTACHMENT_UNUSED) { + skip_call |= + log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, + DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS", + "CreateRenderPass: Color attachment %d cannot be greater than the total number of attachments %d.", + attachment, pCreateInfo->attachmentCount); continue; } if (attachment_first_read.count(attachment)) @@ -8715,8 +8779,8 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderP uint32_t attachment = subpass.pDepthStencilAttachment->attachment; if (attachment >= pCreateInfo->attachmentCount) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, - __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", - "Depth stencil attachment %d cannot be greater than the total number of attachments %d.", + __LINE__, DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS", + "CreateRenderPass: Depth stencil attachment %d cannot be greater than the total number of attachments %d.", attachment, pCreateInfo->attachmentCount); continue; } @@ -8727,10 +8791,10 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderP } for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) { uint32_t attachment = subpass.pInputAttachments[j].attachment; - if (attachment >= pCreateInfo->attachmentCount) { + if (attachment >= pCreateInfo->attachmentCount && attachment != VK_ATTACHMENT_UNUSED) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS", - "Input attachment %d cannot be greater than the total number of attachments %d.", + "CreateRenderPass: Input attachment %d cannot be greater than the total number of attachments %d.", attachment, pCreateInfo->attachmentCount); continue; } diff --git a/layers/core_validation_error_enums.h b/layers/core_validation_error_enums.h index 3904bdf1..bcbdd33b 100644 --- a/layers/core_validation_error_enums.h +++ b/layers/core_validation_error_enums.h @@ -137,6 +137,10 @@ enum DRAW_STATE_ERROR { // RenderPass is active DRAWSTATE_NO_ACTIVE_RENDERPASS, // Rendering cmd submitted without an active // RenderPass + DRAWSTATE_INVALID_IMAGE_USAGE, // Image attachment location conflicts with + // image's USAGE flags + DRAWSTATE_INVALID_ATTACHMENT_INDEX, // Attachment reference contains an index + // that is out-of-bounds DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, // DescriptorSet bound but it was // never updated. This is a warning // code. -- cgit v1.2.3