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.cpp187
1 files changed, 50 insertions, 137 deletions
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index c2ebffd1..7e3c796f 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -789,45 +789,7 @@ static bool validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE *pCB,
return result;
}
-// Verify attachment reference compatibility according to spec
-// If one array is larger, treat missing elements of shorter array as VK_ATTACHMENT_UNUSED & other array much match this
-// If both AttachmentReference arrays have requested index, check their corresponding AttachmentDescriptions
-// to make sure that format and samples counts match.
-// If not, they are not compatible.
-static bool attachment_references_compatible(const uint32_t index, const VkAttachmentReference *pPrimary,
- const uint32_t primaryCount, const VkAttachmentDescription *pPrimaryAttachments,
- const VkAttachmentReference *pSecondary, const uint32_t secondaryCount,
- const VkAttachmentDescription *pSecondaryAttachments) {
- // Check potential NULL cases first to avoid nullptr issues later
- if (pPrimary == nullptr) {
- if (pSecondary == nullptr) {
- return true;
- }
- return false;
- } else if (pSecondary == nullptr) {
- return false;
- }
- if (index >= primaryCount) { // Check secondary as if primary is VK_ATTACHMENT_UNUSED
- if (VK_ATTACHMENT_UNUSED == pSecondary[index].attachment) return true;
- } else if (index >= secondaryCount) { // Check primary as if secondary is VK_ATTACHMENT_UNUSED
- if (VK_ATTACHMENT_UNUSED == pPrimary[index].attachment) return true;
- } else { // Format and sample count must match
- if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) && (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) {
- return true;
- } else if ((pPrimary[index].attachment == VK_ATTACHMENT_UNUSED) || (pSecondary[index].attachment == VK_ATTACHMENT_UNUSED)) {
- return false;
- }
- if ((pPrimaryAttachments[pPrimary[index].attachment].format ==
- pSecondaryAttachments[pSecondary[index].attachment].format) &&
- (pPrimaryAttachments[pPrimary[index].attachment].samples ==
- pSecondaryAttachments[pSecondary[index].attachment].samples))
- return true;
- }
- // Format and sample counts didn't match
- return false;
-}
-
-static bool logInvalidAttachmentMessage(layer_data *dev_data, const char *type1_string, const RENDER_PASS_STATE *rp1_state,
+static bool logInvalidAttachmentMessage(layer_data const *dev_data, const char *type1_string, const RENDER_PASS_STATE *rp1_state,
const char *type2_string, const RENDER_PASS_STATE *rp2_state, uint32_t primary_attach,
uint32_t secondary_attach, const char *msg, const char *caller,
UNIQUE_VALIDATION_ERROR_CODE error_code) {
@@ -839,10 +801,10 @@ static bool logInvalidAttachmentMessage(layer_data *dev_data, const char *type1_
primary_attach, secondary_attach, msg, validation_error_map[error_code]);
}
-static bool validateAttachmentCompatibility(layer_data *dev_data, const char *type1_string, const RENDER_PASS_STATE *rp1_state,
- const char *type2_string, const RENDER_PASS_STATE *rp2_state, uint32_t primary_attach,
- uint32_t secondary_attach, bool is_multi, const char *caller,
- UNIQUE_VALIDATION_ERROR_CODE error_code) {
+static bool validateAttachmentCompatibility(layer_data const *dev_data, const char *type1_string,
+ const RENDER_PASS_STATE *rp1_state, const char *type2_string,
+ const RENDER_PASS_STATE *rp2_state, uint32_t primary_attach, uint32_t secondary_attach,
+ bool is_multi, const char *caller, UNIQUE_VALIDATION_ERROR_CODE error_code) {
bool skip = false;
const auto &primaryPassCI = rp1_state->createInfo;
const auto &secondaryPassCI = rp2_state->createInfo;
@@ -882,7 +844,7 @@ static bool validateAttachmentCompatibility(layer_data *dev_data, const char *ty
return skip;
}
-static bool validateSubpassCompatibility(layer_data *dev_data, const char *type1_string, const RENDER_PASS_STATE *rp1_state,
+static bool validateSubpassCompatibility(layer_data const *dev_data, const char *type1_string, const RENDER_PASS_STATE *rp1_state,
const char *type2_string, const RENDER_PASS_STATE *rp2_state, const int subpass,
bool is_multi, const char *caller, UNIQUE_VALIDATION_ERROR_CODE error_code) {
bool skip = false;
@@ -936,8 +898,9 @@ static bool validateSubpassCompatibility(layer_data *dev_data, const char *type1
// Verify that given renderPass CreateInfo for primary and secondary command buffers are compatible.
// This function deals directly with the CreateInfo, there are overloaded versions below that can take the renderPass handle and
// will then feed into this function
-static bool validateRenderPassCompatibility(layer_data *dev_data, const char *type1_string, const RENDER_PASS_STATE *rp1_state,
- const char *type2_string, const RENDER_PASS_STATE *rp2_state, const char *caller,
+static bool validateRenderPassCompatibility(layer_data const *dev_data, const char *type1_string,
+ const RENDER_PASS_STATE *rp1_state, const char *type2_string,
+ const RENDER_PASS_STATE *rp2_state, const char *caller,
UNIQUE_VALIDATION_ERROR_CODE error_code) {
bool skip = false;
@@ -958,68 +921,6 @@ static bool validateRenderPassCompatibility(layer_data *dev_data, const char *ty
return skip;
}
-// TODO : Scrub verify_renderpass_compatibility() and validateRenderPassCompatibility() and unify them and/or share code
-// For given primary RenderPass object and secondary RenderPassCreateInfo, verify that they're compatible
-static bool verify_renderpass_compatibility(const layer_data *dev_data, const VkRenderPassCreateInfo *primaryRPCI,
- const VkRenderPassCreateInfo *secondaryRPCI, string &errorMsg) {
- if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) {
- stringstream errorStr;
- errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount
- << " subpasses but renderPass for secondary cmdBuffer has " << secondaryRPCI->subpassCount << " subpasses.";
- errorMsg = errorStr.str();
- return false;
- }
- uint32_t spIndex = 0;
- for (spIndex = 0; spIndex < primaryRPCI->subpassCount; ++spIndex) {
- // For each subpass, verify that corresponding color, input, resolve & depth/stencil attachment references are compatible
- uint32_t primaryColorCount = primaryRPCI->pSubpasses[spIndex].colorAttachmentCount;
- uint32_t secondaryColorCount = secondaryRPCI->pSubpasses[spIndex].colorAttachmentCount;
- uint32_t colorMax = std::max(primaryColorCount, secondaryColorCount);
- for (uint32_t cIdx = 0; cIdx < colorMax; ++cIdx) {
- if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pColorAttachments, primaryColorCount,
- primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pColorAttachments,
- secondaryColorCount, secondaryRPCI->pAttachments)) {
- stringstream errorStr;
- errorStr << "color attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible.";
- errorMsg = errorStr.str();
- return false;
- } else if (!attachment_references_compatible(cIdx, primaryRPCI->pSubpasses[spIndex].pResolveAttachments,
- primaryColorCount, primaryRPCI->pAttachments,
- secondaryRPCI->pSubpasses[spIndex].pResolveAttachments,
- secondaryColorCount, secondaryRPCI->pAttachments)) {
- stringstream errorStr;
- errorStr << "resolve attachments at index " << cIdx << " of subpass index " << spIndex << " are not compatible.";
- errorMsg = errorStr.str();
- return false;
- }
- }
-
- if (!attachment_references_compatible(0, primaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment, 1,
- primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pDepthStencilAttachment,
- 1, secondaryRPCI->pAttachments)) {
- stringstream errorStr;
- errorStr << "depth/stencil attachments of subpass index " << spIndex << " are not compatible.";
- errorMsg = errorStr.str();
- return false;
- }
-
- uint32_t primaryInputCount = primaryRPCI->pSubpasses[spIndex].inputAttachmentCount;
- uint32_t secondaryInputCount = secondaryRPCI->pSubpasses[spIndex].inputAttachmentCount;
- uint32_t inputMax = std::max(primaryInputCount, secondaryInputCount);
- for (uint32_t i = 0; i < inputMax; ++i) {
- if (!attachment_references_compatible(i, primaryRPCI->pSubpasses[spIndex].pInputAttachments, primaryInputCount,
- primaryRPCI->pAttachments, secondaryRPCI->pSubpasses[spIndex].pInputAttachments,
- secondaryInputCount, secondaryRPCI->pAttachments)) {
- stringstream errorStr;
- errorStr << "input attachments at index " << i << " of subpass index " << spIndex << " are not compatible.";
- errorMsg = errorStr.str();
- return false;
- }
- }
- }
- return true;
-}
-
// Return Set node ptr for specified set or else NULL
cvdescriptorset::DescriptorSet *GetSetNode(const layer_data *dev_data, VkDescriptorSet set) {
auto set_it = dev_data->setMap.find(set);
@@ -1052,7 +953,7 @@ static void list_bits(std::ostream &s, uint32_t bits) {
// Validate draw-time state related to the PSO
static bool ValidatePipelineDrawtimeState(layer_data const *dev_data, LAST_BOUND_STATE const &state, const GLOBAL_CB_NODE *pCB,
- PIPELINE_STATE const *pPipeline) {
+ CMD_TYPE cmd_type, PIPELINE_STATE const *pPipeline, const char *caller) {
bool skip = false;
// Verify vertex binding
@@ -1156,38 +1057,49 @@ static bool ValidatePipelineDrawtimeState(layer_data const *dev_data, LAST_BOUND
}
// Verify that PSO creation renderPass is compatible with active renderPass
if (pCB->activeRenderPass) {
- // TODO : These errors map to VUIDs depending on which type of Draw is being called. Here are the RP mismatch/subpass
- // mismatch codes:
- // Draw: VALIDATION_ERROR_1a200366, VALIDATION_ERROR_1a200368
- // DrawIndexed: VALIDATION_ERROR_1a40038c, VALIDATION_ERROR_1a40038e
- // DrawIndexedIndirect: VALIDATION_ERROR_1a600426, VALIDATION_ERROR_1a600428
- // DrawIndexedIndirectCountAMD: VALIDATION_ERROR_1a800460, VALIDATION_ERROR_1a800462
- // DrawIndirect: VALIDATION_ERROR_1aa003be, VALIDATION_ERROR_1aa003c0
- // DrawIndirectCountAMD: VALIDATION_ERROR_1ac003f6, VALIDATION_ERROR_1ac003f8
- //
- // For CmdExecuteCommands Checks: VALIDATION_ERROR_1b2000c4, VALIDATION_ERROR_1b2000c6
+ // TODO: Move all of the error codes common across different Draws into a LUT accessed by cmd_type
+ // TODO: AMD extension codes are included here, but actual function entrypoints are not yet intercepted
+ // Error codes for renderpass and subpass mismatches
+ auto rp_error = VALIDATION_ERROR_1a200366, sp_error = VALIDATION_ERROR_1a200368;
+ switch (cmd_type) {
+ case CMD_DRAWINDEXED:
+ rp_error = VALIDATION_ERROR_1a40038c;
+ sp_error = VALIDATION_ERROR_1a40038e;
+ break;
+ case CMD_DRAWINDIRECT:
+ rp_error = VALIDATION_ERROR_1aa003be;
+ sp_error = VALIDATION_ERROR_1aa003c0;
+ break;
+ case CMD_DRAWINDIRECTCOUNTAMD:
+ rp_error = VALIDATION_ERROR_1ac003f6;
+ sp_error = VALIDATION_ERROR_1ac003f8;
+ break;
+ case CMD_DRAWINDEXEDINDIRECT:
+ rp_error = VALIDATION_ERROR_1a600426;
+ sp_error = VALIDATION_ERROR_1a600428;
+ break;
+ case CMD_DRAWINDEXEDINDIRECTCOUNTAMD:
+ rp_error = VALIDATION_ERROR_1a800460;
+ sp_error = VALIDATION_ERROR_1a800462;
+ break;
+ default:
+ assert(CMD_DRAW == cmd_type);
+ break;
+ }
std::string err_string;
- if ((pCB->activeRenderPass->renderPass != pPipeline->graphicsPipelineCI.renderPass) &&
- !verify_renderpass_compatibility(dev_data, pCB->activeRenderPass->createInfo.ptr(), pPipeline->render_pass_ci.ptr(),
- err_string)) {
+ if (pCB->activeRenderPass->renderPass != pPipeline->graphicsPipelineCI.renderPass) {
// renderPass that PSO was created with must be compatible with active renderPass that PSO is being used with
- skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
- HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
- "At Draw time the active render pass (0x%" PRIxLEAST64
- ") is incompatible w/ gfx pipeline "
- "(0x%" PRIxLEAST64 ") that was created w/ render pass (0x%" PRIxLEAST64 ") due to: %s",
- HandleToUint64(pCB->activeRenderPass->renderPass), HandleToUint64(pPipeline->pipeline),
- HandleToUint64(pPipeline->graphicsPipelineCI.renderPass), err_string.c_str());
+ skip |= validateRenderPassCompatibility(dev_data, "active render pass", pCB->activeRenderPass, "pipeline state object",
+ GetRenderPassState(dev_data, pPipeline->graphicsPipelineCI.renderPass), caller,
+ rp_error);
}
-
if (pPipeline->graphicsPipelineCI.subpass != pCB->activeSubpass) {
skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
- HandleToUint64(pPipeline->pipeline), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
- "Pipeline was built for subpass %u but used in subpass %u", pPipeline->graphicsPipelineCI.subpass,
- pCB->activeSubpass);
+ HandleToUint64(pPipeline->pipeline), __LINE__, sp_error, "DS",
+ "Pipeline was built for subpass %u but used in subpass %u. %s", pPipeline->graphicsPipelineCI.subpass,
+ pCB->activeSubpass, validation_error_map[sp_error]);
}
}
- // TODO : Add more checks here
return skip;
}
@@ -1212,7 +1124,7 @@ static bool verify_set_layout_compatibility(const cvdescriptorset::DescriptorSet
}
// Validate overall state at the time of a draw call
-static bool ValidateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, const bool indexed,
+static bool ValidateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, CMD_TYPE cmd_type, const bool indexed,
const VkPipelineBindPoint bind_point, const char *function,
UNIQUE_VALIDATION_ERROR_CODE const msg_code) {
bool result = false;
@@ -1274,7 +1186,8 @@ static bool ValidateDrawState(layer_data *dev_data, GLOBAL_CB_NODE *cb_node, con
}
// Check general pipeline state that needs to be validated at drawtime
- if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) result |= ValidatePipelineDrawtimeState(dev_data, state, cb_node, pPipe);
+ if (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point)
+ result |= ValidatePipelineDrawtimeState(dev_data, state, cb_node, cmd_type, pPipe, function);
return result;
}
@@ -5856,7 +5769,7 @@ static bool ValidateCmdDrawType(layer_data *dev_data, VkCommandBuffer cmd_buffer
if (*cb_state) {
skip |= ValidateCmdQueueFlags(dev_data, *cb_state, caller, queue_flags, queue_flag_code);
skip |= ValidateCmd(dev_data, *cb_state, cmd_type, caller);
- skip |= ValidateDrawState(dev_data, *cb_state, indexed, bind_point, caller, dynamic_state_msg_code);
+ skip |= ValidateDrawState(dev_data, *cb_state, cmd_type, indexed, bind_point, caller, dynamic_state_msg_code);
skip |= (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) ? outsideRenderPass(dev_data, *cb_state, caller, msg_code)
: insideRenderPass(dev_data, *cb_state, caller, msg_code);
}