blob: 8cce671888838290f5608cc98aba34a268de1bc9 [file] [log] [blame]
/*
* Copyright (c) 2015-2023 The Khronos Group Inc.
* Copyright (c) 2015-2023 Valve Corporation
* Copyright (c) 2015-2023 LunarG, Inc.
* Copyright (c) 2015-2023 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"
TEST_F(NegativePipelineTopology, PolygonMode) {
TEST_DESCRIPTION("Attempt to use invalid polygon fill modes.");
VkPhysicalDeviceFeatures device_features = {};
device_features.fillModeNonSolid = VK_FALSE;
// The sacrificial device object
RETURN_IF_SKIP(Init(&device_features));
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;
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(this, 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(InitFramework())
RETURN_IF_SKIP(InitState())
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(this, 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(InitFramework())
RETURN_IF_SKIP(InitState())
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(this, 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);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extended_dynamic_state_features = vku::InitStructHelper();
GetPhysicalDeviceFeatures2(extended_dynamic_state_features);
if (!extended_dynamic_state_features.extendedDynamicState) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState";
}
RETURN_IF_SKIP(InitState(nullptr, &extended_dynamic_state_features));
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(this, 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(this, 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);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT ptl_restart_features = vku::InitStructHelper();
GetPhysicalDeviceFeatures2(ptl_restart_features);
if (!ptl_restart_features.primitiveTopologyListRestart) {
GTEST_SKIP() << "primitive topology list restart feature is not available, skipping test";
}
ptl_restart_features.primitiveTopologyListRestart = false;
ptl_restart_features.primitiveTopologyPatchListRestart = false;
RETURN_IF_SKIP(InitState(nullptr, &ptl_restart_features));
InitRenderTarget();
VkShaderObj vs(this, 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->phy().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);
RETURN_IF_SKIP(Init())
InitRenderTarget();
if (!m_device->phy().features().tessellationShader) {
GTEST_SKIP() << "Device does not support tessellation shaders";
}
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);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceFeatures device_features = {};
GetPhysicalDeviceFeatures(&device_features);
// 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.
device_features.fillModeNonSolid = VK_FALSE;
RETURN_IF_SKIP(InitState(&device_features));
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);
}