Skip to content

Commit

Permalink
layers: Add Dual Source Blending check
Browse files Browse the repository at this point in the history
  • Loading branch information
spencer-lunarg committed Jun 5, 2024
1 parent 7001473 commit 17f812b
Show file tree
Hide file tree
Showing 11 changed files with 347 additions and 138 deletions.
91 changes: 91 additions & 0 deletions layers/core_checks/cc_drawdispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1533,6 +1533,7 @@ bool CoreChecks::ValidateActionState(const vvl::CommandBuffer &cb_state, const V
skip |= ValidateDrawDynamicState(last_bound_state, vuid);
skip |= ValidateDrawPrimitivesGeneratedQuery(last_bound_state, vuid);
skip |= ValidateDrawProtectedMemory(last_bound_state, vuid);
skip |= ValidateDrawDualSourceBlend(last_bound_state, vuid);

if (pipeline) {
skip |= ValidateDrawPipeline(last_bound_state, *pipeline, vuid);
Expand Down Expand Up @@ -1939,3 +1940,93 @@ bool CoreChecks::ValidateDrawProtectedMemory(const LastBound &last_bound_state,

return skip;
}

bool CoreChecks::ValidateDrawDualSourceBlend(const LastBound &last_bound_state, const vvl::DrawDispatchVuid &vuid) const {
bool skip = false;
const vvl::CommandBuffer &cb_state = last_bound_state.cb_state;
const auto *pipeline = last_bound_state.pipeline_state;
if (pipeline && !pipeline->ColorBlendState()) return skip;

// TODO - have better way to get fragment shader state
std::shared_ptr<const spirv::EntryPoint> entrypoint;
if (pipeline) {
for (const auto &stage : pipeline->stage_states) {
if (stage.entrypoint && (stage.entrypoint->stage == VK_SHADER_STAGE_FRAGMENT_BIT)) {
entrypoint = stage.entrypoint;
break;
}
}
} else {
for (const auto stage : last_bound_state.shader_object_states) {
if (stage && stage->entrypoint && (stage->entrypoint->stage == VK_SHADER_STAGE_FRAGMENT_BIT)) {
entrypoint = stage->entrypoint;
break;
}
}
}
if (!entrypoint) return skip;

uint32_t max_fragment_location = 0;
for (const auto *variable : entrypoint->user_defined_interface_variables) {
if (variable->storage_class != spv::StorageClassOutput) continue;
if (variable->decorations.location != spirv::kInvalidValue) {
max_fragment_location = std::max(max_fragment_location, variable->decorations.location);
}
}
if (max_fragment_location < phys_dev_props.limits.maxFragmentDualSrcAttachments) return skip;

// If color blend is disabled, the blend equation doesn't matter
const bool dynamic_blend_enable = !pipeline || pipeline->IsDynamic(CB_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
const bool dynamic_blend_equation = !pipeline || pipeline->IsDynamic(CB_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
const uint32_t attachment_count = pipeline ? pipeline->ColorBlendState()->attachmentCount
: (uint32_t)cb_state.dynamic_state_value.color_blend_equations.size();
for (uint32_t i = 0; i < attachment_count; ++i) {
const bool blend_enable = dynamic_blend_enable ? cb_state.dynamic_state_value.color_blend_enabled[i]
: pipeline->ColorBlendState()->pAttachments[i].blendEnable;
if (!blend_enable) continue;
if (dynamic_blend_equation) {
const VkColorBlendEquationEXT &color_blend_equation = cb_state.dynamic_state_value.color_blend_equations[i];
if (IsSecondaryColorInputBlendFactor(color_blend_equation.srcColorBlendFactor) ||
IsSecondaryColorInputBlendFactor(color_blend_equation.dstColorBlendFactor) ||
IsSecondaryColorInputBlendFactor(color_blend_equation.srcAlphaBlendFactor) ||
IsSecondaryColorInputBlendFactor(color_blend_equation.dstAlphaBlendFactor)) {
const LogObjectList objlist = cb_state.GetObjectList(VK_PIPELINE_BIND_POINT_GRAPHICS);
skip |= LogError(vuid.blend_dual_source_09239, objlist, vuid.loc(),
"Fragment output attachment %" PRIu32
" is using Dual-Source Blending, but the largest output fragment Location (%" PRIu32
") is not less than maxFragmentDualSrcAttachments (%" PRIu32
"). The following are set by vkCmdSetColorBlendEquationEXT:\n\tsrcColorBlendFactor = "
"%s\n\tdstColorBlendFactor = %s\n\tsrcAlphaBlendFactor = "
"%s\n\tdstAlphaBlendFactor = %s\n",
i, max_fragment_location, phys_dev_props.limits.maxFragmentDualSrcAttachments,
string_VkBlendFactor(color_blend_equation.srcColorBlendFactor),
string_VkBlendFactor(color_blend_equation.dstColorBlendFactor),
string_VkBlendFactor(color_blend_equation.srcAlphaBlendFactor),
string_VkBlendFactor(color_blend_equation.dstAlphaBlendFactor));
break;
}
} else {
const VkPipelineColorBlendAttachmentState &attachment = pipeline->ColorBlendState()->pAttachments[i];
if (IsSecondaryColorInputBlendFactor(attachment.srcColorBlendFactor) ||
IsSecondaryColorInputBlendFactor(attachment.dstColorBlendFactor) ||
IsSecondaryColorInputBlendFactor(attachment.srcAlphaBlendFactor) ||
IsSecondaryColorInputBlendFactor(attachment.dstAlphaBlendFactor)) {
const LogObjectList objlist = cb_state.GetObjectList(VK_PIPELINE_BIND_POINT_GRAPHICS);
skip |= LogError(
vuid.blend_dual_source_09239, objlist, vuid.loc(),
"Fragment output attachment %" PRIu32
" is using Dual-Source Blending, but the largest output fragment Location (%" PRIu32
") is not less than maxFragmentDualSrcAttachments (%" PRIu32
"). The following are set by VkPipelineColorBlendAttachmentState:\n\tsrcColorBlendFactor = "
"%s\n\tdstColorBlendFactor = %s\n\tsrcAlphaBlendFactor = %s\n\tdstAlphaBlendFactor "
"= %s\n",
i, max_fragment_location, phys_dev_props.limits.maxFragmentDualSrcAttachments,
string_VkBlendFactor(attachment.srcColorBlendFactor), string_VkBlendFactor(attachment.dstColorBlendFactor),
string_VkBlendFactor(attachment.srcAlphaBlendFactor), string_VkBlendFactor(attachment.dstAlphaBlendFactor));
break;
}
}
}

return skip;
}
1 change: 1 addition & 0 deletions layers/core_checks/core_validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class CoreChecks : public ValidationStateTracker {
bool ValidateTraceRaysDynamicStateSetStatus(const LastBound& last_bound_state, const vvl::DrawDispatchVuid& vuid) const;
bool ValidateDrawPrimitivesGeneratedQuery(const LastBound& last_bound_state, const vvl::DrawDispatchVuid& vuid) const;
bool ValidateDrawProtectedMemory(const LastBound& last_bound_state, const vvl::DrawDispatchVuid& vuid) const;
bool ValidateDrawDualSourceBlend(const LastBound& last_bound_state, const vvl::DrawDispatchVuid& vuid) const;
bool ValidateStageMaskHost(const LogObjectList& objlist, const Location& stage_mask_loc,
VkPipelineStageFlags2KHR stageMask) const;
bool ValidateMapMemory(const vvl::DeviceMemory& mem_info, VkDeviceSize offset, VkDeviceSize size, const Location& offset_loc,
Expand Down
15 changes: 15 additions & 0 deletions layers/drawdispatch/drawdispatch_vuids.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ struct DispatchVuidsCmdDraw : DrawDispatchVuid {
vertex_input_04914 = "VUID-vkCmdDraw-None-04914";
vertex_input_08734 = "VUID-vkCmdDraw-Input-08734";
blend_enable_04727 = "VUID-vkCmdDraw-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDraw-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDraw-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDraw-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDraw-None-07881";
Expand Down Expand Up @@ -389,6 +390,7 @@ struct DispatchVuidsCmdDrawMultiEXT : DrawDispatchVuid {
vertex_input_04914 = "VUID-vkCmdDrawMultiEXT-None-04914";
vertex_input_08734 = "VUID-vkCmdDrawMultiEXT-Input-08734";
blend_enable_04727 = "VUID-vkCmdDrawMultiEXT-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawMultiEXT-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawMultiEXT-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawMultiEXT-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawMultiEXT-None-07881";
Expand Down Expand Up @@ -706,6 +708,7 @@ struct DispatchVuidsCmdDrawIndexed : DrawDispatchVuid {
vertex_input_04914 = "VUID-vkCmdDrawIndexed-None-04914";
vertex_input_08734 = "VUID-vkCmdDrawIndexed-Input-08734";
blend_enable_04727 = "VUID-vkCmdDrawIndexed-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawIndexed-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawIndexed-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawIndexed-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawIndexed-None-07881";
Expand Down Expand Up @@ -1023,6 +1026,7 @@ struct DispatchVuidsCmdDrawMultiIndexedEXT : DrawDispatchVuid {
vertex_input_04914 = "VUID-vkCmdDrawMultiIndexedEXT-None-04914";
vertex_input_08734 = "VUID-vkCmdDrawMultiIndexedEXT-Input-08734";
blend_enable_04727 = "VUID-vkCmdDrawMultiIndexedEXT-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawMultiIndexedEXT-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawMultiIndexedEXT-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawMultiIndexedEXT-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawMultiIndexedEXT-None-07881";
Expand Down Expand Up @@ -1340,6 +1344,7 @@ struct DispatchVuidsCmdDrawIndirect : DrawDispatchVuid {
vertex_input_04914 = "VUID-vkCmdDrawIndirect-None-04914";
vertex_input_08734 = "VUID-vkCmdDrawIndirect-Input-08734";
blend_enable_04727 = "VUID-vkCmdDrawIndirect-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawIndirect-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawIndirect-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawIndirect-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawIndirect-None-07881";
Expand Down Expand Up @@ -1656,6 +1661,7 @@ struct DispatchVuidsCmdDrawIndexedIndirect : DrawDispatchVuid {
vertex_input_04914 = "VUID-vkCmdDrawIndexedIndirect-None-04914";
vertex_input_08734 = "VUID-vkCmdDrawIndexedIndirect-Input-08734";
blend_enable_04727 = "VUID-vkCmdDrawIndexedIndirect-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawIndexedIndirect-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawIndexedIndirect-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawIndexedIndirect-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawIndexedIndirect-None-07881";
Expand Down Expand Up @@ -2071,6 +2077,7 @@ struct DispatchVuidsCmdDrawIndirectCount : DrawDispatchVuid {
vertex_input_04914 = "VUID-vkCmdDrawIndirectCount-None-04914";
vertex_input_08734 = "VUID-vkCmdDrawIndirectCount-Input-08734";
blend_enable_04727 = "VUID-vkCmdDrawIndirectCount-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawIndirectCount-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawIndirectCount-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawIndirectCount-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawIndirectCount-None-07881";
Expand Down Expand Up @@ -2390,6 +2397,7 @@ struct DispatchVuidsCmdDrawIndexedIndirectCount : DrawDispatchVuid {
vertex_input_04914 = "VUID-vkCmdDrawIndexedIndirectCount-None-04914";
vertex_input_08734 = "VUID-vkCmdDrawIndexedIndirectCount-Input-08734";
blend_enable_04727 = "VUID-vkCmdDrawIndexedIndirectCount-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawIndexedIndirectCount-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawIndexedIndirectCount-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawIndexedIndirectCount-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawIndexedIndirectCount-None-07881";
Expand Down Expand Up @@ -2888,6 +2896,7 @@ struct DispatchVuidsCmdDrawMeshTasksNV: DrawDispatchVuid {
depth_bias_enable_04877 = "VUID-vkCmdDrawMeshTasksNV-None-04877";
logic_op_04878 = "VUID-vkCmdDrawMeshTasksNV-logicOp-04878";
blend_enable_04727 = "VUID-vkCmdDrawMeshTasksNV-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawMeshTasksNV-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawMeshTasksNV-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawMeshTasksNV-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawMeshTasksNV-None-07881";
Expand Down Expand Up @@ -3190,6 +3199,7 @@ struct DispatchVuidsCmdDrawMeshTasksIndirectNV: DrawDispatchVuid {
depth_bias_enable_04877 = "VUID-vkCmdDrawMeshTasksIndirectNV-None-04877";
logic_op_04878 = "VUID-vkCmdDrawMeshTasksIndirectNV-logicOp-04878";
blend_enable_04727 = "VUID-vkCmdDrawMeshTasksIndirectNV-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawMeshTasksIndirectNV-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawMeshTasksIndirectNV-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawMeshTasksIndirectNV-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawMeshTasksIndirectNV-None-07881";
Expand Down Expand Up @@ -3495,6 +3505,7 @@ struct DispatchVuidsCmdDrawMeshTasksIndirectCountNV : DrawDispatchVuid {
depth_bias_enable_04877 = "VUID-vkCmdDrawMeshTasksIndirectCountNV-None-04877";
logic_op_04878 = "VUID-vkCmdDrawMeshTasksIndirectCountNV-logicOp-04878";
blend_enable_04727 = "VUID-vkCmdDrawMeshTasksIndirectCountNV-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawMeshTasksIndirectCountNV-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawMeshTasksIndirectCountNV-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawMeshTasksIndirectCountNV-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawMeshTasksIndirectCountNV-None-07881";
Expand Down Expand Up @@ -3794,6 +3805,7 @@ struct DispatchVuidsCmdDrawMeshTasksEXT: DrawDispatchVuid {
depth_bias_enable_04877 = "VUID-vkCmdDrawMeshTasksEXT-None-04877";
logic_op_04878 = "VUID-vkCmdDrawMeshTasksEXT-logicOp-04878";
blend_enable_04727 = "VUID-vkCmdDrawMeshTasksEXT-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawMeshTasksEXT-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawMeshTasksEXT-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawMeshTasksEXT-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawMeshTasksEXT-None-07881";
Expand Down Expand Up @@ -4096,6 +4108,7 @@ struct DispatchVuidsCmdDrawMeshTasksIndirectEXT: DrawDispatchVuid {
depth_bias_enable_04877 = "VUID-vkCmdDrawMeshTasksIndirectEXT-None-04877";
logic_op_04878 = "VUID-vkCmdDrawMeshTasksIndirectEXT-logicOp-04878";
blend_enable_04727 = "VUID-vkCmdDrawMeshTasksIndirectEXT-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawMeshTasksIndirectEXT-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawMeshTasksIndirectEXT-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawMeshTasksIndirectEXT-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawMeshTasksIndirectEXT-None-07881";
Expand Down Expand Up @@ -4401,6 +4414,7 @@ struct DispatchVuidsCmdDrawMeshTasksIndirectCountEXT : DrawDispatchVuid {
depth_bias_enable_04877 = "VUID-vkCmdDrawMeshTasksIndirectCountEXT-None-04877";
logic_op_04878 = "VUID-vkCmdDrawMeshTasksIndirectCountEXT-logicOp-04878";
blend_enable_04727 = "VUID-vkCmdDrawMeshTasksIndirectCountEXT-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawMeshTasksIndirectCountEXT-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawMeshTasksIndirectCountEXT-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawMeshTasksIndirectCountEXT-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawMeshTasksIndirectCountEXT-None-07881";
Expand Down Expand Up @@ -4713,6 +4727,7 @@ struct DispatchVuidsCmdDrawIndirectByteCountEXT: DrawDispatchVuid {
vertex_input_04914 = "VUID-vkCmdDrawIndirectByteCountEXT-None-04914";
vertex_input_08734 = "VUID-vkCmdDrawIndirectByteCountEXT-Input-08734";
blend_enable_04727 = "VUID-vkCmdDrawIndirectByteCountEXT-blendEnable-04727";
blend_dual_source_09239 = "VUID-vkCmdDrawIndirectByteCountEXT-maxFragmentDualSrcAttachments-09239";
dynamic_discard_rectangle_07751 = "VUID-vkCmdDrawIndirectByteCountEXT-None-07751";
dynamic_discard_rectangle_enable_07880 = "VUID-vkCmdDrawIndirectByteCountEXT-None-07880";
dynamic_discard_rectangle_mode_07881 = "VUID-vkCmdDrawIndirectByteCountEXT-None-07881";
Expand Down
1 change: 1 addition & 0 deletions layers/drawdispatch/drawdispatch_vuids.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ struct DrawDispatchVuid {
const char* vertex_input_04914 = kVUIDUndefined;
const char* vertex_input_08734 = kVUIDUndefined;
const char* blend_enable_04727 = kVUIDUndefined;
const char* blend_dual_source_09239 = kVUIDUndefined;
const char* dynamic_discard_rectangle_07751 = kVUIDUndefined;
const char* dynamic_discard_rectangle_enable_07880 = kVUIDUndefined;
const char* dynamic_discard_rectangle_mode_07881 = kVUIDUndefined;
Expand Down
Loading

0 comments on commit 17f812b

Please sign in to comment.