layers: Implement VU 00303-00308
Implement Valid Usages 00303-00308 with new function
ValidateBarrierLayoutToImageUsage() which verifies an
ImageMemoryBarrier's old/new ImageLayouts are compatible with its
Image's ImageUsageFlags.
Rename ValidateImageLayouts() to ValidateBarriersToImages().
Rename some variables:
- internal vars to use Google style.
- vars passed verbatim from Vulkan to use Vulkan names.
Fix issues revealed in layer tests due to these new checks:
- 2 new Unexpected messages in VkLayerTest.
- 1 failing VkPositiveTest.
Update VU database for check_implemented = Y.
Change-Id: I8723f99d515fbea707299b4d1fcf33a4da6b7b0b
diff --git a/layers/buffer_validation.cpp b/layers/buffer_validation.cpp
index 355eba8..f237d64 100644
--- a/layers/buffer_validation.cpp
+++ b/layers/buffer_validation.cpp
@@ -373,30 +373,93 @@
SetLayout(device_data, pCB, mem_barrier->image, sub, mem_barrier->newLayout);
}
-bool ValidateImageLayouts(layer_data *device_data, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount,
- const VkImageMemoryBarrier *pImgMemBarriers) {
+// Verify an ImageMemoryBarrier's old/new ImageLayouts are compatible with the Image's ImageUsageFlags.
+bool ValidateBarrierLayoutToImageUsage(layer_data *device_data, const VkImageMemoryBarrier *img_barrier, bool new_not_old,
+ VkImageUsageFlags usage_flags, const char *func_name) {
+ const auto report_data = core_validation::GetReportData(device_data);
+ bool skip = false;
+ const VkImageLayout layout = (new_not_old) ? img_barrier->newLayout : img_barrier->oldLayout;
+ UNIQUE_VALIDATION_ERROR_CODE msg_code = VALIDATION_ERROR_UNDEFINED; // sentinel value meaning "no error"
+
+ switch (layout) {
+ case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+ if ((usage_flags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) == 0) {
+ msg_code = VALIDATION_ERROR_00303;
+ }
+ break;
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
+ if ((usage_flags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0) {
+ msg_code = VALIDATION_ERROR_00304;
+ }
+ break;
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
+ if ((usage_flags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0) {
+ msg_code = VALIDATION_ERROR_00305;
+ }
+ break;
+ case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
+ if ((usage_flags & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) == 0) {
+ msg_code = VALIDATION_ERROR_00306;
+ }
+ break;
+ case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
+ if ((usage_flags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) == 0) {
+ msg_code = VALIDATION_ERROR_00307;
+ }
+ break;
+ case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
+ if ((usage_flags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0) {
+ msg_code = VALIDATION_ERROR_00308;
+ }
+ break;
+ default:
+ // Other VkImageLayout values do not have VUs defined in this context.
+ break;
+ }
+
+ if (msg_code != VALIDATION_ERROR_UNDEFINED) {
+ skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, msg_code,
+ "DS", "%s: Image barrier 0x%p %sLayout=%s is not compatible with image 0x%" PRIx64 " usage flags 0x%" PRIx32
+ ". %s",
+ func_name, img_barrier, ((new_not_old) ? "new" : "old"), string_VkImageLayout(layout),
+ (uint64_t)(img_barrier->image), usage_flags, validation_error_map[msg_code]);
+ }
+ return skip;
+}
+
+// Verify image barriers are compatible with the images they reference.
+bool ValidateBarriersToImages(layer_data *device_data, VkCommandBuffer cmdBuffer, uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *pImageMemoryBarriers, const char *func_name) {
GLOBAL_CB_NODE *pCB = GetCBNode(device_data, cmdBuffer);
bool skip = false;
- uint32_t levelCount = 0;
- uint32_t layerCount = 0;
+ uint32_t level_count = 0;
+ uint32_t layer_count = 0;
- for (uint32_t i = 0; i < memBarrierCount; ++i) {
- auto mem_barrier = &pImgMemBarriers[i];
- if (!mem_barrier) continue;
+ for (uint32_t i = 0; i < imageMemoryBarrierCount; ++i) {
+ auto img_barrier = &pImageMemoryBarriers[i];
+ if (!img_barrier) continue;
+
// TODO: Do not iterate over every possibility - consolidate where possible
- ResolveRemainingLevelsLayers(device_data, &levelCount, &layerCount, mem_barrier->subresourceRange,
- GetImageState(device_data, mem_barrier->image));
+ ResolveRemainingLevelsLayers(device_data, &level_count, &layer_count, img_barrier->subresourceRange,
+ GetImageState(device_data, img_barrier->image));
- for (uint32_t j = 0; j < levelCount; j++) {
- uint32_t level = mem_barrier->subresourceRange.baseMipLevel + j;
- for (uint32_t k = 0; k < layerCount; k++) {
- uint32_t layer = mem_barrier->subresourceRange.baseArrayLayer + k;
- skip |= ValidateImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_COLOR_BIT);
- skip |= ValidateImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_DEPTH_BIT);
- skip |= ValidateImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_STENCIL_BIT);
- skip |= ValidateImageAspectLayout(device_data, pCB, mem_barrier, level, layer, VK_IMAGE_ASPECT_METADATA_BIT);
+ for (uint32_t j = 0; j < level_count; j++) {
+ uint32_t level = img_barrier->subresourceRange.baseMipLevel + j;
+ for (uint32_t k = 0; k < layer_count; k++) {
+ uint32_t layer = img_barrier->subresourceRange.baseArrayLayer + k;
+ skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_COLOR_BIT);
+ skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_DEPTH_BIT);
+ skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_STENCIL_BIT);
+ skip |= ValidateImageAspectLayout(device_data, pCB, img_barrier, level, layer, VK_IMAGE_ASPECT_METADATA_BIT);
}
}
+
+ IMAGE_STATE *image_state = GetImageState(device_data, img_barrier->image);
+ if (image_state) {
+ VkImageUsageFlags usage_flags = image_state->createInfo.usage;
+ skip |= ValidateBarrierLayoutToImageUsage(device_data, img_barrier, false, usage_flags, func_name);
+ skip |= ValidateBarrierLayoutToImageUsage(device_data, img_barrier, true, usage_flags, func_name);
+ }
}
return skip;
}
diff --git a/layers/buffer_validation.h b/layers/buffer_validation.h
index e83ee9b..c318fb2 100644
--- a/layers/buffer_validation.h
+++ b/layers/buffer_validation.h
@@ -111,8 +111,11 @@
void TransitionImageAspectLayout(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkImageMemoryBarrier *mem_barrier, uint32_t level,
uint32_t layer, VkImageAspectFlags aspect);
-bool ValidateImageLayouts(layer_data *device_data, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount,
- const VkImageMemoryBarrier *pImgMemBarriers);
+bool ValidateBarrierLayoutToImageUsage(layer_data *device_data, const VkImageMemoryBarrier *img_barrier, bool new_not_old,
+ VkImageUsageFlags usage, const char *func_name);
+
+bool ValidateBarriersToImages(layer_data *device_data, VkCommandBuffer cmdBuffer, uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *pImageMemoryBarriers, const char *func_name);
void TransitionImageLayouts(layer_data *device_data, VkCommandBuffer cmdBuffer, uint32_t memBarrierCount,
const VkImageMemoryBarrier *pImgMemBarriers);
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 17f0b20..f64a4b7 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -8386,7 +8386,8 @@
cb_state->eventUpdates.push_back(event_update);
skip |= ValidateCmd(dev_data, cb_state, CMD_WAITEVENTS, "vkCmdWaitEvents()");
UpdateCmdBufferLastCmd(cb_state, CMD_WAITEVENTS);
- skip |= ValidateImageLayouts(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
+ skip |=
+ ValidateBarriersToImages(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers, "vkCmdWaitEvents()");
if (!skip) {
TransitionImageLayouts(dev_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
}
@@ -8414,7 +8415,8 @@
VALIDATION_ERROR_00267);
skip |= ValidateStageMaskGsTsEnables(device_data, dstStageMask, "vkCmdPipelineBarrier()", VALIDATION_ERROR_00266,
VALIDATION_ERROR_00268);
- skip |= ValidateImageLayouts(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers);
+ skip |= ValidateBarriersToImages(device_data, commandBuffer, imageMemoryBarrierCount, pImageMemoryBarriers,
+ "vkCmdPipelineBarrier()");
skip |= ValidateBarriers("vkCmdPipelineBarrier()", commandBuffer, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
return skip;
diff --git a/layers/vk_validation_error_database.txt b/layers/vk_validation_error_database.txt
index 526da22..c6973e1 100644
--- a/layers/vk_validation_error_database.txt
+++ b/layers/vk_validation_error_database.txt
@@ -304,12 +304,12 @@
VALIDATION_ERROR_00300~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If image was created with a sharing mode of VK_SHARING_MODE_EXCLUSIVE, and srcQueueFamilyIndex and dstQueueFamilyIndex are valid queue families, at least one of them must be the same as the family of the queue that will execute this barrier' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
VALIDATION_ERROR_00301~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'subresourceRange must be a valid image subresource range for the image (see [resources-image-views])' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
VALIDATION_ERROR_00302~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If image has a depth/stencil format with both depth and stencil components, then aspectMask member of subresourceRange must include both VK_IMAGE_ASPECT_DEPTH_BIT and VK_IMAGE_ASPECT_STENCIL_BIT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
-VALIDATION_ERROR_00303~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL then image must have been created with VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
-VALIDATION_ERROR_00304~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL then image must have been created with VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
-VALIDATION_ERROR_00305~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL then image must have been created with VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
-VALIDATION_ERROR_00306~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL then image must have been created with VK_IMAGE_USAGE_SAMPLED_BIT or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
-VALIDATION_ERROR_00307~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL then image must have been created with VK_IMAGE_USAGE_TRANSFER_SRC_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
-VALIDATION_ERROR_00308~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL then image must have been created with VK_IMAGE_USAGE_TRANSFER_DST_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
+VALIDATION_ERROR_00303~^~Y~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL then image must have been created with VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
+VALIDATION_ERROR_00304~^~Y~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL then image must have been created with VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
+VALIDATION_ERROR_00305~^~Y~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL then image must have been created with VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
+VALIDATION_ERROR_00306~^~Y~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL then image must have been created with VK_IMAGE_USAGE_SAMPLED_BIT or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
+VALIDATION_ERROR_00307~^~Y~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL then image must have been created with VK_IMAGE_USAGE_TRANSFER_SRC_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
+VALIDATION_ERROR_00308~^~Y~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'If either oldLayout or newLayout is VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL then image must have been created with VK_IMAGE_USAGE_TRANSFER_DST_BIT set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~
VALIDATION_ERROR_00309~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'sType must be VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~implicit, TBD in parameter validation layer.
VALIDATION_ERROR_00310~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'pNext must be NULL' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~implicit, TBD in parameter validation layer.
VALIDATION_ERROR_00311~^~N~^~Unknown~^~vkCmdPipelineBarrier~^~For more information refer to Vulkan Spec Section '6.6.3. Image Memory Barriers' which states 'srcAccessMask must be a valid combination of VkAccessFlagBits values' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/xhtml/vkspec.html#VkImageMemoryBarrier)~^~implicit