blob: c276cd98f938a630f259da4a314454b1210357d5 [file]
/*
* Copyright (c) 2015-2026 The Khronos Group Inc.
* Copyright (c) 2015-2026 Valve Corporation
* Copyright (c) 2015-2026 LunarG, Inc.
* Copyright (c) 2015-2026 Google, Inc.
* Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include "../framework/layer_validation_tests.h"
#include "../framework/pipeline_helper.h"
class NegativePipelineTopology : public VkLayerTest {};
TEST_F(NegativePipelineTopology, PolygonMode) {
TEST_DESCRIPTION("Attempt to use invalid polygon fill modes.");
// The sacrificial device object
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPipelineRasterizationStateCreateInfo rs_ci = vku::InitStructHelper();
rs_ci.lineWidth = 1.0f;
rs_ci.rasterizerDiscardEnable = VK_TRUE;
auto set_polygonMode = [&](CreatePipelineHelper& helper) { helper.rs_state_ci_ = rs_ci; };
// Set polygonMode to POINT while the non-solid fill mode feature is disabled.
// Introduce failure by setting unsupported polygon mode
rs_ci.polygonMode = VK_POLYGON_MODE_POINT;
CreatePipelineHelper::OneshotTest(*this, set_polygonMode, kErrorBit,
"VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01507");
// Set polygonMode to LINE while the non-solid fill mode feature is disabled.
// Introduce failure by setting unsupported polygon mode
rs_ci.polygonMode = VK_POLYGON_MODE_LINE;
CreatePipelineHelper::OneshotTest(*this, set_polygonMode, kErrorBit,
"VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01507");
// Set polygonMode to FILL_RECTANGLE_NV while the extension is not enabled.
// Introduce failure by setting unsupported polygon mode
rs_ci.polygonMode = VK_POLYGON_MODE_FILL_RECTANGLE_NV;
m_errorMonitor->SetDesiredError("VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-parameter");
CreatePipelineHelper::OneshotTest(*this, set_polygonMode, kErrorBit,
"VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01414");
}
// Create VS declaring PointSize but not writing to it
static const char* NoPointSizeVertShader = R"glsl(
#version 450
vec2 vertices[3];
out gl_PerVertex
{
vec4 gl_Position;
float gl_PointSize;
};
void main() {
vertices[0] = vec2(-1.0, -1.0);
vertices[1] = vec2( 1.0, -1.0);
vertices[2] = vec2( 0.0, 1.0);
gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);
}
)glsl";
TEST_F(NegativePipelineTopology, PointSize) {
TEST_DESCRIPTION("Create a pipeline using TOPOLOGY_POINT_LIST but do not set PointSize in vertex shader.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkShaderObj vs(*m_device, NoPointSizeVertShader, VK_SHADER_STAGE_VERTEX_BIT);
auto set_info = [&](CreatePipelineHelper& helper) {
helper.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
};
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-topology-08773");
}
TEST_F(NegativePipelineTopology, PointSizeNonDynamicAndRestricted) {
TEST_DESCRIPTION(
"Create a pipeline using TOPOLOGY_POINT_LIST but do not set PointSize in vertex shader, with no dynamic state and "
"dynamicPrimitiveTopologyUnrestricted is false.");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceExtendedDynamicState3PropertiesEXT dynamic_state_3_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(dynamic_state_3_props);
if (dynamic_state_3_props.dynamicPrimitiveTopologyUnrestricted) {
GTEST_SKIP() << "dynamicPrimitiveTopologyUnrestricted is VK_TRUE";
}
VkShaderObj vs(*m_device, NoPointSizeVertShader, VK_SHADER_STAGE_VERTEX_BIT);
auto set_info = [&](CreatePipelineHelper& helper) {
helper.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
};
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-topology-08773");
}
TEST_F(NegativePipelineTopology, PointSizeNonDynamicAndUnrestricted) {
TEST_DESCRIPTION(
"Create a pipeline using TOPOLOGY_POINT_LIST but do not set PointSize in vertex shader, with "
"dynamicPrimitiveTopologyUnrestricted is true, but not dynamic state.");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceExtendedDynamicState3PropertiesEXT dynamic_state_3_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(dynamic_state_3_props);
if (!dynamic_state_3_props.dynamicPrimitiveTopologyUnrestricted) {
GTEST_SKIP() << "dynamicPrimitiveTopologyUnrestricted is VK_FALSE";
}
VkShaderObj vs(*m_device, NoPointSizeVertShader, VK_SHADER_STAGE_VERTEX_BIT);
auto set_info = [&](CreatePipelineHelper& helper) {
helper.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
};
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-topology-08773");
}
TEST_F(NegativePipelineTopology, PointSizeDynamicAndRestricted) {
TEST_DESCRIPTION(
"Create a pipeline using TOPOLOGY_POINT_LIST but do not set PointSize in vertex shader, with dynamic state but "
"dynamicPrimitiveTopologyUnrestricted is false.");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceExtendedDynamicState3PropertiesEXT dynamic_state_3_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(dynamic_state_3_props);
if (dynamic_state_3_props.dynamicPrimitiveTopologyUnrestricted) {
GTEST_SKIP() << "dynamicPrimitiveTopologyUnrestricted is VK_TRUE";
}
VkShaderObj vs(*m_device, NoPointSizeVertShader, VK_SHADER_STAGE_VERTEX_BIT);
const VkDynamicState dyn_state = VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY;
VkPipelineDynamicStateCreateInfo dyn_state_ci = vku::InitStructHelper();
dyn_state_ci.dynamicStateCount = 1;
dyn_state_ci.pDynamicStates = &dyn_state;
auto set_info = [&](CreatePipelineHelper& helper) {
helper.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
helper.dyn_state_ci_ = dyn_state_ci;
helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
};
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-topology-08773");
}
TEST_F(NegativePipelineTopology, PrimitiveTopology) {
TEST_DESCRIPTION("InvalidTopology.");
VkPhysicalDeviceFeatures deviceFeatures = {};
deviceFeatures.geometryShader = VK_FALSE;
deviceFeatures.tessellationShader = VK_FALSE;
RETURN_IF_SKIP(Init(&deviceFeatures));
InitRenderTarget();
VkShaderObj vs(*m_device, kVertexPointSizeGlsl, VK_SHADER_STAGE_VERTEX_BIT);
VkPrimitiveTopology topology;
auto set_info = [&](CreatePipelineHelper& helper) {
helper.ia_ci_.topology = topology;
helper.ia_ci_.primitiveRestartEnable = VK_TRUE;
helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
};
topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252");
topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252");
topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252");
{
topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
constexpr std::array vuids = {"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252",
"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429"};
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, vuids);
}
{
topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
constexpr std::array vuids = {"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252",
"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429"};
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, vuids);
}
{
topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
constexpr std::array vuids = {"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06253",
"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430",
"VUID-VkGraphicsPipelineCreateInfo-topology-08889"};
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, vuids);
}
topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429");
topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429");
}
TEST_F(NegativePipelineTopology, PrimitiveTopologyListRestart) {
TEST_DESCRIPTION("Test VK_EXT_primitive_topology_list_restart");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tessellationShader);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkShaderObj vs(*m_device, kVertexPointSizeGlsl, VK_SHADER_STAGE_VERTEX_BIT);
VkPrimitiveTopology topology;
auto set_info = [&](CreatePipelineHelper& helper) {
helper.ia_ci_.topology = topology;
helper.ia_ci_.primitiveRestartEnable = VK_TRUE;
helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
};
topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06252");
if (m_device->Physical().Features().tessellationShader) {
topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
constexpr std::array vuids = {"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-06253",
"VUID-VkGraphicsPipelineCreateInfo-topology-08889"};
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, vuids);
}
}
TEST_F(NegativePipelineTopology, PatchListNoTessellation) {
TEST_DESCRIPTION("Use VK_PRIMITIVE_TOPOLOGY_PATCH_LIST without tessellation shader");
AddOptionalExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tessellationShader);
RETURN_IF_SKIP(Init());
InitRenderTarget();
auto set_info = [&](CreatePipelineHelper& helper) { helper.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; };
const char* vuid = IsExtensionsEnabled(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME)
? "VUID-VkGraphicsPipelineCreateInfo-topology-08889"
: "VUID-VkGraphicsPipelineCreateInfo-topology-08889";
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, vuid);
}
TEST_F(NegativePipelineTopology, FillRectangleNV) {
TEST_DESCRIPTION("Verify VK_NV_fill_rectangle");
AddRequiredExtensions(VK_NV_FILL_RECTANGLE_EXTENSION_NAME);
// Disable non-solid fill modes to make sure that the usage of VK_POLYGON_MODE_LINE and
// VK_POLYGON_MODE_POINT will cause an error when the VK_NV_fill_rectangle extension is enabled.
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPolygonMode polygon_mode = VK_POLYGON_MODE_LINE;
auto set_polygon_mode = [&polygon_mode](CreatePipelineHelper& helper) { helper.rs_state_ci_.polygonMode = polygon_mode; };
// Set unsupported polygon mode VK_POLYGON_MODE_LINE
CreatePipelineHelper::OneshotTest(*this, set_polygon_mode, kErrorBit,
"VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01507");
// Set unsupported polygon mode VK_POLYGON_MODE_POINT
polygon_mode = VK_POLYGON_MODE_POINT;
CreatePipelineHelper::OneshotTest(*this, set_polygon_mode, kErrorBit,
"VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01507");
// Set supported polygon mode VK_POLYGON_MODE_FILL
polygon_mode = VK_POLYGON_MODE_FILL;
CreatePipelineHelper::OneshotTest(*this, set_polygon_mode, kErrorBit);
// Set supported polygon mode VK_POLYGON_MODE_FILL_RECTANGLE_NV
polygon_mode = VK_POLYGON_MODE_FILL_RECTANGLE_NV;
CreatePipelineHelper::OneshotTest(*this, set_polygon_mode, kErrorBit);
}
TEST_F(NegativePipelineTopology, DynamicPrimitiveRestartEnable) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/4413");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
// Should work without looking at the SPIR-V
const VkLayerSettingEXT settings[] = {{OBJECT_LAYER_NAME, "check_shaders", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkFalse}};
VkLayerSettingsCreateInfoEXT create_info = {VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT, nullptr, 1, settings};
RETURN_IF_SKIP(InitFramework(&create_info));
RETURN_IF_SKIP(InitState());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
pipe.ia_ci_.primitiveRestartEnable = VK_FALSE;
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdSetPrimitiveRestartEnableEXT(m_command_buffer, VK_TRUE);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-09637");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdEndRenderPass(m_command_buffer);
m_command_buffer.End();
}
TEST_F(NegativePipelineTopology, DynamicPrimitiveRestartEnablePatchList) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/4413");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
AddRequiredFeature(vkt::Feature::tessellationShader);
// Should work without looking at the SPIR-V
const VkLayerSettingEXT settings[] = {{OBJECT_LAYER_NAME, "check_shaders", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkFalse}};
VkLayerSettingsCreateInfoEXT create_info = {VK_STRUCTURE_TYPE_LAYER_SETTINGS_CREATE_INFO_EXT, nullptr, 1, settings};
RETURN_IF_SKIP(InitFramework(&create_info));
RETURN_IF_SKIP(InitState());
InitRenderTarget();
VkShaderObj tcs(*m_device, kTessellationControlMinimalGlsl, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
VkShaderObj tes(*m_device, kTessellationEvalMinimalGlsl, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
VkPipelineTessellationStateCreateInfo tess_ci = vku::InitStructHelper();
tess_ci.patchControlPoints = 4u;
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
pipe.tess_ci_ = tess_ci;
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), tcs.GetStageCreateInfo(), tes.GetStageCreateInfo(),
pipe.fs_->GetStageCreateInfo()};
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdSetPrimitiveRestartEnableEXT(m_command_buffer, VK_TRUE);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-10909");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdEndRenderPass(m_command_buffer);
m_command_buffer.End();
}
TEST_F(NegativePipelineTopology, PointSizeDynamicAndUnrestricted) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceExtendedDynamicState3PropertiesEXT dynamic_state_3_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(dynamic_state_3_props);
if (!dynamic_state_3_props.dynamicPrimitiveTopologyUnrestricted) {
GTEST_SKIP() << "dynamicPrimitiveTopologyUnrestricted is VK_FALSE";
}
VkShaderObj vs(*m_device, kMinimalShaderGlsl, VK_SHADER_STAGE_VERTEX_BIT);
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetPrimitiveTopologyEXT(m_command_buffer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-primitiveTopology-10748");
vk::CmdDraw(m_command_buffer, 4, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativePipelineTopology, PatchListTopology) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddOptionalExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
AddRequiredFeature(vkt::Feature::tessellationShader);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceExtendedDynamicState3PropertiesEXT dynamic_state_3_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(dynamic_state_3_props);
if (!dynamic_state_3_props.dynamicPrimitiveTopologyUnrestricted) {
GTEST_SKIP() << "dynamicPrimitiveTopologyUnrestricted is VK_FALSE";
}
VkShaderObj tcs(*m_device, kTessellationControlMinimalGlsl, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
VkShaderObj tes(*m_device, kTessellationEvalMinimalGlsl, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
VkPipelineInputAssemblyStateCreateInfo iasci{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0,
VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE};
VkPipelineTessellationStateCreateInfo tsci{VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, nullptr, 0, 3};
CreatePipelineHelper pipe(*this);
pipe.gp_ci_.pTessellationState = &tsci;
pipe.gp_ci_.pInputAssemblyState = &iasci;
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo(), tcs.GetStageCreateInfo(),
tes.GetStageCreateInfo()};
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetPrimitiveTopologyEXT(m_command_buffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-primitiveTopology-10286");
vk::CmdDraw(m_command_buffer, 4, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativePipelineTopology, PatchListTopologyNoShader) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddOptionalExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
AddRequiredFeature(vkt::Feature::tessellationShader);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceExtendedDynamicState3PropertiesEXT dynamic_state_3_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(dynamic_state_3_props);
if (!dynamic_state_3_props.dynamicPrimitiveTopologyUnrestricted) {
GTEST_SKIP() << "dynamicPrimitiveTopologyUnrestricted is VK_FALSE";
}
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetPrimitiveTopologyEXT(m_command_buffer, VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-primitiveTopology-10747");
vk::CmdDraw(m_command_buffer, 4, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}