From 79fde938178535f598e030a0e9d19a0cb61b72e0 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Wed, 14 Sep 2016 08:02:49 -0600 Subject: [PATCH] layers: Update ImageView state tracking Create IMAGE_VIEW_STATE class to hold VkImageViewCreateInfo and update related state tracking. This class derives from BASE_NODE in preparation for tracking in_use for ImageViews consistent to other object in_use tracking. --- layers/core_validation.cpp | 100 +++++++++++++++++++++-------------------- layers/core_validation_types.h | 14 +++++- layers/descriptor_sets.cpp | 31 ++++++------- 3 files changed, 80 insertions(+), 65 deletions(-) diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 1b005ef..eb2e136 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -113,7 +113,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; @@ -253,8 +253,8 @@ 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, VkImageView image_view) { +// Return IMAGE_VIEW_STATE ptr for specified imageView or else NULL +IMAGE_VIEW_STATE *getImageViewState(const layer_data *dev_data, VkImageView image_view) { auto iv_it = dev_data->imageViewMap.find(image_view); if (iv_it == dev_data->imageViewMap.end()) { return nullptr; @@ -3703,10 +3703,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 iv_data = getImageViewData(dev_data, imageView); - assert(iv_data); - const VkImage &image = iv_data->image; - const VkImageSubresourceRange &subRange = iv_data->subresourceRange; + auto view_state = getImageViewState(dev_data, imageView); + assert(view_state); + const VkImage &image = view_state->create_info.image; + const VkImageSubresourceRange &subRange = view_state->create_info.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; @@ -3717,7 +3717,7 @@ void SetLayout(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkImageView imag // the aspectMask is ignored and both are used. Verify that the extra implicit layout // is OK for descriptor set layout validation if (subRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) { - if (vk_format_is_depth_and_stencil(iv_data->format)) { + if (vk_format_is_depth_and_stencil(view_state->create_info.format)) { sub.aspectMask |= (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); } } @@ -6184,9 +6184,9 @@ static bool PreCallValidateCreateImageView(layer_data *dev_data, const VkImageVi return skip_call; } -static inline void PostCallRecordCreateImageView(layer_data *dev_data, const VkImageViewCreateInfo *pCreateInfo, VkImageView *pView) { - dev_data->imageViewMap[*pView] = unique_ptr(new VkImageViewCreateInfo(*pCreateInfo)); - ResolveRemainingLevelsLayers(dev_data, &dev_data->imageViewMap[*pView].get()->subresourceRange, pCreateInfo->image); +static inline void PostCallRecordCreateImageView(layer_data *dev_data, const VkImageViewCreateInfo *pCreateInfo, VkImageView view) { + dev_data->imageViewMap[view] = unique_ptr(new IMAGE_VIEW_STATE(view, pCreateInfo)); + ResolveRemainingLevelsLayers(dev_data, &dev_data->imageViewMap[view].get()->create_info.subresourceRange, pCreateInfo->image); } VKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo, @@ -6200,7 +6200,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageVie VkResult result = dev_data->device_dispatch_table->CreateImageView(device, pCreateInfo, pAllocator, pView); if (VK_SUCCESS == result) { lock.lock(); - PostCallRecordCreateImageView(dev_data, pCreateInfo, pView); + PostCallRecordCreateImageView(dev_data, pCreateInfo, *pView); lock.unlock(); } @@ -7361,11 +7361,11 @@ static bool markStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_N bool skip_call = false; for (auto imageView : pCB->updateImages) { - auto iv_data = getImageViewData(dev_data, imageView); - if (!iv_data) + auto view_state = getImageViewState(dev_data, imageView); + if (!view_state) continue; - auto img_node = getImageNode(dev_data, iv_data->image); + auto img_node = getImageNode(dev_data, view_state->create_info.image); assert(img_node); std::function function = [=]() { SetImageMemoryValid(dev_data, img_node, true); @@ -9079,9 +9079,9 @@ static bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentR // Attachment counts are verified elsewhere, but prevent an invalid access if (attachments[attach].attachment < fbci->attachmentCount) { const VkImageView *image_view = &fbci->pAttachments[attachments[attach].attachment]; - VkImageViewCreateInfo *ivci = getImageViewData(dev_data, *image_view); - if (ivci != nullptr) { - const VkImageCreateInfo *ici = &getImageNode(dev_data, ivci->image)->createInfo; + auto view_state = getImageViewState(dev_data, *image_view); + if (view_state) { + const VkImageCreateInfo *ici = &getImageNode(dev_data, view_state->create_info.image)->createInfo; if (ici != nullptr) { if ((ici->usage & usage_flag) == 0) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, @@ -9124,18 +9124,19 @@ static bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebuf // attachmentCounts match, so make sure corresponding attachment details line up const VkImageView *image_views = pCreateInfo->pAttachments; for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { - VkImageViewCreateInfo *ivci = getImageViewData(dev_data, image_views[i]); - if (ivci->format != rpci->pAttachments[i].format) { + auto view_state = getImageViewState(dev_data, image_views[i]); + auto ivci = view_state->create_info; + if (ivci.format != rpci->pAttachments[i].format) { skip_call |= log_msg( dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, reinterpret_cast(pCreateInfo->renderPass), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS", "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has format of %s that does not match " "the format of " "%s used by the corresponding attachment for renderPass (0x%" PRIxLEAST64 ").", - i, string_VkFormat(ivci->format), string_VkFormat(rpci->pAttachments[i].format), + i, string_VkFormat(ivci.format), string_VkFormat(rpci->pAttachments[i].format), reinterpret_cast(pCreateInfo->renderPass)); } - const VkImageCreateInfo *ici = &getImageNode(dev_data, ivci->image)->createInfo; + const VkImageCreateInfo *ici = &getImageNode(dev_data, ivci.image)->createInfo; if (ici->samples != rpci->pAttachments[i].samples) { skip_call |= log_msg( dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, @@ -9146,17 +9147,17 @@ static bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebuf reinterpret_cast(pCreateInfo->renderPass)); } // Verify that view only has a single mip level - if (ivci->subresourceRange.levelCount != 1) { + if (ivci.subresourceRange.levelCount != 1) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, DRAWSTATE_INVALID_FRAMEBUFFER_CREATE_INFO, "DS", "vkCreateFramebuffer(): VkFramebufferCreateInfo attachment #%u has mip levelCount of %u " "but only a single mip level (levelCount == 1) is allowed when creating a Framebuffer.", - i, ivci->subresourceRange.levelCount); + i, ivci.subresourceRange.levelCount); } - const uint32_t mip_level = ivci->subresourceRange.baseMipLevel; + const uint32_t mip_level = ivci.subresourceRange.baseMipLevel; uint32_t mip_width = max(1u, ici->extent.width >> mip_level); uint32_t mip_height = max(1u, ici->extent.height >> mip_level); - if ((ivci->subresourceRange.layerCount < pCreateInfo->layers) || (mip_width < pCreateInfo->width) || + if ((ivci.subresourceRange.layerCount < pCreateInfo->layers) || (mip_width < pCreateInfo->width) || (mip_height < pCreateInfo->height)) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, @@ -9169,13 +9170,13 @@ static bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebuf "width: %u, %u\n" "height: %u, %u\n" "layerCount: %u, %u\n", - i, ivci->subresourceRange.baseMipLevel, i, mip_width, pCreateInfo->width, mip_height, - pCreateInfo->height, ivci->subresourceRange.layerCount, pCreateInfo->layers); + i, ivci.subresourceRange.baseMipLevel, i, mip_width, pCreateInfo->width, mip_height, + pCreateInfo->height, ivci.subresourceRange.layerCount, pCreateInfo->layers); } - if (((ivci->components.r != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci->components.r != VK_COMPONENT_SWIZZLE_R)) || - ((ivci->components.g != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci->components.g != VK_COMPONENT_SWIZZLE_G)) || - ((ivci->components.b != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci->components.b != VK_COMPONENT_SWIZZLE_B)) || - ((ivci->components.a != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci->components.a != VK_COMPONENT_SWIZZLE_A))) { + if (((ivci.components.r != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.r != VK_COMPONENT_SWIZZLE_R)) || + ((ivci.components.g != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.g != VK_COMPONENT_SWIZZLE_G)) || + ((ivci.components.b != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.b != VK_COMPONENT_SWIZZLE_B)) || + ((ivci.components.a != VK_COMPONENT_SWIZZLE_IDENTITY) && (ivci.components.a != VK_COMPONENT_SWIZZLE_A))) { skip_call |= log_msg( dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, DRAWSTATE_INVALID_FRAMEBUFFER_CREATE_INFO, "DS", @@ -9185,8 +9186,8 @@ static bool ValidateFramebufferCreateInfo(layer_data *dev_data, const VkFramebuf "g swizzle = %s\n" "b swizzle = %s\n" "a swizzle = %s\n", - i, string_VkComponentSwizzle(ivci->components.r), string_VkComponentSwizzle(ivci->components.g), - string_VkComponentSwizzle(ivci->components.b), string_VkComponentSwizzle(ivci->components.a)); + i, string_VkComponentSwizzle(ivci.components.r), string_VkComponentSwizzle(ivci.components.g), + string_VkComponentSwizzle(ivci.components.b), string_VkComponentSwizzle(ivci.components.a)); } } } @@ -9247,13 +9248,13 @@ static void PostCallRecordCreateFramebuffer(layer_data *dev_data, const VkFrameb for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) { VkImageView view = pCreateInfo->pAttachments[i]; - auto view_data = getImageViewData(dev_data, view); - if (!view_data) { + auto view_state = getImageViewState(dev_data, view); + if (!view_state) { continue; } MT_FB_ATTACHMENT_INFO fb_info; - fb_info.mem = getImageNode(dev_data, view_data->image)->mem; - fb_info.image = view_data->image; + fb_info.mem = getImageNode(dev_data, view_state->create_info.image)->mem; + fb_info.image = view_state->create_info.image; fb_node->attachments.push_back(fb_info); } dev_data->frameBufferMap[fb] = std::move(fb_node); @@ -9393,19 +9394,20 @@ static bool ValidateDependencies(const layer_data *my_data, FRAMEBUFFER_NODE con overlapping_attachments[j].push_back(i); continue; } - auto view_data_i = getImageViewData(my_data, viewi); - auto view_data_j = getImageViewData(my_data, viewj); - if (!view_data_i || !view_data_j) { + auto view_state_i = getImageViewState(my_data, viewi); + auto view_state_j = getImageViewState(my_data, viewj); + if (!view_state_i || !view_state_j) { continue; } - if (view_data_i->image == view_data_j->image && - isRegionOverlapping(view_data_i->subresourceRange, view_data_j->subresourceRange)) { + auto view_ci_i = view_state_i->create_info; + auto view_ci_j = view_state_j->create_info; + if (view_ci_i.image == view_ci_j.image && isRegionOverlapping(view_ci_i.subresourceRange, view_ci_j.subresourceRange)) { overlapping_attachments[i].push_back(j); overlapping_attachments[j].push_back(i); continue; } - auto image_data_i = getImageNode(my_data, view_data_i->image); - auto image_data_j = getImageNode(my_data, view_data_j->image); + auto image_data_i = getImageNode(my_data, view_ci_i.image); + auto image_data_j = getImageNode(my_data, view_ci_j.image); if (!image_data_i || !image_data_j) { continue; } @@ -9971,10 +9973,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 = getImageViewData(dev_data, image_view); - assert(image_data); - const VkImage &image = image_data->image; - const VkImageSubresourceRange &subRange = image_data->subresourceRange; + auto view_state = getImageViewState(dev_data, image_view); + assert(view_state); + const VkImage &image = view_state->create_info.image; + const VkImageSubresourceRange &subRange = view_state->create_info.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 df05e34..f913848 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -186,6 +186,18 @@ class IMAGE_NODE : public BASE_NODE { }; }; +class IMAGE_VIEW_STATE : public BASE_NODE { + public: + using BASE_NODE::in_use; + VkImageView image_view; + VkImageViewCreateInfo create_info; + IMAGE_VIEW_STATE() : image_view(VK_NULL_HANDLE), create_info{} {}; + IMAGE_VIEW_STATE(VkImageView iv, const VkImageViewCreateInfo *ci) : image_view(iv), create_info(*ci){}; + IMAGE_VIEW_STATE(const IMAGE_VIEW_STATE &rh_obj) : image_view(rh_obj.image_view), create_info(rh_obj.create_info) { + in_use.store(rh_obj.in_use.load()); + }; +}; + // Simple struct to hold handle and type of object so they can be uniquely identified and looked up in appropriate map // TODO : Unify this with VK_OBJECT above struct MT_OBJ_HANDLE_TYPE { @@ -649,7 +661,7 @@ IMAGE_NODE *getImageNode(const layer_data *, VkImage); DEVICE_MEM_INFO *getMemObjInfo(const layer_data *, VkDeviceMemory); VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *, VkBufferView); SAMPLER_NODE *getSamplerNode(const layer_data *, VkSampler); -VkImageViewCreateInfo *getImageViewData(const layer_data *, VkImageView); +IMAGE_VIEW_STATE *getImageViewState(const layer_data *, VkImageView); VkSwapchainKHR getSwapchainFromImage(const layer_data *, VkImage); SWAPCHAIN_NODE *getSwapchainNode(const layer_data *, VkSwapchainKHR); void invalidateCommandBuffers(std::unordered_set, VK_OBJECT); diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 9b20638..79d9c28 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -431,20 +431,21 @@ bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::map(descriptors_[i].get())->GetImageView(); auto reqs = binding_pair.second; - auto image_view_data = getImageViewData(device_data_, image_view); - assert(image_view_data); + auto image_view_state = getImageViewState(device_data_, image_view); + assert(image_view_state); + auto image_view_ci = image_view_state->create_info; - if ((reqs & DESCRIPTOR_REQ_ALL_VIEW_TYPE_BITS) && (~reqs & (1 << image_view_data->viewType))) { + if ((reqs & DESCRIPTOR_REQ_ALL_VIEW_TYPE_BITS) && (~reqs & (1 << image_view_ci.viewType))) { // bad view type std::stringstream error_str; error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i << " requires an image view of type " << string_descriptor_req_view_type(reqs) - << " but got " << string_VkImageViewType(image_view_data->viewType) << "."; + << " but got " << string_VkImageViewType(image_view_ci.viewType) << "."; *error = error_str.str(); return false; } - auto image_node = getImageNode(device_data_, image_view_data->image); + auto image_node = getImageNode(device_data_, image_view_ci.image); assert(image_node); if ((reqs & DESCRIPTOR_REQ_SINGLE_SAMPLE) && @@ -670,8 +671,8 @@ 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, std::string *error) { - auto iv_data = getImageViewData(dev_data, image_view); - if (!iv_data) { + auto iv_state = getImageViewState(dev_data, image_view); + if (!iv_state) { std::stringstream error_str; error_str << "Invalid VkImageView: " << image_view; *error = error_str.str(); @@ -680,8 +681,8 @@ bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout // Note that when an imageview is created, we validated that memory is bound so no need to re-check here // 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 = iv_data->subresourceRange.aspectMask; - VkImage image = iv_data->image; + VkImageAspectFlags aspect_mask = iv_state->create_info.subresourceRange.aspectMask; + VkImage image = iv_state->create_info.image; VkFormat format = VK_FORMAT_MAX_ENUM; VkImageUsageFlags usage = 0; auto image_node = getImageNode(dev_data, image); @@ -877,9 +878,9 @@ void cvdescriptorset::ImageSamplerDescriptor::BindCommandBuffer(const core_valid core_validation::AddCommandBufferBindingSampler(cb_node, sampler_node); } // Add binding for image - auto iv_data = getImageViewData(dev_data, image_view_); - if (iv_data) { - auto image_node = getImageNode(dev_data, iv_data->image); + auto iv_state = getImageViewState(dev_data, image_view_); + if (iv_state) { + auto image_node = getImageNode(dev_data, iv_state->create_info.image); if (image_node) core_validation::AddCommandBufferBindingImage(dev_data, cb_node, image_node); } @@ -910,9 +911,9 @@ void cvdescriptorset::ImageDescriptor::CopyUpdate(const Descriptor *src) { void cvdescriptorset::ImageDescriptor::BindCommandBuffer(const core_validation::layer_data *dev_data, GLOBAL_CB_NODE *cb_node) { // Add binding for image - auto iv_data = getImageViewData(dev_data, image_view_); - if (iv_data) { - auto image_node = getImageNode(dev_data, iv_data->image); + auto iv_state = getImageViewState(dev_data, image_view_); + if (iv_state) { + auto image_node = getImageNode(dev_data, iv_state->create_info.image); if (image_node) core_validation::AddCommandBufferBindingImage(dev_data, cb_node, image_node); } -- 2.7.4