Skip to content

Commit

Permalink
layers: Fix VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT
Browse files Browse the repository at this point in the history
  • Loading branch information
spencer-lunarg committed Sep 25, 2024
1 parent dd3fcd9 commit b3bd2ba
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 16 deletions.
30 changes: 17 additions & 13 deletions layers/core_checks/cc_cmd_buffer_dynamic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ bool CoreChecks::ValidateDynamicStateIsSet(const LastBound& last_bound_state, co
case CB_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV:
vuid_str = vuid.set_clip_space_w_scaling_04138;
break;
case CB_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT:
vuid_str = vuid.patch_control_points_04875;
break;
default:
assert(false);
break;
Expand All @@ -212,8 +215,8 @@ bool CoreChecks::ValidateGraphicsDynamicStateSetStatus(const LastBound& last_bou
const bool vertex_shader_bound = has_pipeline || last_bound_state.IsValidShaderBound(ShaderObjectStage::VERTEX);
const bool fragment_shader_bound = has_pipeline || last_bound_state.IsValidShaderBound(ShaderObjectStage::FRAGMENT);
const bool geom_shader_bound = has_pipeline || last_bound_state.IsValidShaderBound(ShaderObjectStage::GEOMETRY);
const bool tessev_shader_bound =
has_pipeline || last_bound_state.IsValidShaderBound(ShaderObjectStage::TESSELLATION_EVALUATION);
const bool tesc_shader_bound = has_pipeline || last_bound_state.IsValidShaderBound(ShaderObjectStage::TESSELLATION_CONTROL);
const bool tese_shader_bound = has_pipeline || last_bound_state.IsValidShaderBound(ShaderObjectStage::TESSELLATION_EVALUATION);

// build the mask of what has been set in the Pipeline, but yet to be set in the Command Buffer,
// for Shader Object, everything is dynamic don't need a mask
Expand Down Expand Up @@ -377,10 +380,21 @@ bool CoreChecks::ValidateGraphicsDynamicStateSetStatus(const LastBound& last_bou
skip |= ValidateDynamicStateIsSet(last_bound_state, state_status_cb, CB_DYNAMIC_STATE_VERTEX_INPUT_EXT, vuid);
}

if (tessev_shader_bound) {
if (tese_shader_bound) {
skip |= ValidateDynamicStateIsSet(last_bound_state, state_status_cb, CB_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT, vuid);
}

if (tesc_shader_bound) {
// Don't call GetPrimitiveTopology() because want to view the Topology from the dynamic state for ShaderObjects
const VkPrimitiveTopology topology =
(!last_bound_state.pipeline_state || last_bound_state.pipeline_state->IsDynamic(CB_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY))
? cb_state.dynamic_state_value.primitive_topology
: last_bound_state.pipeline_state->topology_at_rasterizer;
if (topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) {
skip |= ValidateDynamicStateIsSet(last_bound_state, state_status_cb, CB_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT, vuid);
}
}

if (geom_shader_bound) {
if (enabled_features.geometryStreams) {
skip |= ValidateDynamicStateIsSet(last_bound_state, state_status_cb, CB_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT, vuid);
Expand Down Expand Up @@ -454,12 +468,6 @@ bool CoreChecks::ValidateGraphicsDynamicStatePipelineSetStatus(const LastBound&
// build the mask of what has been set in the Pipeline, but yet to be set in the Command Buffer
const CBDynamicFlags state_status_cb = ~((cb_state.dynamic_state_status.cb ^ pipeline.dynamic_state) & pipeline.dynamic_state);

// VK_EXT_extended_dynamic_state2
{
skip |= ValidateDynamicStateIsSet(state_status_cb, CB_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT, cb_state, objlist, loc,
vuid.patch_control_points_04875);
}

// VK_EXT_extended_dynamic_state3
{
skip |= ValidateDynamicStateIsSet(state_status_cb, CB_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT, cb_state, objlist, loc,
Expand Down Expand Up @@ -1492,10 +1500,6 @@ bool CoreChecks::ValidateDrawDynamicStateShaderObject(const LastBound& last_boun
vuid.set_line_width_08617);
}

if (tessev_shader_bound) {
skip |= ValidateDynamicStateIsSet(cb_state.dynamic_state_status.cb, CB_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT, cb_state,
objlist, loc, vuid.patch_control_points_04875);
}
if ((tessev_shader_bound && tess_shader_line_topology) || (geom_shader_bound && geom_shader_line_topology)) {
skip |= ValidateDynamicStateIsSet(cb_state.dynamic_state_status.cb, CB_DYNAMIC_STATE_LINE_WIDTH, cb_state, objlist, loc,
vuid.set_line_width_08619);
Expand Down
4 changes: 1 addition & 3 deletions layers/state_tracker/pipeline_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1009,9 +1009,7 @@ bool LastBound::IsColorWriteEnabled(uint32_t i) const {
}

VkPrimitiveTopology LastBound::GetPrimitiveTopology() const {
if (!pipeline_state) {
return GetShaderState(ShaderObjectStage::VERTEX)->GetTopology();
} else if (pipeline_state->IsDynamic(CB_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY)) {
if (!pipeline_state || pipeline_state->IsDynamic(CB_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY)) {
return cb_state.dynamic_state_value.primitive_topology;
} else {
return pipeline_state->topology_at_rasterizer;
Expand Down
1 change: 1 addition & 0 deletions tests/unit/shader_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3348,6 +3348,7 @@ TEST_F(NegativeShaderObject, MissingCmdSetPatchControlPointsEXT) {
const VkShaderEXT shaders[] = {vertShader.handle(), tescShader.handle(), teseShader.handle(), VK_NULL_HANDLE,
fragShader.handle()};
vk::CmdBindShadersEXT(m_commandBuffer->handle(), 5u, stages, shaders);
vk::CmdSetPrimitiveTopologyEXT(m_commandBuffer->handle(), VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
vk::CmdDraw(m_commandBuffer->handle(), 4, 1, 0, 0);
m_commandBuffer->EndRendering();
m_commandBuffer->end();
Expand Down
34 changes: 34 additions & 0 deletions tests/unit/shader_object_positive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1632,3 +1632,37 @@ TEST_F(PositiveShaderObject, DrawWithVertGeomFragShaderObjects) {
m_commandBuffer->EndRendering();
m_commandBuffer->end();
}

TEST_F(PositiveShaderObject, MissingCmdSetPatchControlPointsEXT) {
RETURN_IF_SKIP(InitBasicShaderObject());
VkPhysicalDeviceFeatures features;
GetPhysicalDeviceFeatures(&features);
if (features.tessellationShader == VK_FALSE) {
GTEST_SKIP() << "tessellationShader not supported.";
}
InitDynamicRenderTarget();

const vkt::Shader vertShader(*m_device, VK_SHADER_STAGE_VERTEX_BIT, GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl));
const vkt::Shader tescShader(*m_device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
GLSLToSPV(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, kTessellationControlMinimalGlsl));
const vkt::Shader teseShader(*m_device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
GLSLToSPV(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, kTessellationEvalMinimalGlsl));
const vkt::Shader fragShader(*m_device, VK_SHADER_STAGE_FRAGMENT_BIT,
GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kFragmentMinimalGlsl));
m_commandBuffer->begin();
m_commandBuffer->BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea());
SetDefaultDynamicStatesExclude({VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT});
const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, VK_SHADER_STAGE_GEOMETRY_BIT,
VK_SHADER_STAGE_FRAGMENT_BIT};
const VkShaderEXT shaders[] = {vertShader.handle(), tescShader.handle(), teseShader.handle(), VK_NULL_HANDLE,
fragShader.handle()};
vk::CmdBindShadersEXT(m_commandBuffer->handle(), 5u, stages, shaders);
// valid because this is not VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
vk::CmdSetPrimitiveTopologyEXT(m_commandBuffer->handle(), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
vk::CmdDraw(m_commandBuffer->handle(), 4, 1, 0, 0);
m_commandBuffer->EndRendering();
m_commandBuffer->end();

m_errorMonitor->VerifyFound();
}

0 comments on commit b3bd2ba

Please sign in to comment.