}
// Check object status for selected flag state
-static VkBool32 validate_status(layer_data *my_data, GLOBAL_CB_NODE *pNode, CBStatusFlags enable_mask, CBStatusFlags status_mask,
- CBStatusFlags status_flag, VkFlags msg_flags, DRAW_STATE_ERROR error_code, const char *fail_msg) {
- // If non-zero enable mask is present, check it against status but if enable_mask
- // is 0 then no enable required so we should always just check status
- if ((!enable_mask) || (enable_mask & pNode->status)) {
- if ((pNode->status & status_mask) != status_flag) {
- // TODO : How to pass dispatchable objects as srcObject? Here src obj should be cmd buffer
- return log_msg(my_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, error_code,
- "DS", "CB object %#" PRIxLEAST64 ": %s", (uint64_t)(pNode->commandBuffer), fail_msg);
- }
+static VkBool32 validate_status(layer_data *my_data, GLOBAL_CB_NODE *pNode, CBStatusFlags status_mask, VkFlags msg_flags,
+ DRAW_STATE_ERROR error_code, const char *fail_msg) {
+ if (!(pNode->status & status_mask)) {
+ return log_msg(my_data->report_data, msg_flags, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
+ reinterpret_cast<const uint64_t &>(pNode->commandBuffer), __LINE__, error_code, "DS",
+ "CB object %#" PRIxLEAST64 ": %s", reinterpret_cast<const uint64_t &>(pNode->commandBuffer), fail_msg);
}
return VK_FALSE;
}
}
// Validate state stored as flags at time of draw call
-static VkBool32 validate_draw_state_flags(layer_data *my_data, GLOBAL_CB_NODE *pCB, VkBool32 indexedDraw) {
+static VkBool32 validate_draw_state_flags(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const PIPELINE_NODE *pPipe,
+ VkBool32 indexedDraw) {
VkBool32 result;
- result =
- validate_status(my_data, pCB, CBSTATUS_NONE, CBSTATUS_VIEWPORT_SET, CBSTATUS_VIEWPORT_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
- DRAWSTATE_VIEWPORT_NOT_BOUND, "Dynamic viewport state not set for this command buffer");
- result |=
- validate_status(my_data, pCB, CBSTATUS_NONE, CBSTATUS_SCISSOR_SET, CBSTATUS_SCISSOR_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
- DRAWSTATE_SCISSOR_NOT_BOUND, "Dynamic scissor state not set for this command buffer");
- result |= validate_status(my_data, pCB, CBSTATUS_NONE, CBSTATUS_LINE_WIDTH_SET, CBSTATUS_LINE_WIDTH_SET,
- VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_LINE_WIDTH_NOT_BOUND,
- "Dynamic line width state not set for this command buffer");
- result |= validate_status(my_data, pCB, CBSTATUS_NONE, CBSTATUS_DEPTH_BIAS_SET, CBSTATUS_DEPTH_BIAS_SET,
- VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_DEPTH_BIAS_NOT_BOUND,
- "Dynamic depth bias state not set for this command buffer");
- result |= validate_status(my_data, pCB, CBSTATUS_COLOR_BLEND_WRITE_ENABLE, CBSTATUS_BLEND_SET, CBSTATUS_BLEND_SET,
- VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_BLEND_NOT_BOUND,
- "Dynamic blend object state not set for this command buffer");
- result |= validate_status(my_data, pCB, CBSTATUS_DEPTH_WRITE_ENABLE, CBSTATUS_DEPTH_BOUNDS_SET, CBSTATUS_DEPTH_BOUNDS_SET,
- VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND,
- "Dynamic depth bounds state not set for this command buffer");
- result |= validate_status(my_data, pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_READ_MASK_SET,
- CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_STENCIL_NOT_BOUND,
- "Dynamic stencil read mask state not set for this command buffer");
- result |= validate_status(my_data, pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_WRITE_MASK_SET,
- CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_STENCIL_NOT_BOUND,
- "Dynamic stencil write mask state not set for this command buffer");
- result |= validate_status(my_data, pCB, CBSTATUS_STENCIL_TEST_ENABLE, CBSTATUS_STENCIL_REFERENCE_SET,
- CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_STENCIL_NOT_BOUND,
- "Dynamic stencil reference state not set for this command buffer");
- if (indexedDraw)
- result |= validate_status(my_data, pCB, CBSTATUS_NONE, CBSTATUS_INDEX_BUFFER_BOUND, CBSTATUS_INDEX_BUFFER_BOUND,
- VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_INDEX_BUFFER_NOT_BOUND,
+ result = validate_status(dev_data, pCB, CBSTATUS_VIEWPORT_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_VIEWPORT_NOT_BOUND,
+ "Dynamic viewport state not set for this command buffer");
+ result |= validate_status(dev_data, pCB, CBSTATUS_SCISSOR_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT, DRAWSTATE_SCISSOR_NOT_BOUND,
+ "Dynamic scissor state not set for this command buffer");
+ if ((pPipe->iaStateCI.topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) ||
+ (pPipe->iaStateCI.topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP)) {
+ result |= validate_status(dev_data, pCB, CBSTATUS_LINE_WIDTH_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ DRAWSTATE_LINE_WIDTH_NOT_BOUND, "Dynamic line width state not set for this command buffer");
+ }
+ if (pPipe->rsStateCI.depthBiasEnable) {
+ result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BIAS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ DRAWSTATE_DEPTH_BIAS_NOT_BOUND, "Dynamic depth bias state not set for this command buffer");
+ }
+ if (pPipe->blendConstantsEnabled) {
+ result |= validate_status(dev_data, pCB, CBSTATUS_BLEND_CONSTANTS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ DRAWSTATE_BLEND_NOT_BOUND, "Dynamic blend constants state not set for this command buffer");
+ }
+ if (pPipe->dsStateCI.depthBoundsTestEnable) {
+ result |= validate_status(dev_data, pCB, CBSTATUS_DEPTH_BOUNDS_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ DRAWSTATE_DEPTH_BOUNDS_NOT_BOUND, "Dynamic depth bounds state not set for this command buffer");
+ }
+ if (pPipe->dsStateCI.stencilTestEnable) {
+ result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_READ_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil read mask state not set for this command buffer");
+ result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_WRITE_MASK_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil write mask state not set for this command buffer");
+ result |= validate_status(dev_data, pCB, CBSTATUS_STENCIL_REFERENCE_SET, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ DRAWSTATE_STENCIL_NOT_BOUND, "Dynamic stencil reference state not set for this command buffer");
+ }
+ if (indexedDraw) {
+ result |= validate_status(dev_data, pCB, CBSTATUS_INDEX_BUFFER_BOUND, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ DRAWSTATE_INDEX_BUFFER_NOT_BOUND,
"Index buffer object not bound to this command buffer when Indexed Draw attempted");
+ }
return result;
}
// Validate overall state at the time of a draw call
static VkBool32 validate_draw_state(layer_data *my_data, GLOBAL_CB_NODE *pCB, VkBool32 indexedDraw) {
- // First check flag states
- VkBool32 result = validate_draw_state_flags(my_data, pCB, indexedDraw);
PIPELINE_NODE *pPipe = getPipeline(my_data, pCB->lastBound[VK_PIPELINE_BIND_POINT_GRAPHICS].pipeline);
+ // First check flag states
+ VkBool32 result = validate_draw_state_flags(my_data, pCB, pPipe, indexedDraw);
// Now complete other state checks
// TODO : Currently only performing next check if *something* was bound (non-zero last bound)
// There is probably a better way to gate when this check happens, and to know if something *should* have been bound
if (pPipeline->graphicsPipelineCI.pColorBlendState != NULL) {
if (!my_data->physDevProperties.features.independentBlend) {
- if (pPipeline->attachments.size() > 0) {
+ if (pPipeline->attachments.size() > 1) {
VkPipelineColorBlendAttachmentState *pAttachments = &pPipeline->attachments[0];
for (size_t i = 1; i < pPipeline->attachments.size(); i++) {
if ((pAttachments[0].blendEnable != pAttachments[i].blendEnable) ||
// Set PSO-related status bits for CB, including dynamic state set via PSO
static void set_cb_pso_status(GLOBAL_CB_NODE *pCB, const PIPELINE_NODE *pPipe) {
- for (auto const & att : pPipe->attachments) {
- if (0 != att.colorWriteMask) {
- pCB->status |= CBSTATUS_COLOR_BLEND_WRITE_ENABLE;
- }
- }
- if (pPipe->dsStateCI.depthWriteEnable) {
- pCB->status |= CBSTATUS_DEPTH_WRITE_ENABLE;
- }
- if (pPipe->dsStateCI.stencilTestEnable) {
- pCB->status |= CBSTATUS_STENCIL_TEST_ENABLE;
- }
// Account for any dynamic state not set via this PSO
if (!pPipe->dynStateCI.dynamicStateCount) { // All state is static
pCB->status = CBSTATUS_ALL;
psoDynStateMask &= ~CBSTATUS_DEPTH_BIAS_SET;
break;
case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
- psoDynStateMask &= ~CBSTATUS_BLEND_SET;
+ psoDynStateMask &= ~CBSTATUS_BLEND_CONSTANTS_SET;
break;
case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
psoDynStateMask &= ~CBSTATUS_DEPTH_BOUNDS_SET;
return result;
}
+// utility function to set collective state for pipeline
+void set_pipeline_state(PIPELINE_NODE *pPipe) {
+ // If any attachment used by this pipeline has blendEnable, set top-level blendEnable
+ if (pPipe->graphicsPipelineCI.pColorBlendState) {
+ for (size_t i = 0; i < pPipe->attachments.size(); ++i) {
+ if (VK_TRUE == pPipe->attachments[i].blendEnable) {
+ if (((pPipe->attachments[i].dstAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
+ (pPipe->attachments[i].dstAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
+ ((pPipe->attachments[i].dstColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
+ (pPipe->attachments[i].dstColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
+ ((pPipe->attachments[i].srcAlphaBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
+ (pPipe->attachments[i].srcAlphaBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA)) ||
+ ((pPipe->attachments[i].srcColorBlendFactor >= VK_BLEND_FACTOR_CONSTANT_COLOR) &&
+ (pPipe->attachments[i].srcColorBlendFactor <= VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA))) {
+ pPipe->blendConstantsEnabled = true;
+ }
+ }
+ }
+ }
+}
+
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
if (pPN) {
pCB->lastBound[pipelineBindPoint].pipeline = pipeline;
set_cb_pso_status(pCB, pPN);
+ set_pipeline_state(pPN);
skipCall |= validatePipelineState(dev_data, pCB, pipelineBindPoint, pipeline);
} else {
skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
if (pCB) {
skipCall |= addCmd(dev_data, pCB, CMD_SETBLENDSTATE, "vkCmdSetBlendConstants()");
- pCB->status |= CBSTATUS_BLEND_SET;
+ pCB->status |= CBSTATUS_BLEND_CONSTANTS_SET;
}
loader_platform_thread_unlock_mutex(&globalLock);
if (VK_FALSE == skipCall)
std::vector<VkVertexInputBindingDescription> vertexBindingDescriptions;
std::vector<VkVertexInputAttributeDescription> vertexAttributeDescriptions;
std::vector<VkPipelineColorBlendAttachmentState> attachments;
+ bool blendConstantsEnabled; // Blend constants enabled for any attachments
// Default constructor
_PIPELINE_NODE()
: pipeline{}, graphicsPipelineCI{}, vertexInputCI{}, iaStateCI{}, tessStateCI{}, vpStateCI{}, rsStateCI{}, msStateCI{},
cbStateCI{}, dsStateCI{}, dynStateCI{}, vsCI{}, tcsCI{}, tesCI{}, gsCI{}, fsCI{}, computePipelineCI{}, active_shaders(0),
- active_slots(), vertexBindingDescriptions(), vertexAttributeDescriptions(), attachments() {}
+ active_slots(), vertexBindingDescriptions(), vertexAttributeDescriptions(), attachments(), blendConstantsEnabled(false) {}
} PIPELINE_NODE;
class BASE_NODE {
// CB Status -- used to track status of various bindings on cmd buffer objects
typedef VkFlags CBStatusFlags;
typedef enum _CBStatusFlagBits {
- CBSTATUS_NONE = 0x00000000, // No status is set
- CBSTATUS_VIEWPORT_SET = 0x00000001, // Viewport has been set
- CBSTATUS_LINE_WIDTH_SET = 0x00000002, // Line width has been set
- CBSTATUS_DEPTH_BIAS_SET = 0x00000004, // Depth bias has been set
- CBSTATUS_COLOR_BLEND_WRITE_ENABLE = 0x00000008, // PSO w/ CB Enable set has been set
- CBSTATUS_BLEND_SET = 0x00000010, // Blend state object has been set
- CBSTATUS_DEPTH_WRITE_ENABLE = 0x00000020, // PSO w/ Depth Enable set has been set
- CBSTATUS_STENCIL_TEST_ENABLE = 0x00000040, // PSO w/ Stencil Enable set has been set
- CBSTATUS_DEPTH_BOUNDS_SET = 0x00000080, // Depth bounds state object has been set
- CBSTATUS_STENCIL_READ_MASK_SET = 0x00000100, // Stencil read mask has been set
- CBSTATUS_STENCIL_WRITE_MASK_SET = 0x00000200, // Stencil write mask has been set
- CBSTATUS_STENCIL_REFERENCE_SET = 0x00000400, // Stencil reference has been set
- CBSTATUS_INDEX_BUFFER_BOUND = 0x00000800, // Index buffer has been set
- CBSTATUS_SCISSOR_SET = 0x00001000, // Scissor has been set
- CBSTATUS_ALL = 0x00001FFF, // All dynamic state set
+ // clang-format off
+ CBSTATUS_NONE = 0x00000000, // No status is set
+ CBSTATUS_VIEWPORT_SET = 0x00000001, // Viewport has been set
+ CBSTATUS_LINE_WIDTH_SET = 0x00000002, // Line width has been set
+ CBSTATUS_DEPTH_BIAS_SET = 0x00000004, // Depth bias has been set
+ CBSTATUS_BLEND_CONSTANTS_SET = 0x00000008, // Blend constants state has been set
+ CBSTATUS_DEPTH_BOUNDS_SET = 0x00000010, // Depth bounds state object has been set
+ CBSTATUS_STENCIL_READ_MASK_SET = 0x00000020, // Stencil read mask has been set
+ CBSTATUS_STENCIL_WRITE_MASK_SET = 0x00000040, // Stencil write mask has been set
+ CBSTATUS_STENCIL_REFERENCE_SET = 0x00000080, // Stencil reference has been set
+ CBSTATUS_INDEX_BUFFER_BOUND = 0x00000100, // Index buffer has been set
+ CBSTATUS_SCISSOR_SET = 0x00000200, // Scissor has been set
+ CBSTATUS_ALL = 0x000003FF, // All dynamic state set
+ // clang-format on
} CBStatusFlagBits;
typedef struct stencil_data {