diff --git a/layers/core_checks/cc_copy_blit_resolve.cpp b/layers/core_checks/cc_copy_blit_resolve.cpp index c365ef95d39..00a9cc3e94b 100644 --- a/layers/core_checks/cc_copy_blit_resolve.cpp +++ b/layers/core_checks/cc_copy_blit_resolve.cpp @@ -2917,7 +2917,7 @@ bool CoreChecks::ValidateHostCopyImageLayout(const VkDevice device, const VkImag if (!found) { LogObjectList objlist(device, image); skip |= LogError(objlist, vuid, - "%s(): %s is %s which is not one of the layouts retuned in " + "%s(): %s is %s which is not one of the layouts returned in " "VkPhysicalDeviceHostImageCopyPropertiesEXT::%s", func_name, field_name, string_VkImageLayout(image_layout), supported_name); } diff --git a/layers/core_checks/cc_image.cpp b/layers/core_checks/cc_image.cpp index 2ee9d11d3aa..0bbcd3aaffa 100644 --- a/layers/core_checks/cc_image.cpp +++ b/layers/core_checks/cc_image.cpp @@ -2275,13 +2275,131 @@ bool CoreChecks::PreCallValidateGetImageSubresourceLayout2EXT(VkDevice device, V return skip; } +static const SubresourceRangeErrorCodes TransitionImageLayoutVUIDs{ + "VUID-VkHostImageLayoutTransitionInfoEXT-subresourceRange-01486", + "VUID-VkHostImageLayoutTransitionInfoEXT-subresourceRange-01724", + "VUID-VkHostImageLayoutTransitionInfoEXT-subresourceRange-01488", + "VUID-VkHostImageLayoutTransitionInfoEXT-subresourceRange-01725", +}; + bool CoreChecks::PreCallValidateTransitionImageLayoutEXT(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfoEXT *pTransitions) const { bool skip = false; - + const char *func_name = "vkTransitionImageLayoutEXT()"; + + for (uint32_t i = 0; i < transitionCount; ++i) { + auto transition = pTransitions[i]; + auto image_state = Get(transition.image); + auto image_format = image_state->createInfo.format; + auto aspect_mask = transition.subresourceRange.aspectMask; + const bool has_depth_mask = (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; + const bool has_stencil_mask = (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; + + if ((image_state->createInfo.usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT) == 0) { + const LogObjectList objlist(device, image_state->Handle()); + skip |= LogError(objlist, "VUID-VkHostImageLayoutTransitionInfoEXT-image-09055", + "%s: image in transition %d was not created with VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT", func_name, i); + } + + skip |= ValidateImageSubresourceRange(image_state->createInfo.mipLevels, image_state->createInfo.arrayLayers, + transition.subresourceRange, func_name, "subresourceRange", "arrayLayers", + image_state->image(), TransitionImageLayoutVUIDs); + skip |= + ValidateMemoryIsBoundToImage(device, *image_state, func_name, "VUID-VkHostImageLayoutTransitionInfoEXT-image-01932"); + + if (((FormatIsColor(image_format) == true) && (FormatIsMultiplane(image_format) == false)) || + (image_state->disjoint == false)) { + if (aspect_mask != VK_IMAGE_ASPECT_COLOR_BIT) { + const LogObjectList objlist(device, image_state->Handle()); + skip |= LogError( + objlist, "VUID-VkHostImageLayoutTransitionInfoEXT-image-01671", + "%s: image in transition %d requires subresourceRange.aspectMask to be VK_IMAGE_ASPECT_COLOR_BIT, but it is %s", + func_name, i, string_VkImageAspectFlags(aspect_mask).c_str()); + } + } + if ((FormatIsMultiplane(image_format)) && (image_state->disjoint == true)) { + if (!IsValidPlaneAspect(image_format, aspect_mask) && ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) == 0)) { + const LogObjectList objlist(device, image_state->Handle()); + skip |= LogError(objlist, "VUID-VkHostImageLayoutTransitionInfoEXT-image-01671", + "%s: image in transition %d requires subresourceRange.aspectMask to include at least one " + "multi-planar aspect mask or to be VK_IMAGE_ASPECT_COLOR_BIT, but it is %s", + func_name, i, string_VkImageAspectFlags(aspect_mask).c_str()); + } + } + if (FormatIsDepthAndStencil(image_format)) { + if (enabled_features.core12.separateDepthStencilLayouts) { + if (!has_depth_mask && !has_stencil_mask) { + const LogObjectList objlist(device, image_state->Handle()); + skip |= LogError(objlist, "VUID-VkHostImageLayoutTransitionInfoEXT-image-03319", + "%s: image in transition %d of format %s requires subresourceRange.aspectMask to have either " + "the depth or stencil " + "aspects set, but its aspectMask is %s", + func_name, i, string_VkFormat(image_format), string_VkImageAspectFlags(aspect_mask).c_str()); + } + } else { + if (!has_depth_mask || !has_stencil_mask) { + const LogObjectList objlist(device, image_state->Handle()); + skip |= LogError(objlist, "VUID-VkHostImageLayoutTransitionInfoEXT-image-03320", + "%s: image in transition %d of format %s requires subresourceRange.aspectMask to have both " + "the depth and stencil " + "aspects set, but its aspectMask is %s", + func_name, i, string_VkFormat(image_format), string_VkImageAspectFlags(aspect_mask).c_str()); + } + } + } + if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) { + if ((transition.oldLayout == VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL) || + (transition.oldLayout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL) || + (transition.newLayout == VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL) || + (transition.newLayout == VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL)) { + const LogObjectList objlist(device, image_state->Handle()); + skip |= LogError(objlist, "VUID-VkHostImageLayoutTransitionInfoEXT-aspectMask-08702", + "%s: the aspect mask in transition %i is %s meaning that neither oldLayout nor newLayout can be " + "VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL or VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL" + "oldLayout = %s and newLayout = %s", + func_name, i, string_VkImageAspectFlags(aspect_mask).c_str(), + string_VkImageLayout(transition.oldLayout), string_VkImageLayout(transition.oldLayout)); + } + } + if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) { + if ((transition.oldLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL) || + (transition.oldLayout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL) || + (transition.newLayout == VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL) || + (transition.newLayout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL)) { + const LogObjectList objlist(device, image_state->Handle()); + skip |= LogError(objlist, "VUID-VkHostImageLayoutTransitionInfoEXT-aspectMask-08703", + "%s: the aspect mask in transition %i is %s meaning that neither oldLayout nor newLayout can be " + "VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL or VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL" + "oldLayout = %s and newLayout = %s", + func_name, i, string_VkImageAspectFlags(aspect_mask).c_str(), + string_VkImageLayout(transition.oldLayout), string_VkImageLayout(transition.oldLayout)); + } + } + if ((transition.oldLayout != VK_IMAGE_LAYOUT_UNDEFINED) && (transition.oldLayout != VK_IMAGE_LAYOUT_PREINITIALIZED)) { + auto *props = &phys_dev_ext_props.host_image_copy_properties; + skip |= ValidateHostCopyImageLayout(device, transition.image, props->copySrcLayoutCount, props->pCopySrcLayouts, + transition.oldLayout, func_name, "oldLayout", "pCopySrcLayouts", + "VUID-VkHostImageLayoutTransitionInfoEXT-oldLayout-09056"); + } + + auto *props = &phys_dev_ext_props.host_image_copy_properties; + skip |= ValidateHostCopyImageLayout(device, transition.image, props->copyDstLayoutCount, props->pCopyDstLayouts, + transition.newLayout, func_name, "newLayout", "pCopyDstLayouts", + "VUID-VkHostImageLayoutTransitionInfoEXT-newLayout-09057"); + } return skip; }; +void CoreChecks::PostCallRecordTransitionImageLayoutEXT(VkDevice device, uint32_t transitionCount, + const VkHostImageLayoutTransitionInfoEXT *pTransitions, VkResult result) { + ValidationStateTracker::PostCallRecordTransitionImageLayoutEXT(device, transitionCount, pTransitions, result); + //for (uint32_t i = 0; i < transitionCount; ++i) { + // auto transition = pTransitions[i]; + // auto image_state = GetWrite(transition.image); + // Todo Update image's layout_range_map in transition.subresourceRange + //} +} + // Validates the image is allowed to be protected bool CoreChecks::ValidateProtectedImage(const CMD_BUFFER_STATE &cb_state, const IMAGE_STATE &image_state, const char *cmd_name, const char *vuid, const char *more_message) const { diff --git a/layers/core_checks/core_validation.h b/layers/core_checks/core_validation.h index 83ac3eda136..d58492d1123 100644 --- a/layers/core_checks/core_validation.h +++ b/layers/core_checks/core_validation.h @@ -2288,6 +2288,8 @@ class CoreChecks : public ValidationStateTracker { VkSubresourceLayout& layout, bool is_ext) const; bool PreCallValidateTransitionImageLayoutEXT(VkDevice device, uint32_t transitionCount, const VkHostImageLayoutTransitionInfoEXT* pTransitions) const override; + void PostCallRecordTransitionImageLayoutEXT(VkDevice device, uint32_t transitionCount, + const VkHostImageLayoutTransitionInfoEXT* pTransitions, VkResult result) override; bool PreCallValidateGetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) const override; bool PreCallValidateGetImageSubresourceLayout2EXT(VkDevice device, VkImage image, const VkImageSubresource2EXT* pSubresource,