aboutsummaryrefslogtreecommitdiff
path: root/layers/core_validation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layers/core_validation.cpp')
-rw-r--r--layers/core_validation.cpp191
1 files changed, 106 insertions, 85 deletions
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 135b3a72..c18ca569 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -1753,6 +1753,7 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) {
pCB->updateBuffers.clear();
clear_cmd_buf_and_mem_references(dev_data, pCB);
pCB->validate_functions.clear();
+ pCB->secondary_validate_functions.clear();
pCB->eventUpdates.clear();
pCB->queryUpdates.clear();
@@ -6153,8 +6154,88 @@ static VkPipelineStageFlags ExpandPipelineStageFlags(VkPipelineStageFlags inflag
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
}
+// Verify image barrier image state and that the image is consistent with FB image
+static bool ValidateImageBarrierImage(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE const *cb_state,
+ uint32_t active_subpass, const safe_VkSubpassDescription &sub_desc, uint64_t rp_handle,
+ uint32_t img_index, const VkImageMemoryBarrier &img_barrier) {
+ bool skip = false;
+ const auto &fb_state = GetFramebufferState(device_data, cb_state->activeFramebuffer);
+ assert(fb_state);
+ const auto img_bar_image = img_barrier.image;
+ bool image_match = false;
+ bool sub_image_found = false; // Do we find a corresponding subpass description
+ VkImageLayout sub_image_layout = VK_IMAGE_LAYOUT_UNDEFINED;
+ uint32_t attach_index = 0;
+ uint32_t index_count = 0;
+ // Verify that a framebuffer image matches barrier image
+ for (const auto &fb_attach : fb_state->attachments) {
+ if (img_bar_image == fb_attach.image) {
+ image_match = true;
+ attach_index = index_count;
+ break;
+ }
+ index_count++;
+ }
+ if (image_match) { // Make sure subpass is referring to matching attachment
+ if (sub_desc.pDepthStencilAttachment && sub_desc.pDepthStencilAttachment->attachment == attach_index) {
+ sub_image_layout = sub_desc.pDepthStencilAttachment->layout;
+ sub_image_found = true;
+ } else {
+ for (uint32_t j = 0; j < sub_desc.colorAttachmentCount; ++j) {
+ if (sub_desc.pColorAttachments && sub_desc.pColorAttachments[j].attachment == attach_index) {
+ sub_image_layout = sub_desc.pColorAttachments[j].layout;
+ sub_image_found = true;
+ break;
+ } else if (sub_desc.pResolveAttachments && sub_desc.pResolveAttachments[j].attachment == attach_index) {
+ sub_image_layout = sub_desc.pResolveAttachments[j].layout;
+ sub_image_found = true;
+ break;
+ }
+ }
+ }
+ if (!sub_image_found) {
+ skip |= log_msg(
+ device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, rp_handle,
+ __LINE__, VALIDATION_ERROR_1b800936, "CORE",
+ "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
+ ") is not referenced by the VkSubpassDescription for active subpass (%d) of current renderPass (0x%" PRIx64 "). %s",
+ funcName, img_index, HandleToUint64(img_bar_image), active_subpass, rp_handle,
+ validation_error_map[VALIDATION_ERROR_1b800936]);
+ }
+ } else { // !image_match
+ auto const fb_handle = HandleToUint64(fb_state->framebuffer);
+ skip |=
+ log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, fb_handle,
+ __LINE__, VALIDATION_ERROR_1b800936, "CORE",
+ "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
+ ") does not match an image from the current framebuffer (0x%" PRIx64 "). %s",
+ funcName, img_index, HandleToUint64(img_bar_image), fb_handle, validation_error_map[VALIDATION_ERROR_1b800936]);
+ }
+ if (img_barrier.oldLayout != img_barrier.newLayout) {
+ skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+ HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b80093a, "CORE",
+ "%s: As the Image Barrier for image 0x%" PRIx64
+ " is being executed within a render pass instance, oldLayout must equal newLayout yet they are "
+ "%s and %s. %s",
+ funcName, HandleToUint64(img_barrier.image), string_VkImageLayout(img_barrier.oldLayout),
+ string_VkImageLayout(img_barrier.newLayout), validation_error_map[VALIDATION_ERROR_1b80093a]);
+ } else {
+ if (sub_image_found && sub_image_layout != img_barrier.oldLayout) {
+ skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
+ rp_handle, __LINE__, VALIDATION_ERROR_1b800938, "CORE",
+ "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
+ ") is referenced by the VkSubpassDescription for active subpass (%d) of current renderPass (0x%" PRIx64
+ ") as having layout %s, but image barrier has layout %s. %s",
+ funcName, img_index, HandleToUint64(img_bar_image), active_subpass, rp_handle,
+ string_VkImageLayout(img_barrier.oldLayout), string_VkImageLayout(sub_image_layout),
+ validation_error_map[VALIDATION_ERROR_1b800938]);
+ }
+ }
+ return skip;
+}
+
// Validate image barriers within a renderPass
-static bool ValidateRenderPassImageBarriers(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE const *cb_state,
+static bool ValidateRenderPassImageBarriers(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE *cb_state,
uint32_t active_subpass, const safe_VkSubpassDescription &sub_desc, uint64_t rp_handle,
VkAccessFlags sub_src_access_mask, VkAccessFlags sub_dst_access_mask,
uint32_t image_mem_barrier_count, const VkImageMemoryBarrier *image_barriers) {
@@ -6190,83 +6271,16 @@ static bool ValidateRenderPassImageBarriers(layer_data *device_data, const char
funcName, i, img_barrier.srcQueueFamilyIndex, i, img_barrier.dstQueueFamilyIndex,
validation_error_map[VALIDATION_ERROR_1b80093c]);
}
- // TODO : Secondary CBs could have null framebuffer so just skipping that case for now. Need to correctly
- // handle that case at ExecuteCBs time
- const auto &fb_state = GetFramebufferState(device_data, cb_state->activeFramebuffer);
- if (fb_state) {
- const auto img_bar_image = img_barrier.image;
- bool image_match = false;
- bool sub_image_found = false; // Do we find a corresponding subpass description
- VkImageLayout sub_image_layout = VK_IMAGE_LAYOUT_UNDEFINED;
- uint32_t attach_index = 0;
- uint32_t index_count = 0;
- // Verify that a framebuffer image matches barrier image
- for (const auto &fb_attach : fb_state->attachments) {
- if (img_bar_image == fb_attach.image) {
- image_match = true;
- attach_index = index_count;
- break;
- }
- index_count++;
- }
- if (image_match) { // Make sure subpass is referring to matching attachment
- if (sub_desc.pDepthStencilAttachment && sub_desc.pDepthStencilAttachment->attachment == attach_index) {
- sub_image_layout = sub_desc.pDepthStencilAttachment->layout;
- sub_image_found = true;
- } else {
- for (uint32_t j = 0; j < sub_desc.colorAttachmentCount; ++j) {
- if (sub_desc.pColorAttachments && sub_desc.pColorAttachments[j].attachment == attach_index) {
- sub_image_layout = sub_desc.pColorAttachments[j].layout;
- sub_image_found = true;
- break;
- } else if (sub_desc.pResolveAttachments && sub_desc.pResolveAttachments[j].attachment == attach_index) {
- sub_image_layout = sub_desc.pResolveAttachments[j].layout;
- sub_image_found = true;
- break;
- }
- }
- }
- if (!sub_image_found) {
- skip |= log_msg(
- device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
- rp_handle, __LINE__, VALIDATION_ERROR_1b800936, "CORE",
- "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
- ") is not referenced by the VkSubpassDescription for active subpass (%d) of current renderPass (0x%" PRIx64
- "). %s",
- funcName, i, HandleToUint64(img_bar_image), active_subpass, rp_handle,
- validation_error_map[VALIDATION_ERROR_1b800936]);
- }
- } else { // !image_match
- auto const fb_handle = HandleToUint64(fb_state->framebuffer);
- skip |=
- log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT,
- fb_handle, __LINE__, VALIDATION_ERROR_1b800936, "CORE",
- "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
- ") does not match an image from the current framebuffer (0x%" PRIx64 "). %s",
- funcName, i, HandleToUint64(img_bar_image), fb_handle, validation_error_map[VALIDATION_ERROR_1b800936]);
- }
- if (img_barrier.oldLayout != img_barrier.newLayout) {
- skip |=
- log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
- HandleToUint64(cb_state->commandBuffer), __LINE__, VALIDATION_ERROR_1b80093a, "CORE",
- "%s: As the Image Barrier for image 0x%" PRIx64
- " is being executed within a render pass instance, oldLayout must equal newLayout yet they are "
- "%s and %s. %s",
- funcName, HandleToUint64(img_barrier.image), string_VkImageLayout(img_barrier.oldLayout),
- string_VkImageLayout(img_barrier.newLayout), validation_error_map[VALIDATION_ERROR_1b80093a]);
- } else {
- if (sub_image_found && sub_image_layout != img_barrier.oldLayout) {
- skip |= log_msg(
- device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
- rp_handle, __LINE__, VALIDATION_ERROR_1b800938, "CORE",
- "%s: Barrier pImageMemoryBarriers[%d].image (0x%" PRIx64
- ") is referenced by the VkSubpassDescription for active subpass (%d) of current renderPass (0x%" PRIx64
- ") as having layout %s, but image barrier has layout %s. %s",
- funcName, i, HandleToUint64(img_bar_image), active_subpass, rp_handle,
- string_VkImageLayout(img_barrier.oldLayout), string_VkImageLayout(sub_image_layout),
- validation_error_map[VALIDATION_ERROR_1b800938]);
- }
- }
+ // Secondary CBs can have null framebuffer so queue up validation in that case 'til FB is known
+ if (VK_NULL_HANDLE == cb_state->activeFramebuffer) {
+ assert(VK_COMMAND_BUFFER_LEVEL_SECONDARY == cb_state->createInfo.level);
+ // Secondary CB case w/o FB specified delay validation
+ cb_state->secondary_validate_functions.emplace_back([=]() {
+ return ValidateImageBarrierImage(device_data, funcName, cb_state, active_subpass, sub_desc, rp_handle, i,
+ img_barrier);
+ });
+ } else {
+ skip |= ValidateImageBarrierImage(device_data, funcName, cb_state, active_subpass, sub_desc, rp_handle, i, img_barrier);
}
}
return skip;
@@ -6274,7 +6288,7 @@ static bool ValidateRenderPassImageBarriers(layer_data *device_data, const char
// Validate VUs for Pipeline Barriers that are within a renderPass
// Pre: cb_state->activeRenderPass must be a pointer to valid renderPass state
-static bool ValidateRenderPassPipelineBarriers(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE const *cb_state,
+static bool ValidateRenderPassPipelineBarriers(layer_data *device_data, const char *funcName, GLOBAL_CB_NODE *cb_state,
VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
VkDependencyFlags dependency_flags, uint32_t mem_barrier_count,
const VkMemoryBarrier *mem_barriers, uint32_t buffer_mem_barrier_count,
@@ -6755,12 +6769,11 @@ VKAPI_ATTR void VKAPI_CALL CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t
imageMemoryBarrierCount, pImageMemoryBarriers);
}
-static bool PreCallValidateCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE const *cb_state,
- VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
- VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount,
- const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount,
- const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
- const VkImageMemoryBarrier *pImageMemoryBarriers) {
+static bool PreCallValidateCmdPipelineBarrier(layer_data *device_data, GLOBAL_CB_NODE *cb_state, VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
+ uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
+ uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
bool skip = false;
skip |= ValidateStageMasksAgainstQueueCapabilities(device_data, cb_state, srcStageMask, dstStageMask, "vkCmdPipelineBarrier",
VALIDATION_ERROR_1b80093e);
@@ -8260,6 +8273,14 @@ VKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uin
}
// If framebuffer for secondary CB is not NULL, then it must match active FB from primaryCB
skip |= validateFramebuffer(dev_data, commandBuffer, pCB, pCommandBuffers[i], pSubCB);
+ if (VK_NULL_HANDLE == pSubCB->activeFramebuffer) {
+ // This is a state update during validation which is not ideal
+ // Inherit primary's activeFramebuffer and run any validate functions
+ pSubCB->activeFramebuffer = pCB->activeFramebuffer;
+ for (auto &function : pSubCB->secondary_validate_functions) {
+ skip |= function();
+ }
+ }
}
string errorString = "";
// secondaryCB must have been created w/ RP compatible w/ primaryCB active renderpass