layers:Add image layout validation for descriptors
This change adds validation to make sure that an image layout at the
time the image is used in a descriptor matches the layout that was
given when the descriptor was updated.
Because image view covers a range of mip levels, loop over each level
and verify layouts one at a time.
Also Updated a number of validate functions to use cont ptr params for
data that they aren't changing.
diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp
index 84663c4..de34945 100644
--- a/layers/descriptor_sets.cpp
+++ b/layers/descriptor_sets.cpp
@@ -24,6 +24,7 @@
#include "descriptor_sets.h"
#include "vk_enum_string_helper.h"
#include "vk_safe_struct.h"
+#include "buffer_validation.h"
#include <sstream>
#include <algorithm>
@@ -395,7 +396,8 @@
// that any update buffers are valid, and that any dynamic offsets are within the bounds of their buffers.
// Return true if state is acceptable, or false and write an error message into error string
bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::map<uint32_t, descriptor_req> &bindings,
- const std::vector<uint32_t> &dynamic_offsets, std::string *error) const {
+ const std::vector<uint32_t> &dynamic_offsets, const GLOBAL_CB_NODE *cb_node,
+ const char *caller, std::string *error) const {
for (auto binding_pair : bindings) {
auto binding = binding_pair.first;
if (!p_layout_->HasBinding(binding)) {
@@ -472,9 +474,15 @@
}
}
} else if (descriptor_class == ImageSampler || descriptor_class == Image) {
- auto image_view = (descriptor_class == ImageSampler)
- ? static_cast<ImageSamplerDescriptor *>(descriptors_[i].get())->GetImageView()
- : static_cast<ImageDescriptor *>(descriptors_[i].get())->GetImageView();
+ VkImageView image_view;
+ VkImageLayout image_layout;
+ if (descriptor_class == ImageSampler) {
+ image_view = static_cast<ImageSamplerDescriptor *>(descriptors_[i].get())->GetImageView();
+ image_layout = static_cast<ImageSamplerDescriptor *>(descriptors_[i].get())->GetImageLayout();
+ } else {
+ image_view = static_cast<ImageDescriptor *>(descriptors_[i].get())->GetImageView();
+ image_layout = static_cast<ImageDescriptor *>(descriptors_[i].get())->GetImageLayout();
+ }
auto reqs = binding_pair.second;
auto image_view_state = GetImageViewState(device_data_, image_view);
@@ -493,7 +501,30 @@
auto image_node = GetImageState(device_data_, image_view_ci.image);
assert(image_node);
-
+ // Verify Image Layout
+ // TODO: VALIDATION_ERROR_02981 is the error physically closest to the spec language of interest, however
+ // there is no VUID for the actual spec language. Need to file a spec MR to add VU language for:
+ // imageLayout is the layout that the image subresources accessible from imageView will be in at the time
+ // this descriptor is accessed.
+ // Copy first mip level into sub_layers and loop over each mip level to verify layout
+ VkImageSubresourceLayers sub_layers;
+ sub_layers.aspectMask = image_view_ci.subresourceRange.aspectMask;
+ sub_layers.baseArrayLayer = image_view_ci.subresourceRange.baseArrayLayer;
+ sub_layers.layerCount = image_view_ci.subresourceRange.layerCount;
+ bool hit_error = false;
+ for (auto cur_level = image_view_ci.subresourceRange.baseMipLevel;
+ cur_level < image_view_ci.subresourceRange.levelCount; ++cur_level) {
+ sub_layers.mipLevel = cur_level;
+ VerifyImageLayout(device_data_, cb_node, image_node, sub_layers, image_layout,
+ VK_IMAGE_LAYOUT_UNDEFINED, caller, VALIDATION_ERROR_02981, &hit_error);
+ if (hit_error) {
+ *error =
+ "Image layout specified at vkUpdateDescriptorSets() time doesn't match actual image layout at "
+ "time descriptor is used. See previous error callback for specific details.";
+ return false;
+ }
+ }
+ // Verify Sample counts
if ((reqs & DESCRIPTOR_REQ_SINGLE_SAMPLE) && image_node->createInfo.samples != VK_SAMPLE_COUNT_1_BIT) {
std::stringstream error_str;
error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
@@ -502,7 +533,6 @@
*error = error_str.str();
return false;
}
-
if ((reqs & DESCRIPTOR_REQ_MULTI_SAMPLE) && image_node->createInfo.samples == VK_SAMPLE_COUNT_1_BIT) {
std::stringstream error_str;
error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i