diff options
| author | Tobin Ehlis <tobine@google.com> | 2016-05-26 11:21:59 -0600 |
|---|---|---|
| committer | Tobin Ehlis <tobine@google.com> | 2016-06-02 09:54:34 -0600 |
| commit | 2fc91e01eeb0cec1b03332570c5eebe0d380a305 (patch) | |
| tree | 77b8eca5ab44e0d527d62b37b68a7ed4933681f1 | |
| parent | 3fe78667aeae10ab4fe5cb881d0f67a80200753b (diff) | |
| download | usermoji-2fc91e01eeb0cec1b03332570c5eebe0d380a305.tar.xz | |
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.
| -rw-r--r-- | layers/core_validation.cpp | 106 | ||||
| -rw-r--r-- | layers/descriptor_sets.cpp | 93 | ||||
| -rw-r--r-- | layers/descriptor_sets.h | 21 |
3 files changed, 127 insertions, 93 deletions
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<cvdescriptorset::DescriptorSetLayout const *> 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<const uint64_t &>(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<const uint64_t &>(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<uint32_t>(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<const uint64_t &>(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<cvdescriptorset::DescriptorSetLayout const *> layout_nodes(pAllocateInfo->descriptorSetCount, nullptr); - std::unique_lock<std::mutex> 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<VkDescriptorSetLayout, cvdescriptorset::DescriptorSetLayout *> &set_layout_map, + const std::unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> &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<const uint64_t &>(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<const uint64_t &>(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<uint32_t>(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<const uint64_t &>(p_alloc_info->descriptorPool), __LINE__, DRAWSTATE_INVALID_POOL, "DS", + "Unable to find pool node for pool 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call", + reinterpret_cast<const uint64_t &>(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<uint64_t &>(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<uint64_t &>(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<const uint64_t &>(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<uint64_t &>(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<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> *pool_map, + std::unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> *set_map, + const std::unordered_map<VkDescriptorSetLayout, cvdescriptorset::DescriptorSetLayout *> &layout_map, + const std::unordered_map<VkBuffer, BUFFER_NODE> &buffer_map, + const std::unordered_map<VkDeviceMemory, DEVICE_MEM_INFO> &mem_obj_map, + const std::unordered_map<VkBufferView, VkBufferViewCreateInfo> &buffer_view_map, + const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> &sampler_map, + const std::unordered_map<VkImageView, VkImageViewCreateInfo> &image_view_map, + const std::unordered_map<VkImage, IMAGE_NODE> &image_map, + const std::unordered_map<VkImage, VkSwapchainKHR> &image_to_swapchain_map, + const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> &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<uint32_t>(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<VkDescriptorSet, cvdescriptorset::DescriptorSet *> &, 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<VkDescriptorSet, cvdescriptorset::DescriptorSet *> &, 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<VkDescriptorSetLayout, cvdescriptorset::DescriptorSetLayout *> &, + const std::unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> &); +// Update state based on allocating new descriptorsets +void PerformAllocateDescriptorSets( + const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, std::unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> *, + std::unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> *, + const std::unordered_map<VkDescriptorSetLayout, cvdescriptorset::DescriptorSetLayout *> &, + const std::unordered_map<VkBuffer, BUFFER_NODE> &, const std::unordered_map<VkDeviceMemory, DEVICE_MEM_INFO> &, + const std::unordered_map<VkBufferView, VkBufferViewCreateInfo> &, + const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> &, + const std::unordered_map<VkImageView, VkImageViewCreateInfo> &, const std::unordered_map<VkImage, IMAGE_NODE> &, + const std::unordered_map<VkImage, VkSwapchainKHR> &, const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> &); + /* * DescriptorSet class * |
