Skip to content

Commit b414337

Browse files
layers: Fix Tessellation with Shader Object
1 parent 73d23ad commit b414337

File tree

8 files changed

+317
-370
lines changed

8 files changed

+317
-370
lines changed

layers/core_checks/cc_drawdispatch.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "drawdispatch/drawdispatch_vuids.h"
2323
#include "core_validation.h"
2424
#include "error_message/error_strings.h"
25+
#include "error_message/logging.h"
26+
#include "generated/spirv_grammar_helper.h"
2527
#include "generated/vk_extension_helper.h"
2628
#include "state_tracker/buffer_state.h"
2729
#include "state_tracker/image_state.h"
@@ -1376,6 +1378,7 @@ bool CoreChecks::ValidateActionState(const LastBound &last_bound_state, const Dr
13761378
skip |= ValidateDrawAttachmentColorBlend(last_bound_state, vuid);
13771379
skip |= ValidateDrawAttachmentSampleLocation(last_bound_state, vuid);
13781380
skip |= ValidateDrawDepthStencilAttachments(last_bound_state, vuid);
1381+
skip |= ValidateDrawTessellation(last_bound_state, vuid);
13791382

13801383
if (cb_state.active_render_pass && cb_state.active_render_pass->UsesDynamicRendering()) {
13811384
skip |= ValidateDrawDynamicRenderingFsOutputs(last_bound_state, cb_state, loc);
@@ -2136,6 +2139,86 @@ bool CoreChecks::ValidateDrawDepthStencilAttachments(const LastBound &last_bound
21362139
return skip;
21372140
}
21382141

2142+
bool CoreChecks::ValidateDrawTessellation(const LastBound &last_bound_state, const vvl::DrawDispatchVuid &vuid) const {
2143+
bool skip = false;
2144+
// Already validation to ensure there is both a Control and Eval
2145+
if ((last_bound_state.GetAllActiveBoundStages() & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) == 0) {
2146+
return skip;
2147+
}
2148+
2149+
const spirv::ExecutionModeSet *tesc_execution_mode = nullptr;
2150+
const spirv::ExecutionModeSet *tese_execution_mode = nullptr;
2151+
2152+
if (last_bound_state.pipeline_state) {
2153+
for (auto &stage_state : last_bound_state.pipeline_state->stage_states) {
2154+
const VkShaderStageFlagBits stage = stage_state.GetStage();
2155+
if (stage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
2156+
if (stage_state.entrypoint) {
2157+
tesc_execution_mode = &stage_state.entrypoint->execution_mode;
2158+
}
2159+
} else if (stage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
2160+
if (stage_state.entrypoint) {
2161+
tese_execution_mode = &stage_state.entrypoint->execution_mode;
2162+
}
2163+
}
2164+
}
2165+
} else {
2166+
const auto tesc_shader = last_bound_state.GetShaderState(ShaderObjectStage::TESSELLATION_CONTROL);
2167+
if (tesc_shader && tesc_shader->entrypoint) {
2168+
tesc_execution_mode = &tesc_shader->entrypoint->execution_mode;
2169+
}
2170+
const auto tese_shader = last_bound_state.GetShaderState(ShaderObjectStage::TESSELLATION_EVALUATION);
2171+
if (tese_shader && tese_shader->entrypoint) {
2172+
tese_execution_mode = &tese_shader->entrypoint->execution_mode;
2173+
}
2174+
}
2175+
2176+
ASSERT_AND_RETURN_SKIP(tesc_execution_mode && tese_execution_mode);
2177+
2178+
// VUID being added in https://gitlab.khronos.org/vulkan/vulkan/-/merge_requests/7694
2179+
const uint32_t tesc_subdivision = tesc_execution_mode->GetTessellationSubdivision();
2180+
const uint32_t tese_subdivision = tese_execution_mode->GetTessellationSubdivision();
2181+
if (tesc_subdivision != 0 && tese_subdivision != 0 && tesc_subdivision != tese_subdivision) {
2182+
skip |= LogError("UNASSIGNED-vkCmdDraw-tessellation-subdivision",
2183+
last_bound_state.cb_state.GetObjectList(VK_PIPELINE_BIND_POINT_GRAPHICS), vuid.loc(),
2184+
"The subdivision specified in tessellation control shader (%s) does not match the subdivision in "
2185+
"tessellation evaluation shader (%s).",
2186+
string_SpvExecutionMode(tesc_subdivision), string_SpvExecutionMode(tese_subdivision));
2187+
}
2188+
2189+
const uint32_t tesc_orientation = tesc_execution_mode->GetTessellationOrientation();
2190+
const uint32_t tese_orientation = tese_execution_mode->GetTessellationOrientation();
2191+
if (tesc_orientation != 0 && tese_orientation != 0 && tesc_orientation != tese_orientation) {
2192+
skip |= LogError("UNASSIGNED-vkCmdDraw-tessellation-orientation",
2193+
last_bound_state.cb_state.GetObjectList(VK_PIPELINE_BIND_POINT_GRAPHICS), vuid.loc(),
2194+
"The orientation specified in tessellation control shader (%s) does not match the orientation in "
2195+
"tessellation evaluation shader (%s).",
2196+
string_SpvExecutionMode(tesc_orientation), string_SpvExecutionMode(tese_orientation));
2197+
}
2198+
2199+
const uint32_t tesc_spacing = tesc_execution_mode->GetTessellationSpacing();
2200+
const uint32_t tese_spacing = tese_execution_mode->GetTessellationSpacing();
2201+
if (tesc_spacing != 0 && tese_spacing != 0 && tesc_spacing != tese_spacing) {
2202+
skip |= LogError("UNASSIGNED-vkCmdDraw-tessellation-spacing",
2203+
last_bound_state.cb_state.GetObjectList(VK_PIPELINE_BIND_POINT_GRAPHICS), vuid.loc(),
2204+
"The spacing specified in tessellation control shader (%s) does not match the spacing in "
2205+
"tessellation evaluation shader (%s).",
2206+
string_SpvExecutionMode(tesc_spacing), string_SpvExecutionMode(tese_spacing));
2207+
}
2208+
const uint32_t tesc_patch_size = tesc_execution_mode->output_vertices;
2209+
const uint32_t tese_patch_size = tese_execution_mode->output_vertices;
2210+
if (tesc_patch_size != spirv::kInvalidValue && tese_patch_size != spirv::kInvalidValue && tesc_patch_size != tese_patch_size) {
2211+
skip |= LogError("UNASSIGNED-vkCmdDraw-tessellation-patch-size",
2212+
last_bound_state.cb_state.GetObjectList(VK_PIPELINE_BIND_POINT_GRAPHICS), vuid.loc(),
2213+
"The OutputVertices (patch size) specified in tessellation control shader (%" PRIu32
2214+
") does not match the spacing in "
2215+
"tessellation evaluation shader (%" PRIu32 ").",
2216+
tesc_patch_size, tese_patch_size);
2217+
}
2218+
2219+
return skip;
2220+
}
2221+
21392222
bool CoreChecks::ValidateDrawDynamicRenderpassExternalFormatResolve(const LastBound &last_bound_state,
21402223
const vvl::RenderPass &rp_state,
21412224
const vvl::DrawDispatchVuid &vuid) const {

layers/core_checks/cc_shader_interface.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -699,29 +699,32 @@ bool CoreChecks::ValidatePipelineTessellationStages(const spirv::Module &tesc_mo
699699
const Location &create_info_loc) const {
700700
bool skip = false;
701701

702+
// The other tessellation modes (PointMode, Spacing, Orientation) can be in either stage.
703+
// OutputVertices needs to be in TESC and Subdivision in TESE, but they can be in the other stage, but needs to match
702704
const uint32_t tesc_subdivision = tesc_entrypoint.execution_mode.GetTessellationSubdivision();
703705
const uint32_t tese_subdivision = tese_entrypoint.execution_mode.GetTessellationSubdivision();
704706
const uint32_t tesc_patch_size = tesc_entrypoint.execution_mode.output_vertices;
705707
const uint32_t tese_patch_size = tese_entrypoint.execution_mode.output_vertices;
706708
if (tesc_subdivision == 0 && tese_subdivision == 0) {
707709
const LogObjectList objlist(tesc_module_state.handle(), tese_module_state.handle());
708710
skip |= LogError("VUID-VkGraphicsPipelineCreateInfo-pStages-00732", objlist, create_info_loc,
709-
"Subdivision type is not specified in either of tessellation stages");
711+
"Subdivision (Triangles/Quads/IsoLines) is not specified in either of tessellation stages");
710712
} else if (tesc_subdivision != 0 && tese_subdivision != 0 && tesc_subdivision != tese_subdivision) {
711713
const LogObjectList objlist(tesc_module_state.handle(), tese_module_state.handle());
712714
skip |= LogError("VUID-VkGraphicsPipelineCreateInfo-pStages-00733", objlist, create_info_loc,
713-
"Subdivision type specified in tessellation control shader is %s, but subdivison type specified in "
715+
"Subdivision specified in tessellation control shader is %s, but subdivison type specified in "
714716
"tessellation evaluation shader is %s",
715717
string_SpvExecutionMode(tesc_subdivision), string_SpvExecutionMode(tese_subdivision));
716718
}
717-
if (tesc_patch_size == vvl::kU32Max && tese_patch_size == vvl::kU32Max) {
719+
if (tesc_patch_size == spirv::kInvalidValue && tese_patch_size == spirv::kInvalidValue) {
718720
const LogObjectList objlist(tesc_module_state.handle(), tese_module_state.handle());
719721
skip |= LogError("VUID-VkGraphicsPipelineCreateInfo-pStages-00734", objlist, create_info_loc,
720-
"Output patch size is not specified in either of tessellation stages");
721-
} else if (tesc_patch_size != vvl::kU32Max && tese_patch_size != vvl::kU32Max && tesc_patch_size != tese_patch_size) {
722+
"OutputVertices (patch size) is not specified in either of tessellation stages");
723+
} else if (tesc_patch_size != spirv::kInvalidValue && tese_patch_size != spirv::kInvalidValue &&
724+
tesc_patch_size != tese_patch_size) {
722725
const LogObjectList objlist(tesc_module_state.handle(), tese_module_state.handle());
723726
skip |= LogError("VUID-VkGraphicsPipelineCreateInfo-pStages-00735", objlist, create_info_loc,
724-
"Output patch size specified in tessellation control shader is %" PRIu32
727+
"OutputVertices (patch size) specified in tessellation control shader is %" PRIu32
725728
", but subdivison type specified in tessellation evaluation shader is %" PRIu32,
726729
tesc_patch_size, tese_patch_size);
727730
}

0 commit comments

Comments
 (0)