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/descriptor_sets.cpp | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) (limited to 'layers/descriptor_sets.cpp') 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 +} -- 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/descriptor_sets.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 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/descriptor_sets.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 b5dd2356f3ecabaef208c7c013fac27aebaa061f Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Thu, 19 May 2016 07:56:18 -0600 Subject: layers: Verify that src of copy update is updated Before verifying source update comments make sure that the source descriptors have been updated. This guards against some obscure corner cases where a bad source descriptor could slip through the content verification. --- layers/descriptor_sets.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'layers/descriptor_sets.cpp') diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 2955a6a3..d178a916 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -543,7 +543,17 @@ bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data set_, error))) { return false; } - // Update parameters all look good so verify update contents + // First make sure source descriptors are updated + for (uint32_t i = 0; i < update->descriptorCount; ++i) { + if (!src_set->descriptors_[src_start_idx + i]) { + std::stringstream error_str; + error_str << "Attempting copy update from descriptorSet " << src_set << " binding #" << update->srcBinding << " but descriptor at array offset " + << update->srcArrayElement + i << " has not been updated."; + *error = error_str.str(); + return false; + } + } + // Update parameters all look good and descriptor updated so verify update contents if (!VerifyCopyUpdateContents(update, src_set, src_start_idx, error)) return false; -- 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/descriptor_sets.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 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/descriptor_sets.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 57b4be486a1a214450ac3edb40d1b6968c1591a8 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Mon, 30 May 2016 11:47:31 +1200 Subject: layers: take better advantage of emplace_back in descriptor sets Doesn't win us anything to use emplace_back to invoke a copy constructor. Construct the unique_ptr from raw ptr in-place instead. Signed-off-by: Chris Forbes --- layers/descriptor_sets.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'layers/descriptor_sets.cpp') diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index b0e16e82..2867a134 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))); + descriptors_.emplace_back(new SamplerDescriptor(immut_sampler + di)); else - descriptors_.emplace_back(std::unique_ptr(new SamplerDescriptor())); + descriptors_.emplace_back(new SamplerDescriptor()); } break; } @@ -290,9 +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))); + descriptors_.emplace_back(new ImageSamplerDescriptor(immut + di)); else - descriptors_.emplace_back(std::unique_ptr(new ImageSamplerDescriptor())); + descriptors_.emplace_back(new ImageSamplerDescriptor()); } break; } @@ -301,19 +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))); + descriptors_.emplace_back(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))); + descriptors_.emplace_back(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))); + descriptors_.emplace_back(new BufferDescriptor(type)); break; default: assert(0); // Bad descriptor type specified -- cgit v1.2.3 From 580f8733d50dc60a82ae252fcc758771f511a5e5 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Tue, 24 May 2016 11:14:43 -0600 Subject: layers: Add usage bit validation for image descriptors Verify that images used in imageView that's passed to various image descriptor types have the correct usage bits set. --- layers/descriptor_sets.cpp | 55 ++++++++++++++++++++++++++++++++++++++-------- layers/descriptor_sets.h | 3 ++- 2 files changed, 48 insertions(+), 10 deletions(-) (limited to 'layers/descriptor_sets.cpp') diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 2867a134..72299ccf 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -585,7 +585,7 @@ bool cvdescriptorset::ValidateSampler(const VkSampler sampler, return (sampler_map->count(sampler) != 0); } -bool cvdescriptorset::ValidateImageUpdate(const VkImageView image_view, const VkImageLayout image_layout, +bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type, const std::unordered_map *image_view_map, const std::unordered_map *image_map, const std::unordered_map *image_to_swapchain_map, @@ -599,12 +599,15 @@ bool cvdescriptorset::ValidateImageUpdate(const VkImageView image_view, const Vk return false; } else { // 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; 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; } else { // Also need to check the swapchains. auto swapchain_pair = image_to_swapchain_map->find(image); @@ -616,6 +619,7 @@ bool cvdescriptorset::ValidateImageUpdate(const VkImageView image_view, const Vk } } } + // First validate that format and layout are compatible if (format == VK_FORMAT_MAX_ENUM) { std::stringstream error_str; error_str << "Invalid image (" << image << ") in imageView (" << image_view << ")."; @@ -676,6 +680,39 @@ bool cvdescriptorset::ValidateImageUpdate(const VkImageView image_view, const Vk break; } } + // Now validate that usage flags are correctly set for given type of update + std::string error_usage_bit; + switch (type) { + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { + if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) { + error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT"; + } + break; + } + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { + if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) { + error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT"; + } + break; + } + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: { + if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) { + error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT"; + } + break; + } + default: + break; + } + if (!error_usage_bit.empty()) { + std::stringstream error_str; + error_str << "ImageView (" << image_view << ") with usage mask 0x" << usage + << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have " + << error_usage_bit << " set."; + *error = error_str.str(); + return false; + } } return true; } @@ -954,8 +991,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, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, - error)) { + if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, 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(); @@ -986,8 +1023,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, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, - error)) { + if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, 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(); @@ -1069,8 +1106,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, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, - error)) { + if (!ValidateImageUpdate(image_view, image_layout, src_set->GetTypeFromGlobalIndex(index), 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(); @@ -1083,8 +1120,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, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, - error)) { + if (!ValidateImageUpdate(image_view, image_layout, src_set->GetTypeFromGlobalIndex(index), 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(); diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index 6a0d7e78..a3cf28df 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -161,7 +161,8 @@ 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 ValidateImageUpdate(const VkImageView, const VkImageLayout, const std::unordered_map *, +bool ValidateImageUpdate(VkImageView, VkImageLayout, VkDescriptorType, + const std::unordered_map *, const std::unordered_map *, const std::unordered_map *, const std::unordered_map *, std::string *); -- cgit v1.2.3 From 6eaa12d7fc3aa90e433d7f694238a72306453925 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Tue, 24 May 2016 12:33:42 -0600 Subject: layers: Add usage bit validation for buffer descriptors Verify that buffer used to update all buffer descriptor types (texel or general) has the correct usage bits set. descriptor --- layers/descriptor_sets.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++--- layers/descriptor_sets.h | 1 + 2 files changed, 61 insertions(+), 3 deletions(-) (limited to 'layers/descriptor_sets.cpp') diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 72299ccf..c3f9e3b1 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -982,6 +982,55 @@ bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data // All checks passed, update is clean return true; } +// For the given buffer, verify that its creation parameters are appropriate for the given type +// 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()) { + 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; + std::string error_usage_bit; + switch (type) { + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + if (!(usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) { + error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT"; + } + break; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + if (!(usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) { + error_usage_bit = "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT"; + } + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + if (!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) { + error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT"; + } + break; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + if (!(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) { + error_usage_bit = "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT"; + } + break; + default: + break; + } + if (!error_usage_bit.empty()) { + std::stringstream error_str; + error_str << "Buffer (" << buffer << ") with usage mask 0x" << usage << " being used for a descriptor update of type " + << string_VkDescriptorType(type) << " does not have " << error_usage_bit << " set."; + *error = error_str.str(); + return false; + } + 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 { @@ -1037,12 +1086,20 @@ 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]; - if (!buffer_view_map_->count(buffer_view)) { + auto buffer_view_it = buffer_view_map_->find(buffer_view); + if (buffer_view_it == buffer_view_map_->end()) { 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; + 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(); + *error = error_str.str(); + return false; + } } break; } @@ -1052,9 +1109,9 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc 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)) { + if (!ValidateBufferUpdate(buffer, update->descriptorType, error)) { std::stringstream error_str; - error_str << "Attempted write update to buffer descriptor with invalid buffer: " << buffer; + error_str << "Attempted write update to buffer descriptor failed due to: " << error->c_str(); *error = error_str.str(); return false; } diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index a3cf28df..a211d2f6 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -346,6 +346,7 @@ class DescriptorSet : public BASE_NODE { private: bool VerifyWriteUpdateContents(const VkWriteDescriptorSet *, const uint32_t, std::string *) const; bool VerifyCopyUpdateContents(const VkCopyDescriptorSet *, const DescriptorSet *, const uint32_t, std::string *) const; + bool ValidateBufferUpdate(VkBuffer, VkDescriptorType, 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 ae2eb29829c370138f08131b2246f67a0cc0ddd1 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Tue, 24 May 2016 12:35:57 -0600 Subject: layers: Remove unneeded else block The "if" case returns so no need for this else block or the indentation that it includes. --- layers/descriptor_sets.cpp | 66 ++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 34 deletions(-) (limited to 'layers/descriptor_sets.cpp') diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index c3f9e3b1..e6c8ab65 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -944,40 +944,38 @@ bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data 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; - } + } + // 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; -- cgit v1.2.3 From b4e1c579bd811fa59ffbd5e6bad6cd4c25722d91 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Tue, 24 May 2016 13:07:12 -0600 Subject: layers: Improve descriptor copy update validation Add buffer usage bit validation for descriptor copy updates. Pass down known descriptor type to copy validate function to avoid having to look it up again. Fix various incorrect "write" references in the copy update error messages. --- layers/descriptor_sets.cpp | 32 ++++++++++++++++++++------------ layers/descriptor_sets.h | 3 ++- 2 files changed, 22 insertions(+), 13 deletions(-) (limited to 'layers/descriptor_sets.cpp') diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index e6c8ab65..db712175 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -545,7 +545,7 @@ bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data } } // Update parameters all look good and descriptor updated so verify update contents - if (!VerifyCopyUpdateContents(update, src_set, src_start_idx, error)) + if (!VerifyCopyUpdateContents(update, src_set, src_type, src_start_idx, error)) return false; // All checks passed so update is good @@ -1125,7 +1125,7 @@ bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDesc } // 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 { + VkDescriptorType type, 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) { @@ -1161,10 +1161,10 @@ 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, src_set->GetTypeFromGlobalIndex(index), image_view_map_, image_map_, - image_to_swapchain_map_, swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, type, 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_str << "Attempted copy update to combined image sampler descriptor failed due to: " << error->c_str(); *error = error_str.str(); return false; } @@ -1175,10 +1175,10 @@ 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, src_set->GetTypeFromGlobalIndex(index), image_view_map_, image_map_, - image_to_swapchain_map_, swapchain_map_, error)) { + if (!ValidateImageUpdate(image_view, image_layout, type, 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_str << "Attempted copy update to image descriptor failed due to: " << error->c_str(); *error = error_str.str(); return false; } @@ -1188,9 +1188,17 @@ 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(); - if (!buffer_view_map_->count(buffer_view)) { + auto bv_it = buffer_view_map_->find(buffer_view); + if (bv_it == buffer_view_map_->end()) { std::stringstream error_str; - error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view; + 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; + if (!ValidateBufferUpdate(buffer, type, error)) { + std::stringstream error_str; + error_str << "Attempted copy update to texel buffer descriptor failed due to: " << error->c_str(); *error = error_str.str(); return false; } @@ -1200,9 +1208,9 @@ bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescri 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)) { + if (!ValidateBufferUpdate(buffer, type, error)) { std::stringstream error_str; - error_str << "Attempted write update to buffer descriptor with invalid buffer: " << buffer; + error_str << "Attempted copy update to buffer descriptor failed due to: " << error->c_str(); *error = error_str.str(); return false; } diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index a211d2f6..b0496b1e 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -345,7 +345,8 @@ class DescriptorSet : public BASE_NODE { private: bool VerifyWriteUpdateContents(const VkWriteDescriptorSet *, const uint32_t, std::string *) const; - bool VerifyCopyUpdateContents(const VkCopyDescriptorSet *, const DescriptorSet *, const uint32_t, std::string *) const; + bool VerifyCopyUpdateContents(const VkCopyDescriptorSet *, const DescriptorSet *, VkDescriptorType, uint32_t, + std::string *) const; bool ValidateBufferUpdate(VkBuffer, VkDescriptorType, std::string *) const; // Private helper to set all bound cmd buffers to INVALID state void InvalidateBoundCmdBuffers(); -- cgit v1.2.3 From 89723f04c08dc243479759cf1c300e5b978ec090 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Wed, 25 May 2016 09:24:36 -0600 Subject: layers: DescriptorSet class indentation fixes More cases where "else" blocks weren't needed because the "if" block returns. --- layers/descriptor_sets.cpp | 202 ++++++++++++++++++++++----------------------- 1 file changed, 100 insertions(+), 102 deletions(-) (limited to 'layers/descriptor_sets.cpp') diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index db712175..e1602251 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -597,122 +597,120 @@ bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout error_str << "Invalid VkImageView: " << image_view; *error = error_str.str(); return false; + } + // 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; + 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; } else { - // 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; - 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; - } 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_pair = swapchain_map->find(swapchain); - if (swapchain_pair != swapchain_map->end()) { - format = swapchain_pair->second->createInfo.imageFormat; - } + // 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_pair = swapchain_map->find(swapchain); + if (swapchain_pair != swapchain_map->end()) { + format = swapchain_pair->second->createInfo.imageFormat; } } - // First validate that format and layout are compatible - if (format == VK_FORMAT_MAX_ENUM) { + } + // First validate that format and layout are compatible + if (format == VK_FORMAT_MAX_ENUM) { + std::stringstream error_str; + error_str << "Invalid image (" << image << ") in imageView (" << image_view << ")."; + *error = error_str.str(); + return false; + } + bool ds = vk_format_is_depth_or_stencil(format); + switch (image_layout) { + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + // Only Color bit must be set + if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) { std::stringstream error_str; - error_str << "Invalid image (" << image << ") in imageView (" << image_view << ")."; + error_str << "ImageView (" << image_view << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but does " + "not have VK_IMAGE_ASPECT_COLOR_BIT set."; *error = error_str.str(); return false; - } else { - bool ds = vk_format_is_depth_or_stencil(format); - switch (image_layout) { - case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: - // Only Color bit must be set - if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) { - std::stringstream error_str; - error_str << "ImageView (" << image_view << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but does " - "not have VK_IMAGE_ASPECT_COLOR_BIT set."; - *error = error_str.str(); - return false; - } - // format must NOT be DS - if (ds) { - std::stringstream error_str; - error_str << "ImageView (" << image_view - << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is " - << string_VkFormat(format) << " which is not a color format."; - *error = error_str.str(); - return false; - } - break; - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: - case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: - // Depth or stencil bit must be set, but both must NOT be set - if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) { - if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) { - // both must NOT be set - std::stringstream error_str; - error_str << "ImageView (" << image_view << ") has both STENCIL and DEPTH aspects set"; - *error = error_str.str(); - return false; - } - } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) { - // Neither were set - std::stringstream error_str; - error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout) - << " but does not have STENCIL or DEPTH aspects set"; - *error = error_str.str(); - return false; - } - // format must be DS - if (!ds) { - std::stringstream error_str; - error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout) - << " but the image format is " << string_VkFormat(format) << " which is not a depth/stencil format."; - *error = error_str.str(); - return false; - } - break; - default: - // anything to check for other layouts? - break; - } - } - // Now validate that usage flags are correctly set for given type of update - std::string error_usage_bit; - switch (type) { - case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: - case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { - if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) { - error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT"; - } - break; } - case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { - if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) { - error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT"; - } - break; + // format must NOT be DS + if (ds) { + std::stringstream error_str; + error_str << "ImageView (" << image_view + << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is " + << string_VkFormat(format) << " which is not a color format."; + *error = error_str.str(); + return false; } - case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: { - if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) { - error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT"; + break; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + // Depth or stencil bit must be set, but both must NOT be set + if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) { + if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) { + // both must NOT be set + std::stringstream error_str; + error_str << "ImageView (" << image_view << ") has both STENCIL and DEPTH aspects set"; + *error = error_str.str(); + return false; } - break; - } - default: - break; + } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) { + // Neither were set + std::stringstream error_str; + error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout) + << " but does not have STENCIL or DEPTH aspects set"; + *error = error_str.str(); + return false; } - if (!error_usage_bit.empty()) { + // format must be DS + if (!ds) { std::stringstream error_str; - error_str << "ImageView (" << image_view << ") with usage mask 0x" << usage - << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have " - << error_usage_bit << " set."; + error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout) + << " but the image format is " << string_VkFormat(format) << " which is not a depth/stencil format."; *error = error_str.str(); return false; } + break; + default: + // anything to check for other layouts? + break; + } + // Now validate that usage flags are correctly set for given type of update + std::string error_usage_bit; + switch (type) { + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { + if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) { + error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT"; + } + break; + } + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { + if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) { + error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT"; + } + break; + } + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: { + if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) { + error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT"; + } + break; + } + default: + break; + } + if (!error_usage_bit.empty()) { + std::stringstream error_str; + error_str << "ImageView (" << image_view << ") with usage mask 0x" << usage + << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have " + << error_usage_bit << " set."; + *error = error_str.str(); + return false; } return true; } -- cgit v1.2.3 From 03918739683bd7c81c2572da6036fcae75d1387c Mon Sep 17 00:00:00 2001 From: iostrows Date: Thu, 2 Jun 2016 15:56:26 +0200 Subject: layers: GH611 Fix dynamic offset indexing --- layers/descriptor_sets.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'layers/descriptor_sets.cpp') diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index e1602251..0530f40c 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -341,13 +341,13 @@ bool cvdescriptorset::DescriptorSet::IsCompatible(const DescriptorSetLayout *lay // Return true if state is acceptable, or false and write an error message into error string bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::unordered_set &bindings, const std::vector &dynamic_offsets, std::string *error) const { + auto dyn_offset_index = 0; for (auto binding : bindings) { auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(binding); if (descriptors_[start_idx]->IsImmutableSampler()) { // Nothing to do for strictly immutable sampler } else { auto end_idx = p_layout_->GetGlobalEndIndexFromBinding(binding); - auto dyn_offset_index = 0; for (uint32_t i = start_idx; i <= end_idx; ++i) { if (!descriptors_[i]->updated) { std::stringstream error_str; -- 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/descriptor_sets.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/descriptor_sets.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 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/descriptor_sets.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/descriptor_sets.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/descriptor_sets.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/descriptor_sets.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/descriptor_sets.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/descriptor_sets.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/descriptor_sets.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/descriptor_sets.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/descriptor_sets.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/descriptor_sets.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 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/descriptor_sets.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