blob: 1194e8de6fd8472f8706f1e666b19f370c121a47 [file] [log] [blame]
/*
* Copyright (c) 2015-2025 The Khronos Group Inc.
* Copyright (c) 2015-2025 Valve Corporation
* Copyright (c) 2015-2025 LunarG, Inc.
* Copyright (c) 2015-2025 Google, Inc.
* Modifications Copyright (C) 2022 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 <gtest/gtest.h>
#include <vulkan/vulkan_core.h>
#include "../framework/layer_validation_tests.h"
#include "../framework/pipeline_helper.h"
#include "../framework/render_pass_helper.h"
#include <cmath>
class NegativeDynamicState : public DynamicStateTest {
// helper functions for tests in this file
public:
// VK_EXT_extended_dynamic_state - not calling vkCmdSet before draw
void ExtendedDynamicStateDrawNotSet(VkDynamicState dynamic_state, const char *vuid);
// VK_EXT_extended_dynamic_state3 - Create a pipeline with dynamic state, but the feature disabled
void ExtendedDynamicState3PipelineFeatureDisabled(VkDynamicState dynamic_state, const char *vuid);
// VK_EXT_line_rasterization - Init with LineRasterization features off
void InitLineRasterizationFeatureDisabled();
};
TEST_F(NegativeDynamicState, DepthBiasNotBound) {
TEST_DESCRIPTION(
"Run a simple draw calls to validate failure when Depth Bias dynamic state is required but not correctly bound.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS);
pipe.rs_state_ci_.lineWidth = 1.0f;
pipe.rs_state_ci_.depthBiasEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07834");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, LineWidthNotBound) {
TEST_DESCRIPTION(
"Run a simple draw calls to validate failure when Line Width dynamic state is required but not correctly bound.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH);
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08617");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, LineStippleNotBound) {
TEST_DESCRIPTION(
"Run a simple draw calls to validate failure when Line Stipple dynamic state is required but not correctly bound.");
AddRequiredExtensions(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::stippledBresenhamLines);
AddRequiredFeature(vkt::Feature::bresenhamLines);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
VkPipelineRasterizationLineStateCreateInfo line_state = vku::InitStructHelper();
pipe.AddDynamicState(VK_DYNAMIC_STATE_LINE_STIPPLE);
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
line_state.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM;
line_state.stippledLineEnable = VK_TRUE;
line_state.lineStippleFactor = 1;
line_state.lineStipplePattern = 0;
pipe.rs_state_ci_.pNext = &line_state;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07849");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, InvalidateStaticPipeline) {
TEST_DESCRIPTION("We track which pipeline has caused the dynamic state to be invalidated, make sure it is working correctly.");
AddRequiredExtensions(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_LINE_RASTERIZATION_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3LineStippleEnable);
AddRequiredFeature(vkt::Feature::stippledBresenhamLines);
AddRequiredFeature(vkt::Feature::bresenhamLines);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPipelineRasterizationLineStateCreateInfo line_state = vku::InitStructHelper();
line_state.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM;
line_state.stippledLineEnable = VK_TRUE;
line_state.lineStippleFactor = 1;
line_state.lineStipplePattern = 0;
VkDebugUtilsObjectNameInfoEXT name_info = vku::InitStructHelper();
name_info.objectType = VK_OBJECT_TYPE_PIPELINE;
CreatePipelineHelper pipe_0(*this);
pipe_0.AddDynamicState(VK_DYNAMIC_STATE_LINE_STIPPLE);
pipe_0.AddDynamicState(VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
pipe_0.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
pipe_0.rs_state_ci_.pNext = &line_state;
pipe_0.CreateGraphicsPipeline();
name_info.objectHandle = (uint64_t)pipe_0.Handle();
name_info.pObjectName = "Both Dynamic";
vk::SetDebugUtilsObjectNameEXT(device(), &name_info);
CreatePipelineHelper pipe_1(*this);
pipe_1.AddDynamicState(VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
pipe_1.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
pipe_1.rs_state_ci_.pNext = &line_state;
pipe_1.CreateGraphicsPipeline();
name_info.objectHandle = (uint64_t)pipe_1.Handle();
name_info.pObjectName = "Single Dynamic";
vk::SetDebugUtilsObjectNameEXT(device(), &name_info);
CreatePipelineHelper pipe_2(*this);
pipe_2.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
pipe_2.rs_state_ci_.pNext = &line_state;
pipe_2.CreateGraphicsPipeline();
name_info.objectHandle = (uint64_t)pipe_2.Handle();
name_info.pObjectName = "No Dynamic";
vk::SetDebugUtilsObjectNameEXT(device(), &name_info);
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetLineStippleKHR(m_command_buffer, 1, 0);
vk::CmdSetLineStippleEnableEXT(m_command_buffer, VK_TRUE);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_0);
// Invalidate one dynamic state at a time
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_1);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_2);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_0);
m_errorMonitor->SetDesiredError("No Dynamic"); // VUID-vkCmdDraw-None-08669
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdSetLineStippleEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->SetDesiredError("Single Dynamic"); // VUID-vkCmdDraw-None-07849
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ViewportNotBound) {
TEST_DESCRIPTION(
"Run a simple draw calls to validate failure when Viewport dynamic state is required but not correctly bound.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07831");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, ScissorNotBound) {
TEST_DESCRIPTION("Run a simple draw calls to validate failure when Scissor dynamic state is required but not correctly bound.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07832");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, BlendConstantsNotBound) {
TEST_DESCRIPTION(
"Run a simple draw calls to validate failure when Blend Constants dynamic state is required but not correctly bound.");
// 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_BLEND_CONSTANTS);
pipe.cb_attachments_.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR;
pipe.cb_attachments_.blendEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07835");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, DepthBoundsNotBound) {
TEST_DESCRIPTION(
"Run a simple draw calls to validate failure when Depth Bounds dynamic state is required but not correctly bound.");
AddRequiredFeature(vkt::Feature::depthBounds);
RETURN_IF_SKIP(Init());
m_depth_stencil_fmt = FindSupportedDepthStencilFormat(Gpu());
vkt::Image depth_image(*m_device, m_width, m_height, m_depth_stencil_fmt, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkt::ImageView depth_image_view = depth_image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
InitRenderTarget(1, &depth_image_view.handle());
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
pipe.ds_ci_ = vku::InitStructHelper();
pipe.ds_ci_.depthWriteEnable = VK_TRUE;
pipe.ds_ci_.depthBoundsTestEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07836");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, StencilReadNotBound) {
TEST_DESCRIPTION(
"Run a simple draw calls to validate failure when Stencil Read dynamic state is required but not correctly bound.");
RETURN_IF_SKIP(Init());
m_depth_stencil_fmt = FindSupportedDepthStencilFormat(Gpu());
vkt::Image depth_image(*m_device, m_width, m_height, m_depth_stencil_fmt, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkt::ImageView depth_image_view = depth_image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
InitRenderTarget(1, &depth_image_view.handle());
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK);
pipe.ds_ci_ = vku::InitStructHelper();
pipe.ds_ci_.depthWriteEnable = VK_TRUE;
pipe.ds_ci_.stencilTestEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07837");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, StencilWriteNotBound) {
TEST_DESCRIPTION(
"Run a simple draw calls to validate failure when Stencil Write dynamic state is required but not correctly bound.");
RETURN_IF_SKIP(Init());
m_depth_stencil_fmt = FindSupportedDepthStencilFormat(Gpu());
vkt::Image depth_image(*m_device, m_width, m_height, m_depth_stencil_fmt, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkt::ImageView depth_image_view = depth_image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
InitRenderTarget(1, &depth_image_view.handle());
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK);
pipe.ds_ci_ = vku::InitStructHelper();
pipe.ds_ci_.depthWriteEnable = VK_TRUE;
pipe.ds_ci_.stencilTestEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07838");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, StencilRefNotBound) {
TEST_DESCRIPTION(
"Run a simple draw calls to validate failure when Stencil Ref dynamic state is required but not correctly bound.");
RETURN_IF_SKIP(Init());
m_depth_stencil_fmt = FindSupportedDepthStencilFormat(Gpu());
vkt::Image depth_image(*m_device, m_width, m_height, m_depth_stencil_fmt, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkt::ImageView depth_image_view = depth_image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
InitRenderTarget(1, &depth_image_view.handle());
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
pipe.ds_ci_ = vku::InitStructHelper();
pipe.ds_ci_.depthWriteEnable = VK_TRUE;
pipe.ds_ci_.stencilTestEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07839");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, SetScissorParam) {
TEST_DESCRIPTION("Test parameters of vkCmdSetScissor without multiViewport feature");
VkPhysicalDeviceFeatures features{};
RETURN_IF_SKIP(Init(&features));
const VkRect2D scissor = {{0, 0}, {16, 16}};
const VkRect2D scissors[] = {scissor, scissor};
m_command_buffer.Begin();
// array tests
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-firstScissor-00593");
vk::CmdSetScissor(m_command_buffer, 1, 1, scissors);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-scissorCount-arraylength");
vk::CmdSetScissor(m_command_buffer, 0, 0, nullptr);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-scissorCount-00594");
vk::CmdSetScissor(m_command_buffer, 0, 2, scissors);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-firstScissor-00593");
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-scissorCount-00594");
vk::CmdSetScissor(m_command_buffer, 1, 2, scissors);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-pScissors-parameter");
vk::CmdSetScissor(m_command_buffer, 0, 1, nullptr);
m_errorMonitor->VerifyFound();
struct TestCase {
VkRect2D scissor;
std::string vuid;
};
std::vector<TestCase> test_cases = {{{{-1, 0}, {16, 16}}, "VUID-vkCmdSetScissor-x-00595"},
{{{0, -1}, {16, 16}}, "VUID-vkCmdSetScissor-x-00595"},
{{{1, 0}, {vvl::kI32Max, 16}}, "VUID-vkCmdSetScissor-offset-00596"},
{{{vvl::kI32Max, 0}, {1, 16}}, "VUID-vkCmdSetScissor-offset-00596"},
{{{0, 0}, {uint32_t{vvl::kI32Max} + 1, 16}}, "VUID-vkCmdSetScissor-offset-00596"},
{{{0, 1}, {16, vvl::kI32Max}}, "VUID-vkCmdSetScissor-offset-00597"},
{{{0, vvl::kI32Max}, {16, 1}}, "VUID-vkCmdSetScissor-offset-00597"},
{{{0, 0}, {16, uint32_t{vvl::kI32Max} + 1}}, "VUID-vkCmdSetScissor-offset-00597"}};
for (const auto &test_case : test_cases) {
m_errorMonitor->SetDesiredError(test_case.vuid.c_str());
vk::CmdSetScissor(m_command_buffer, 0, 1, &test_case.scissor);
m_errorMonitor->VerifyFound();
}
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SetScissorParamMultiviewport) {
TEST_DESCRIPTION("Test parameters of vkCmdSetScissor with multiViewport feature enabled");
AddRequiredFeature(vkt::Feature::multiViewport);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-scissorCount-arraylength");
vk::CmdSetScissor(m_command_buffer, 0, 0, nullptr);
m_errorMonitor->VerifyFound();
const auto max_scissors = m_device->Physical().limits_.maxViewports;
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-pScissors-parameter");
vk::CmdSetScissor(m_command_buffer, 0, max_scissors, nullptr);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, SetScissorParamMultiviewportLimit) {
AddRequiredFeature(vkt::Feature::multiViewport);
RETURN_IF_SKIP(Init());
const auto max_scissors = m_device->Physical().limits_.maxViewports;
const uint32_t too_big_max_scissors = 65536 + 1; // let's say this is too much to allocate
if (max_scissors >= too_big_max_scissors) {
GTEST_SKIP() << "maxViewports is too large to practically test against";
}
m_command_buffer.Begin();
const VkRect2D scissor = {{0, 0}, {16, 16}};
const std::vector<VkRect2D> scissors(max_scissors + 1, scissor);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-firstScissor-00592");
vk::CmdSetScissor(m_command_buffer, 0, max_scissors + 1, scissors.data());
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-firstScissor-00592");
vk::CmdSetScissor(m_command_buffer, max_scissors, 1, scissors.data());
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-firstScissor-00592");
vk::CmdSetScissor(m_command_buffer, 1, max_scissors, scissors.data());
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissor-scissorCount-arraylength");
vk::CmdSetScissor(m_command_buffer, 1, 0, scissors.data());
m_errorMonitor->VerifyFound();
}
template <typename ExtType, typename Parm>
void ExtendedDynStateCalls(ErrorMonitor *error_monitor, VkCommandBuffer cmd_buf, ExtType ext_call, const char *vuid, Parm parm) {
error_monitor->SetDesiredError(vuid);
ext_call(cmd_buf, parm);
error_monitor->VerifyFound();
}
TEST_F(NegativeDynamicState, ExtendedDynamicStateDisabled) {
TEST_DESCRIPTION("Validate VK_EXT_extended_dynamic_state VUs");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
const VkDynamicState dyn_states[] = {
VK_DYNAMIC_STATE_CULL_MODE, VK_DYNAMIC_STATE_FRONT_FACE,
VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY, VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT,
VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT, VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE,
VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE,
VK_DYNAMIC_STATE_DEPTH_COMPARE_OP, VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE,
VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE, VK_DYNAMIC_STATE_STENCIL_OP,
};
VkPipelineDynamicStateCreateInfo dyn_state_ci = vku::InitStructHelper();
dyn_state_ci.dynamicStateCount = size32(dyn_states);
dyn_state_ci.pDynamicStates = dyn_states;
pipe.dyn_state_ci_ = dyn_state_ci;
pipe.vp_state_ci_.viewportCount = 0;
pipe.vp_state_ci_.scissorCount = 0;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-03378");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetCullMode-None-08971");
vk::CmdSetCullModeEXT(m_command_buffer, VK_CULL_MODE_NONE);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthBoundsTestEnable-None-08971");
vk::CmdSetDepthBoundsTestEnableEXT(m_command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthCompareOp-None-08971");
vk::CmdSetDepthCompareOpEXT(m_command_buffer, VK_COMPARE_OP_NEVER);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthTestEnable-None-08971");
vk::CmdSetDepthTestEnableEXT(m_command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthWriteEnable-None-08971");
vk::CmdSetDepthWriteEnableEXT(m_command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetFrontFace-None-08971");
vk::CmdSetFrontFaceEXT(m_command_buffer, VK_FRONT_FACE_CLOCKWISE);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetPrimitiveTopology-None-08971");
vk::CmdSetPrimitiveTopologyEXT(m_command_buffer, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissorWithCount-None-08971");
VkRect2D scissor = {{0, 0}, {1, 1}};
vk::CmdSetScissorWithCountEXT(m_command_buffer, 1, &scissor);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetStencilOp-None-08971");
vk::CmdSetStencilOpEXT(m_command_buffer, VK_STENCIL_FACE_BACK_BIT, VK_STENCIL_OP_ZERO, VK_STENCIL_OP_ZERO, VK_STENCIL_OP_ZERO,
VK_COMPARE_OP_NEVER);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetStencilTestEnable-None-08971");
vk::CmdSetStencilTestEnableEXT(m_command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewportWithCount-None-08971");
VkViewport viewport = {0, 0, 1, 1, 0.0f, 0.0f};
vk::CmdSetViewportWithCountEXT(m_command_buffer, 1, &viewport);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindVertexBuffers2-None-08971");
vk::CmdBindVertexBuffers2EXT(m_command_buffer, 0, 0, nullptr, nullptr, nullptr, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ExtendedDynamicStateViewportScissorPipeline) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state pipeline creation with Viewport/Scissor");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
// Verify viewportCount and scissorCount are specified as zero.
{
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-03379");
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-03380");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
// Verify non-count and count dynamic states aren't used together
{
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
pipe.vp_state_ci_.viewportCount = 0;
pipe.vp_state_ci_.scissorCount = 1;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04132");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
{
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR);
pipe.vp_state_ci_.viewportCount = 1;
pipe.vp_state_ci_.scissorCount = 0;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04133");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDynamicState, ExtendedDynamicStateDuplicate) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state Duplicate dynamic state");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(InitFramework(&kDisableMessageLimit));
RETURN_IF_SKIP(InitState());
InitRenderTarget();
const VkDynamicState dyn_states[] = {
VK_DYNAMIC_STATE_CULL_MODE, VK_DYNAMIC_STATE_FRONT_FACE,
VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY, VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT,
VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT, VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE,
VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE,
VK_DYNAMIC_STATE_DEPTH_COMPARE_OP, VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE,
VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE, VK_DYNAMIC_STATE_STENCIL_OP,
};
// Verify dupes of every state.
for (size_t i = 0; i < std::size(dyn_states); ++i) {
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(dyn_states[i]);
pipe.AddDynamicState(dyn_states[i]);
if (dyn_states[i] == VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT) {
pipe.vp_state_ci_.viewportCount = 0;
}
if (dyn_states[i] == VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT) {
pipe.vp_state_ci_.scissorCount = 0;
}
m_errorMonitor->SetDesiredError("VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDynamicState, ExtendedDynamicStateBindVertexBuffers) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state Duplicate dynamic state");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
// Verify each vkCmdSet command
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
pipe.vp_state_ci_.viewportCount = 0;
pipe.vp_state_ci_.scissorCount = 0;
pipe.vi_ci_.vertexBindingDescriptionCount = 1;
VkVertexInputBindingDescription inputBinding = {0, sizeof(float), VK_VERTEX_INPUT_RATE_VERTEX};
pipe.vi_ci_.pVertexBindingDescriptions = &inputBinding;
pipe.vi_ci_.vertexAttributeDescriptionCount = 1;
VkVertexInputAttributeDescription attribute = {0, 0, VK_FORMAT_R32_SFLOAT, 0};
pipe.vi_ci_.pVertexAttributeDescriptions = &attribute;
pipe.CreateGraphicsPipeline();
vkt::Buffer buffer(*m_device, 16, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
std::vector<VkBuffer> buffers(m_device->Physical().limits_.maxVertexInputBindings + 1ull, buffer);
std::vector<VkDeviceSize> offsets(buffers.size(), 0);
vkt::CommandBuffer commandBuffer(*m_device, m_command_pool);
commandBuffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindVertexBuffers2-firstBinding-03355");
vk::CmdBindVertexBuffers2EXT(commandBuffer, m_device->Physical().limits_.maxVertexInputBindings, 1, buffers.data(),
offsets.data(), 0, 0);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindVertexBuffers2-firstBinding-03356");
vk::CmdBindVertexBuffers2EXT(commandBuffer, 0, m_device->Physical().limits_.maxVertexInputBindings + 1, buffers.data(),
offsets.data(), 0, 0);
m_errorMonitor->VerifyFound();
{
vkt::Buffer bufferWrongUsage(*m_device, 16, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
m_errorMonitor->SetDesiredError("VUID-vkCmdBindVertexBuffers2-pBuffers-03359");
VkBuffer buffers2[1] = {bufferWrongUsage};
VkDeviceSize offsets2[1] = {};
vk::CmdBindVertexBuffers2EXT(commandBuffer, 0, 1, buffers2, offsets2, 0, 0);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdBindVertexBuffers2-pBuffers-04111");
m_errorMonitor->SetUnexpectedError("UNASSIGNED-GeneralParameterError-RequiredHandle");
m_errorMonitor->SetUnexpectedError("VUID-vkCmdBindVertexBuffers2-pBuffers-parameter");
VkBuffer buffers2[1] = {VK_NULL_HANDLE};
VkDeviceSize offsets2[1] = {16};
VkDeviceSize strides[1] = {m_device->Physical().limits_.maxVertexInputBindingStride + 1ull};
vk::CmdBindVertexBuffers2EXT(commandBuffer, 0, 1, buffers2, offsets2, 0, 0);
m_errorMonitor->VerifyFound();
buffers2[0] = buffers[0];
VkDeviceSize sizes[1] = {16};
m_errorMonitor->SetDesiredError("VUID-vkCmdBindVertexBuffers2-pOffsets-03357");
m_errorMonitor->SetDesiredError("VUID-vkCmdBindVertexBuffers2-pSizes-03358");
vk::CmdBindVertexBuffers2EXT(commandBuffer, 0, 1, buffers2, offsets2, sizes, 0);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdBindVertexBuffers2-pStrides-03362");
vk::CmdBindVertexBuffers2EXT(commandBuffer, 0, 1, buffers2, offsets2, 0, strides);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDynamicState, ExtendedDynamicStateBindVertexBuffersWholeSize) {
TEST_DESCRIPTION("Test VK_WHOLE_SIZE with VK_EXT_extended_dynamic_state");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
vkt::Buffer buffer(*m_device, 16, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
VkDeviceSize size = VK_WHOLE_SIZE;
VkDeviceSize offset = 0;
m_errorMonitor->SetDesiredError("VUID-vkCmdBindVertexBuffers2-pSizes-03358");
vk::CmdBindVertexBuffers2EXT(m_command_buffer, 0, 1, &buffer.handle(), &offset, &size, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ExtendedDynamicStateViewportScissorDraw) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state viewport/scissor draw state");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
AddRequiredFeature(vkt::Feature::multiViewport); // needed to have 2 viewport count
RETURN_IF_SKIP(Init());
InitRenderTarget();
{
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
pipe.vp_state_ci_.viewportCount = 0;
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-viewportCount-03417");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
{
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
pipe.vp_state_ci_.scissorCount = 0;
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-scissorCount-03418");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
{
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
pipe.vp_state_ci_.viewportCount = 0;
pipe.vp_state_ci_.scissorCount = 0;
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
VkRect2D scissor[2] = {{{0, 0}, {1, 1}}, {{0, 0}, {1, 1}}};
VkViewport viewport = {0, 0, 1, 1, 0.0f, 0.0f};
vk::CmdSetScissorWithCountEXT(m_command_buffer, 2, scissor);
vk::CmdSetViewportWithCountEXT(m_command_buffer, 1, &viewport);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-viewportCount-03419");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
}
TEST_F(NegativeDynamicState, ExtendedDynamicStateSetViewportScissor) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state viewport/scissor draw state");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
AddRequiredFeature(vkt::Feature::multiViewport);
RETURN_IF_SKIP(Init());
InitRenderTarget();
vkt::Buffer buffer(*m_device, 16, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
std::vector<VkBuffer> buffers(m_device->Physical().limits_.maxVertexInputBindings + 1ull, buffer);
std::vector<VkDeviceSize> offsets(buffers.size(), 0);
const char *vs_source = R"glsl(
#version 450
layout(location=0) in vec4 x;
void main(){}
)glsl";
VkShaderObj vs(*m_device, vs_source, VK_SHADER_STAGE_VERTEX_BIT);
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY);
pipe.vp_state_ci_.viewportCount = 0;
pipe.vp_state_ci_.scissorCount = 0;
pipe.vi_ci_.vertexBindingDescriptionCount = 1;
VkVertexInputBindingDescription input_binding = {0, sizeof(float), VK_VERTEX_INPUT_RATE_VERTEX};
pipe.vi_ci_.pVertexBindingDescriptions = &input_binding;
pipe.vi_ci_.vertexAttributeDescriptionCount = 1;
VkVertexInputAttributeDescription attribute = {0, 0, VK_FORMAT_R32_SFLOAT, 0};
pipe.vi_ci_.pVertexAttributeDescriptions = &attribute;
pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
// set everything once
VkViewport viewport = {0, 0, 1, 1, 0.0f, 0.0f};
vk::CmdSetViewportWithCountEXT(m_command_buffer, 1, &viewport);
VkRect2D scissor = {{1, 0}, {16, 16}};
vk::CmdSetScissorWithCountEXT(m_command_buffer, 1, &scissor);
vk::CmdSetPrimitiveTopologyEXT(m_command_buffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
VkDeviceSize strides[] = {1};
vk::CmdBindVertexBuffers2EXT(m_command_buffer, 0, 1, buffers.data(), offsets.data(), 0, strides);
m_errorMonitor->SetDesiredError("VUID-vkCmdBindVertexBuffers2-pStrides-06209");
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-02721");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
strides[0] = 4;
vk::CmdBindVertexBuffers2EXT(m_command_buffer, 0, 1, buffers.data(), offsets.data(), 0, strides);
vk::CmdSetPrimitiveTopologyEXT(m_command_buffer, VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-dynamicPrimitiveTopologyUnrestricted-07500");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
{
// multiViewport
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewportWithCount-viewportCount-03394");
m_errorMonitor->SetUnexpectedError("VUID-vkCmdSetViewportWithCount-viewportCount-arraylength");
VkViewport viewport2 = {
0, 0, 1, 1, 0.0f, 0.0f,
};
vk::CmdSetViewportWithCountEXT(m_command_buffer, 0, &viewport2);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissorWithCount-offset-03400");
VkRect2D scissor2 = {{1, 0}, {vvl::kI32Max, 16}};
vk::CmdSetScissorWithCountEXT(m_command_buffer, 1, &scissor2);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissorWithCount-offset-03401");
VkRect2D scissor2 = {{0, 1}, {16, vvl::kI32Max}};
vk::CmdSetScissorWithCountEXT(m_command_buffer, 1, &scissor2);
m_errorMonitor->VerifyFound();
}
{
// multiViewport
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissorWithCount-scissorCount-03397");
m_errorMonitor->SetUnexpectedError("VUID-vkCmdSetScissorWithCount-scissorCount-arraylength");
vk::CmdSetScissorWithCountEXT(m_command_buffer, 0, 0);
m_errorMonitor->VerifyFound();
}
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissorWithCount-x-03399");
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissorWithCount-x-03399");
VkRect2D scissor3 = {{-1, -1}, {0, 0}};
vk::CmdSetScissorWithCountEXT(m_command_buffer, 1, &scissor3);
m_errorMonitor->VerifyFound();
vk::CmdBindVertexBuffers2EXT(m_command_buffer, 0, 0, nullptr, nullptr, nullptr, nullptr);
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ExtendedDynamicStateEnabledNoMultiview) {
TEST_DESCRIPTION("Validate VK_EXT_extended_dynamic_state VUs");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
vkt::CommandBuffer commandBuffer(*m_device, m_command_pool);
commandBuffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewportWithCount-viewportCount-03395");
VkViewport viewport = {0, 0, 1, 1, 0.0f, 0.0f};
VkViewport viewports[] = {viewport, viewport};
vk::CmdSetViewportWithCountEXT(commandBuffer, size32(viewports), viewports);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetScissorWithCount-scissorCount-03398");
VkRect2D scissor = {{0, 0}, {1, 1}};
VkRect2D scissors[] = {scissor, scissor};
vk::CmdSetScissorWithCountEXT(commandBuffer, size32(scissors), scissors);
m_errorMonitor->VerifyFound();
commandBuffer.End();
}
TEST_F(NegativeDynamicState, ExtendedDynamicState2Disabled) {
TEST_DESCRIPTION("Validate VK_EXT_extended_dynamic_state2 VUs");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04868");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
vkt::CommandBuffer command_buffer(*m_device, m_command_pool);
command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetRasterizerDiscardEnable-None-08970");
vk::CmdSetRasterizerDiscardEnableEXT(command_buffer, VK_TRUE);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthBiasEnable-None-08970");
vk::CmdSetDepthBiasEnableEXT(command_buffer, VK_TRUE);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetPrimitiveRestartEnable-None-08970");
vk::CmdSetPrimitiveRestartEnableEXT(command_buffer, VK_TRUE);
m_errorMonitor->VerifyFound();
command_buffer.End();
}
TEST_F(NegativeDynamicState, ExtendedDynamicState2PatchControlPointsDisabled) {
TEST_DESCRIPTION("Validate VK_EXT_extended_dynamic_state2 PatchControlPoints VUs");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04870");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
vkt::CommandBuffer command_buffer(*m_device, m_command_pool);
command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetPatchControlPointsEXT-None-09422");
vk::CmdSetPatchControlPointsEXT(command_buffer, 3);
m_errorMonitor->VerifyFound();
command_buffer.End();
}
TEST_F(NegativeDynamicState, ExtendedDynamicState2LogicOpDisabled) {
TEST_DESCRIPTION("Validate VK_EXT_extended_dynamic_state2LogicOp VUs");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LOGIC_OP_EXT);
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04869");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
vkt::CommandBuffer command_buffer(*m_device, m_command_pool);
command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetLogicOpEXT-None-09422");
vk::CmdSetLogicOpEXT(command_buffer, VK_LOGIC_OP_AND);
m_errorMonitor->VerifyFound();
command_buffer.End();
}
TEST_F(NegativeDynamicState, ExtendedDynamicState2Enabled) {
TEST_DESCRIPTION("Validate VK_EXT_extended_dynamic_state2 LogicOp VUs");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
RETURN_IF_SKIP(Init());
InitRenderTarget();
const VkDynamicState dyn_states[] = {VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE, VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE,
VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE};
for (size_t i = 0; i < std::size(dyn_states); ++i) {
// Verify duplicates of every dynamic state.
{
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(dyn_states[i]);
pipe.AddDynamicState(dyn_states[i]);
m_errorMonitor->SetDesiredError("VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
// Calling draw without setting the dynamic state is an error
{
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(dyn_states[i]);
pipe.CreateGraphicsPipeline();
vkt::CommandBuffer command_buffer(*m_device, m_command_pool);
command_buffer.Begin();
command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
if (dyn_states[i] == VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE)
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-04876");
if (dyn_states[i] == VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE) m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-04877");
if (dyn_states[i] == VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE)
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-04879");
vk::CmdDraw(command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdEndRenderPass(command_buffer);
command_buffer.End();
}
}
}
TEST_F(NegativeDynamicState, ExtendedDynamicState2InvalidateStaticPipeline) {
TEST_DESCRIPTION("Validate binding a non-dynamic pipeline trigger dynamic static errors");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
pipe.CreateGraphicsPipeline();
CreatePipelineHelper pipe_static(*this);
pipe_static.CreateGraphicsPipeline();
vkt::CommandBuffer command_buffer(*m_device, m_command_pool);
command_buffer.Begin();
vk::CmdSetPrimitiveRestartEnableEXT(command_buffer, VK_TRUE);
command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_static);
vk::CmdDraw(command_buffer, 1, 1, 0, 0);
vk::CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-04879");
vk::CmdDraw(command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdEndRenderPass(command_buffer);
command_buffer.End();
}
TEST_F(NegativeDynamicState, ExtendedDynamicState2PatchControlPointsEnabled) {
TEST_DESCRIPTION("Validate VK_EXT_extended_dynamic_state2 PatchControlPoints VUs");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::tessellationShader);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
AddRequiredFeature(vkt::Feature::extendedDynamicState2PatchControlPoints);
RETURN_IF_SKIP(Init());
InitRenderTarget();
// Verify dupes of the dynamic state.
{
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
m_errorMonitor->SetDesiredError("VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
{
VkPipelineTessellationStateCreateInfo tess_ci = vku::InitStructHelper();
VkShaderObj tcs(*m_device, kTessellationControlMinimalGlsl, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
VkShaderObj tes(*m_device, kTessellationEvalMinimalGlsl, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), tcs.GetStageCreateInfo(), tes.GetStageCreateInfo(),
pipe.fs_->GetStageCreateInfo()};
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
pipe.tess_ci_ = tess_ci;
pipe.CreateGraphicsPipeline();
vkt::CommandBuffer command_buffer(*m_device, m_command_pool);
command_buffer.Begin();
command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
// Calling draw without setting the dynamic state is an error
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-04875");
vk::CmdDraw(command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
// setting an invalid value for patchControlpoints is an error
m_errorMonitor->SetDesiredError("VUID-vkCmdSetPatchControlPointsEXT-patchControlPoints-04874");
vk::CmdSetPatchControlPointsEXT(command_buffer, 0x1000);
m_errorMonitor->VerifyFound();
vk::CmdEndRenderPass(command_buffer);
command_buffer.End();
}
}
TEST_F(NegativeDynamicState, ExtendedDynamicState2LogicOpEnabled) {
TEST_DESCRIPTION("Validate VK_EXT_extended_dynamic_state2 LogicOp VUs");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::logicOp);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
AddRequiredFeature(vkt::Feature::extendedDynamicState2LogicOp);
RETURN_IF_SKIP(Init());
InitRenderTarget();
// Verify dupes of the dynamic state.
{
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LOGIC_OP_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LOGIC_OP_EXT);
m_errorMonitor->SetDesiredError("VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
{
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LOGIC_OP_EXT);
pipe.cb_ci_.logicOpEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
vkt::CommandBuffer command_buffer(*m_device, m_command_pool);
command_buffer.Begin();
command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
// Calling draw without setting the dynamic state is an error
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-logicOp-04878");
vk::CmdDraw(command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdEndRenderPass(command_buffer);
command_buffer.End();
}
}
void NegativeDynamicState::ExtendedDynamicState3PipelineFeatureDisabled(VkDynamicState dynamic_state, const char *vuid) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(dynamic_state);
m_errorMonitor->SetDesiredError(vuid);
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledTessellationDomainOrigin) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3TessellationDomainOrigin-07370");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledDepthClampEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3DepthClampEnable-07371");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledPolygonMode) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_POLYGON_MODE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3PolygonMode-07372");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledRasterizationSamples) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3RasterizationSamples-07373");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledSampleMask) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_SAMPLE_MASK_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3SampleMask-07374");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledAlphaToCoverageEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3AlphaToCoverageEnable-07375");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledAlphaToOneEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3AlphaToOneEnable-07376");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledLogicOpEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3LogicOpEnable-07377");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledColorBlendEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3ColorBlendEnable-07378");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledColorBlendEquation) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3ColorBlendEquation-07379");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledColorWriteMask) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3ColorWriteMask-07380");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledRasterizationStream) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3RasterizationStream-07381");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledExtraPrimitiveOverestimationSize) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3ExtraPrimitiveOverestimationSize-07383");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledDepthClipEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3DepthClipEnable-07384");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledSampleLocationsEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3SampleLocationsEnable-07385");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledColorBlendAdvanced) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3ColorBlendAdvanced-07386");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledProvokingVertexMode) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3ProvokingVertexMode-07387");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledLineRasterizationMode) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3LineRasterizationMode-07388");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledLineStippleEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3LineStippleEnable-07389");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledDepthClipNegativeOneToOne) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3DepthClipNegativeOneToOne-07390");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledViewportWScalingEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3ViewportWScalingEnable-07391");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledViewportSwizzle) {
ExtendedDynamicState3PipelineFeatureDisabled(VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3ViewportSwizzle-07392");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledCoverageToColorEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3CoverageToColorEnable-07393");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledCoverageToColorLocation) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3CoverageToColorLocation-07394");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledCoverageModulationMode) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3CoverageModulationMode-07395");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledCoverageModulationTableEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3CoverageModulationTableEnable-07396");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledCoverageModulationTable) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3CoverageModulationTable-07397");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledCoverageReductionMode) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3CoverageReductionMode-07398");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledRepresentativeFragmentTestEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3RepresentativeFragmentTestEnable-07399");
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledShadingRateImageEnable) {
ExtendedDynamicState3PipelineFeatureDisabled(
VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV,
"VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3ShadingRateImageEnable-07400");
}
TEST_F(NegativeDynamicState, ExtendedDynamicState3CmdSetFeatureDisabled) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 calling vkCmdSet* without feature");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
// Check feature is enable for each set command.
vkt::CommandBuffer command_buffer(*m_device, m_command_pool);
command_buffer.Begin();
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetTessellationDomainOriginEXT-None-09423");
vk::CmdSetTessellationDomainOriginEXT(command_buffer, VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthClampEnableEXT-None-09423");
vk::CmdSetDepthClampEnableEXT(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetPolygonModeEXT-None-09423");
vk::CmdSetPolygonModeEXT(command_buffer, VK_POLYGON_MODE_FILL);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetRasterizationSamplesEXT-None-09423");
vk::CmdSetRasterizationSamplesEXT(command_buffer, VK_SAMPLE_COUNT_1_BIT);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetSampleMaskEXT-None-09423");
VkSampleMask sampleMask = 1U;
vk::CmdSetSampleMaskEXT(command_buffer, VK_SAMPLE_COUNT_1_BIT, &sampleMask);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetAlphaToCoverageEnableEXT-None-09423");
vk::CmdSetAlphaToCoverageEnableEXT(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetAlphaToOneEnableEXT-None-09423");
vk::CmdSetAlphaToOneEnableEXT(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetLogicOpEnableEXT-None-09423");
vk::CmdSetLogicOpEnableEXT(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetColorBlendEnableEXT-None-09423");
VkBool32 enable = VK_FALSE;
vk::CmdSetColorBlendEnableEXT(command_buffer, 0U, 1U, &enable);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetColorBlendEquationEXT-None-09423");
VkColorBlendEquationEXT equation = {
VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD,
};
vk::CmdSetColorBlendEquationEXT(command_buffer, 0U, 1U, &equation);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetColorWriteMaskEXT-None-09423");
VkColorComponentFlags const components = {VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
VK_COLOR_COMPONENT_A_BIT};
vk::CmdSetColorWriteMaskEXT(command_buffer, 0U, 1U, &components);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetRasterizationStreamEXT-None-09423");
m_errorMonitor->SetDesiredError("VUID-vkCmdSetRasterizationStreamEXT-transformFeedback-07411");
m_errorMonitor->SetDesiredError("VUID-vkCmdSetRasterizationStreamEXT-rasterizationStream-07412");
vk::CmdSetRasterizationStreamEXT(command_buffer, 0U);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetConservativeRasterizationModeEXT-None-09423");
vk::CmdSetConservativeRasterizationModeEXT(command_buffer, VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetExtraPrimitiveOverestimationSizeEXT-None-09423");
vk::CmdSetExtraPrimitiveOverestimationSizeEXT(command_buffer, 0.0f);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthClipEnableEXT-None-09423");
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthClipEnableEXT-depthClipEnable-07451");
vk::CmdSetDepthClipEnableEXT(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetSampleLocationsEnableEXT-None-09423");
vk::CmdSetSampleLocationsEnableEXT(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetColorBlendAdvancedEXT-None-09423");
VkColorBlendAdvancedEXT const advanced = {VK_BLEND_OP_BLUE_EXT, VK_FALSE, VK_FALSE, VK_BLEND_OVERLAP_UNCORRELATED_EXT,
VK_FALSE};
vk::CmdSetColorBlendAdvancedEXT(command_buffer, 0U, 1U, &advanced);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetProvokingVertexModeEXT-None-09423");
vk::CmdSetProvokingVertexModeEXT(command_buffer, VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetLineRasterizationModeEXT-None-09423");
vk::CmdSetLineRasterizationModeEXT(command_buffer, VK_LINE_RASTERIZATION_MODE_DEFAULT);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetLineStippleEnableEXT-None-09423");
vk::CmdSetLineStippleEnableEXT(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthClipNegativeOneToOneEXT-None-09423");
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthClipNegativeOneToOneEXT-depthClipControl-07453");
vk::CmdSetDepthClipNegativeOneToOneEXT(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewportWScalingEnableNV-None-09423");
vk::CmdSetViewportWScalingEnableNV(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewportSwizzleNV-None-09423");
VkViewportSwizzleNV const swizzle = {
VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV,
VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV};
vk::CmdSetViewportSwizzleNV(command_buffer, 0U, 1U, &swizzle);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetCoverageToColorEnableNV-None-09423");
vk::CmdSetCoverageToColorEnableNV(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetCoverageToColorLocationNV-None-09423");
vk::CmdSetCoverageToColorLocationNV(command_buffer, 0U);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetCoverageModulationModeNV-None-09423");
vk::CmdSetCoverageModulationModeNV(command_buffer, VK_COVERAGE_MODULATION_MODE_NONE_NV);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetCoverageModulationTableEnableNV-None-09423");
vk::CmdSetCoverageModulationTableEnableNV(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetCoverageModulationTableNV-None-09423");
float const modulation = 1.0f;
vk::CmdSetCoverageModulationTableNV(command_buffer, 1U, &modulation);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetShadingRateImageEnableNV-None-09423");
vk::CmdSetShadingRateImageEnableNV(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetRepresentativeFragmentTestEnableNV-None-09423");
vk::CmdSetRepresentativeFragmentTestEnableNV(command_buffer, VK_FALSE);
m_errorMonitor->VerifyFound();
}
{
m_errorMonitor->SetDesiredError("VUID-vkCmdSetCoverageReductionModeNV-None-09423");
vk::CmdSetCoverageReductionModeNV(command_buffer, VK_COVERAGE_REDUCTION_MODE_MERGE_NV);
m_errorMonitor->VerifyFound();
}
command_buffer.End();
}
TEST_F(NegativeDynamicState, NullSampleMask) {
TEST_DESCRIPTION("Call vkCmdSetSampleMaskEXT with a NULL pSampleMask and without maintenance10");
SetTargetApiVersion(VK_API_VERSION_1_3);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3SampleMask);
RETURN_IF_SKIP(Init());
InitRenderTarget();
// Check feature is enable for each set command.
vkt::CommandBuffer command_buffer(*m_device, m_command_pool);
command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetSampleMaskEXT-pSampleMask-10999");
vk::CmdSetSampleMaskEXT(command_buffer, VK_SAMPLE_COUNT_1_BIT, nullptr);
m_errorMonitor->VerifyFound();
command_buffer.End();
}
TEST_F(NegativeDynamicState, ExtendedDynamicState3DuplicateStatePipeline) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 Duplicate state in pipeline");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework(&kDisableMessageLimit));
RETURN_IF_SKIP(InitState());
InitRenderTarget();
VkDynamicState const dyn_states[] = {VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT,
VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT,
VK_DYNAMIC_STATE_POLYGON_MODE_EXT,
VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT,
VK_DYNAMIC_STATE_SAMPLE_MASK_EXT,
VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT,
VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT,
VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT,
VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT,
VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT,
VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT,
VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT,
VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT,
VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT,
VK_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT,
VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT,
VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT,
VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT,
VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT,
VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT,
VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV,
VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV,
VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV,
VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV,
VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV,
VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV,
VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV,
VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV,
VK_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV,
VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV};
// Verify dupes of every state.
for (size_t i = 0; i < std::size(dyn_states); ++i) {
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(dyn_states[i]);
pipe.AddDynamicState(dyn_states[i]);
m_errorMonitor->SetDesiredError("VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDynamicState, DrawNotSetTessellationDomainOrigin) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_KHR_MAINTENANCE2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3TessellationDomainOrigin);
AddRequiredFeature(vkt::Feature::tessellationShader);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPipelineTessellationDomainOriginStateCreateInfo tess_domain_ci = vku::InitStructHelper();
tess_domain_ci.domainOrigin = VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT;
VkPipelineTessellationStateCreateInfo tess_ci = vku::InitStructHelper(&tess_domain_ci);
tess_ci.patchControlPoints = 4u;
VkShaderObj tcs(*m_device, kTessellationControlMinimalGlsl, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
VkShaderObj tes(*m_device, kTessellationEvalMinimalGlsl, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT);
pipe.gp_ci_.pTessellationState = &tess_ci;
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), tcs.GetStageCreateInfo(), tes.GetStageCreateInfo(),
pipe.fs_->GetStageCreateInfo()};
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07619");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdSetTessellationDomainOriginEXT(m_command_buffer, VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT);
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetDepthClampEnable) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::depthClamp);
AddRequiredFeature(vkt::Feature::extendedDynamicState3DepthClampEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07620");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SetDepthClampFeature) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3DepthClampEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthClampEnableEXT-depthClamp-07449");
vk::CmdSetDepthClampEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SetDepthBoundsTestEnableFeature) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthBoundsTestEnable-depthBounds-10010");
vk::CmdSetDepthBoundsTestEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetPolygonMode) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3PolygonMode);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_POLYGON_MODE_EXT);
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07621");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetPolygonModeEXT-fillModeNonSolid-07424");
vk::CmdSetPolygonModeEXT(m_command_buffer, VK_POLYGON_MODE_POINT);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetPolygonModeEXT-polygonMode-parameter");
// 07425 is effectively handled by VUID-vkCmdSetPolygonModeEXT-polygonMode-parameter since it triggers when the enum is used
// without the extension being enabled m_errorMonitor->SetDesiredFailureMsg(kErrorBit,
// "VUID-vkCmdSetPolygonModeEXT-polygonMode-07425");
vk::CmdSetPolygonModeEXT(m_command_buffer, VK_POLYGON_MODE_FILL_RECTANGLE_NV);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetAlphaToOneEnable) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::alphaToOne);
AddRequiredFeature(vkt::Feature::extendedDynamicState3AlphaToOneEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07625");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, AlphaToOneFeature) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3AlphaToOneEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetAlphaToOneEnableEXT-alphaToOne-07607");
vk::CmdSetAlphaToOneEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetLogicOpEnable) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3LogicOpEnable);
AddRequiredFeature(vkt::Feature::logicOp);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07626");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SetLogicOpFeature) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3LogicOpEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetLogicOpEnableEXT-logicOp-07366");
vk::CmdSetLogicOpEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetColorBlendEquation) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEquation);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
pipe.cb_attachments_.blendEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-10862");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkColorBlendEquationEXT-dualSrcBlend-07357");
m_errorMonitor->SetDesiredError("VUID-VkColorBlendEquationEXT-dualSrcBlend-07358");
m_errorMonitor->SetDesiredError("VUID-VkColorBlendEquationEXT-dualSrcBlend-07359");
m_errorMonitor->SetDesiredError("VUID-VkColorBlendEquationEXT-dualSrcBlend-07360");
m_errorMonitor->SetDesiredError("VUID-VkColorBlendEquationEXT-colorBlendOp-07361");
VkColorBlendEquationEXT const equation = {VK_BLEND_FACTOR_SRC1_COLOR, VK_BLEND_FACTOR_SRC1_COLOR, VK_BLEND_OP_ZERO_EXT,
VK_BLEND_FACTOR_SRC1_COLOR, VK_BLEND_FACTOR_SRC1_COLOR, VK_BLEND_OP_ZERO_EXT};
vk::CmdSetColorBlendEquationEXT(m_command_buffer, 0U, 1U, &equation);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorBlendEquationMultipleAttachments) {
TEST_DESCRIPTION("Only update some of the dynamic color blend equations");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEquation);
RETURN_IF_SKIP(Init());
InitRenderTarget(2);
VkPipelineColorBlendAttachmentState color_blend[2] = {};
color_blend[0] = DefaultColorBlendAttachmentState();
color_blend[1] = DefaultColorBlendAttachmentState();
CreatePipelineHelper pipe(*this);
pipe.cb_ci_.attachmentCount = 2;
pipe.cb_ci_.pAttachments = color_blend;
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
const VkColorBlendEquationEXT equation = {VK_BLEND_FACTOR_SRC_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_OP_ADD,
VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_OP_ADD};
vk::CmdSetColorBlendEquationEXT(m_command_buffer, 1, 1, &equation);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-10862");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorBlendEquationInvalidateStaticPipeline) {
TEST_DESCRIPTION("Only update some of the dynamic color blend equations");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEquation);
RETURN_IF_SKIP(Init());
InitRenderTarget(2);
VkPipelineColorBlendAttachmentState color_blend[2] = {};
color_blend[0] = DefaultColorBlendAttachmentState();
color_blend[1] = DefaultColorBlendAttachmentState();
CreatePipelineHelper pipe(*this);
pipe.cb_ci_.attachmentCount = 2;
pipe.cb_ci_.pAttachments = color_blend;
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
pipe.CreateGraphicsPipeline();
CreatePipelineHelper pipe_static(*this);
pipe_static.cb_ci_.attachmentCount = 2;
pipe_static.cb_ci_.pAttachments = color_blend;
pipe_static.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
const VkColorBlendEquationEXT equation = {VK_BLEND_FACTOR_SRC_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_OP_ADD,
VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_OP_ADD};
vk::CmdSetColorBlendEquationEXT(m_command_buffer, 0, 1, &equation);
vk::CmdSetColorBlendEquationEXT(m_command_buffer, 1, 1, &equation);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_static);
// never reset index 1
vk::CmdSetColorBlendEquationEXT(m_command_buffer, 0, 1, &equation);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-10862");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetRasterizationStream) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::geometryShader);
AddRequiredFeature(vkt::Feature::geometryStreams);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationStream);
AddRequiredFeature(vkt::Feature::transformFeedback);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(transform_feedback_props);
VkShaderObj gs(*m_device, kGeometryMinimalGlsl, VK_SHADER_STAGE_GEOMETRY_BIT);
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT);
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), gs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07630");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetRasterizationStreamEXT-rasterizationStream-07412");
if (!transform_feedback_props.transformFeedbackRasterizationStreamSelect) {
m_errorMonitor->SetDesiredError("VUID-vkCmdSetRasterizationStreamEXT-rasterizationStream-07413");
}
vk::CmdSetRasterizationStreamEXT(m_command_buffer, transform_feedback_props.maxTransformFeedbackStreams + 1);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetExtraPrimitiveOverestimationSize) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ExtraPrimitiveOverestimationSize);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservative_rasterization_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(conservative_rasterization_props);
if (!conservative_rasterization_props.conservativePointAndLineRasterization) {
GTEST_SKIP() << "conservativePointAndLineRasterization is not supported";
}
m_command_buffer.Begin();
VkPipelineRasterizationConservativeStateCreateInfoEXT cs_info = vku::InitStructHelper();
cs_info.conservativeRasterizationMode = VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
cs_info.extraPrimitiveOverestimationSize = 0.0f;
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT);
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
pipe.rs_state_ci_.pNext = &cs_info;
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07632");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetExtraPrimitiveOverestimationSizeEXT-extraPrimitiveOverestimationSize-07428");
vk::CmdSetExtraPrimitiveOverestimationSizeEXT(m_command_buffer, -1.0F);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetColorBlendAdvanced) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendAdvanced);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blend_operation_advanced = vku::InitStructHelper();
GetPhysicalDeviceProperties2(blend_operation_advanced);
m_command_buffer.Begin();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT);
pipe.cb_attachments_.blendEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
VkColorBlendAdvancedEXT second = {VK_BLEND_OP_ADD, VK_FALSE, VK_FALSE, VK_BLEND_OVERLAP_UNCORRELATED_EXT, VK_FALSE};
vk::CmdSetColorBlendAdvancedEXT(m_command_buffer, 1u, 1u, &second);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-rasterizerDiscardEnable-10863");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
if (!blend_operation_advanced.advancedBlendNonPremultipliedSrcColor) {
m_errorMonitor->SetDesiredError("VUID-VkColorBlendAdvancedEXT-srcPremultiplied-07505");
}
if (!blend_operation_advanced.advancedBlendNonPremultipliedDstColor) {
m_errorMonitor->SetDesiredError("VUID-VkColorBlendAdvancedEXT-dstPremultiplied-07506");
}
if (!blend_operation_advanced.advancedBlendCorrelatedOverlap) {
m_errorMonitor->SetDesiredError("VUID-VkColorBlendAdvancedEXT-blendOverlap-07507");
}
VkColorBlendAdvancedEXT advanced = {VK_BLEND_OP_ZERO_EXT, VK_TRUE, VK_TRUE, VK_BLEND_OVERLAP_DISJOINT_EXT, VK_FALSE};
vk::CmdSetColorBlendAdvancedEXT(m_command_buffer, 0U, 1U, &advanced);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetProvokingVertexMode) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ProvokingVertexMode);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT);
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07636");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetProvokingVertexModeEXT-provokingVertexMode-07447");
vk::CmdSetProvokingVertexModeEXT(m_command_buffer, VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetLineRasterizationMode) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3LineRasterizationMode);
AddRequiredFeature(vkt::Feature::stippledRectangularLines);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08666");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetLineRasterizationModeEXT-lineRasterizationMode-07418");
vk::CmdSetLineRasterizationModeEXT(m_command_buffer, VK_LINE_RASTERIZATION_MODE_RECTANGULAR);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetLineRasterizationModeEXT-lineRasterizationMode-07419");
vk::CmdSetLineRasterizationModeEXT(m_command_buffer, VK_LINE_RASTERIZATION_MODE_BRESENHAM);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetLineRasterizationModeEXT-lineRasterizationMode-07420");
vk::CmdSetLineRasterizationModeEXT(m_command_buffer, VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetLineStippleEnable) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3LineStippleEnable);
AddRequiredFeature(vkt::Feature::stippledRectangularLines);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
pipe.CreateGraphicsPipeline();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08669");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetLineStippleEnableGeometry) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3LineStippleEnable);
AddRequiredFeature(vkt::Feature::stippledRectangularLines);
AddRequiredFeature(vkt::Feature::geometryShader);
RETURN_IF_SKIP(Init());
InitRenderTarget();
const char geom_src[] = R"glsl(
#version 460
layout(triangles) in;
layout(line_strip, max_vertices=2) out;
void main() {
gl_Position = vec4(1);
EmitVertex();
}
)glsl";
VkShaderObj gs(*m_device, geom_src, VK_SHADER_STAGE_GEOMETRY_BIT);
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), gs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08669");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetColorWriteMask) {
TEST_DESCRIPTION("VK_EXT_extended_dynamic_state3 dynamic state not set before drawing");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorWriteMask);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetColorWriteMaskEXT-pColorWriteMasks-parameter");
vk::CmdSetColorWriteMaskEXT(m_command_buffer, 0U, 1U, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, VertexInputDynamicStateDisabled) {
TEST_DESCRIPTION("Validate VK_EXT_vertex_input_dynamic_state VUs when disabled");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
// VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04807
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04807");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
m_command_buffer.Begin();
// VUID-vkCmdSetVertexInputEXT-None-08546
m_errorMonitor->SetDesiredError("VUID-vkCmdSetVertexInputEXT-None-08546");
vk::CmdSetVertexInputEXT(m_command_buffer, 0, nullptr, 0, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, VertexInputDynamicStateEnabled) {
TEST_DESCRIPTION("Validate VK_EXT_vertex_input_dynamic_state VUs when enabled");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::vertexInputDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
{
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_VERTEX, 1};
std::vector<VkVertexInputBindingDescription2EXT> bindings(m_device->Physical().limits_.maxVertexInputBindings + 1u,
binding);
for (uint32_t i = 0; i < bindings.size(); ++i) bindings[i].binding = i;
m_errorMonitor->SetDesiredError("VUID-vkCmdSetVertexInputEXT-vertexBindingDescriptionCount-04791");
vk::CmdSetVertexInputEXT(m_command_buffer, m_device->Physical().limits_.maxVertexInputBindings + 1u, bindings.data(), 0,
nullptr);
m_errorMonitor->VerifyFound();
}
{
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_VERTEX, 1};
VkVertexInputAttributeDescription2EXT attribute = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0};
std::vector<VkVertexInputAttributeDescription2EXT> attributes(m_device->Physical().limits_.maxVertexInputAttributes + 1u,
attribute);
for (uint32_t i = 0; i < attributes.size(); ++i) attributes[i].location = i;
m_errorMonitor->SetDesiredError("VUID-vkCmdSetVertexInputEXT-vertexAttributeDescriptionCount-04792");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, m_device->Physical().limits_.maxVertexInputAttributes + 1u,
attributes.data());
m_errorMonitor->VerifyFound();
}
{
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_VERTEX, 1};
VkVertexInputAttributeDescription2EXT attribute = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, nullptr, 0, 1, VK_FORMAT_R32G32B32A32_SFLOAT, 0};
m_errorMonitor->SetDesiredError("VUID-vkCmdSetVertexInputEXT-binding-04793");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 1, &attribute);
m_errorMonitor->VerifyFound();
}
{
VkVertexInputBindingDescription2EXT bindings[2] = {
{VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_VERTEX, 1},
{VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_VERTEX, 1}};
m_errorMonitor->SetDesiredError("VUID-vkCmdSetVertexInputEXT-pVertexBindingDescriptions-04794");
vk::CmdSetVertexInputEXT(m_command_buffer, 2, bindings, 0, nullptr);
m_errorMonitor->VerifyFound();
}
{
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_VERTEX, 1};
VkVertexInputAttributeDescription2EXT attributes[2] = {
{VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0},
{VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_FORMAT_R32G32B32A32_SFLOAT, 0}};
m_errorMonitor->SetDesiredError("VUID-vkCmdSetVertexInputEXT-pVertexAttributeDescriptions-04795");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 2, attributes);
m_errorMonitor->VerifyFound();
}
{
VkVertexInputBindingDescription2EXT binding = {VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
nullptr,
m_device->Physical().limits_.maxVertexInputBindings + 1u,
0,
VK_VERTEX_INPUT_RATE_VERTEX,
1};
m_errorMonitor->SetDesiredError("VUID-VkVertexInputBindingDescription2EXT-binding-04796");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 0, nullptr);
m_errorMonitor->VerifyFound();
}
{
VkVertexInputBindingDescription2EXT binding = {VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT,
nullptr,
0,
m_device->Physical().limits_.maxVertexInputBindingStride + 1u,
VK_VERTEX_INPUT_RATE_VERTEX,
1};
m_errorMonitor->SetDesiredError("VUID-VkVertexInputBindingDescription2EXT-stride-04797");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 0, nullptr);
m_errorMonitor->VerifyFound();
}
{
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_INSTANCE, 0};
m_errorMonitor->SetDesiredError("VUID-VkVertexInputBindingDescription2EXT-divisor-04798");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 0, nullptr);
m_errorMonitor->VerifyFound();
}
{
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_INSTANCE, 2};
m_errorMonitor->SetDesiredError("VUID-VkVertexInputBindingDescription2EXT-divisor-04799");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 0, nullptr);
m_errorMonitor->VerifyFound();
}
{
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_VERTEX, 1};
VkVertexInputAttributeDescription2EXT attribute = {VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
nullptr,
m_device->Physical().limits_.maxVertexInputAttributes + 1u,
0,
VK_FORMAT_R32G32B32A32_SFLOAT,
0};
m_errorMonitor->SetDesiredError("VUID-VkVertexInputAttributeDescription2EXT-location-06228");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 1, &attribute);
m_errorMonitor->VerifyFound();
}
{
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_VERTEX, 1};
VkVertexInputAttributeDescription2EXT attribute = {VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
nullptr,
0,
m_device->Physical().limits_.maxVertexInputBindings + 1u,
VK_FORMAT_R32G32B32A32_SFLOAT,
0};
m_errorMonitor->SetDesiredError("VUID-VkVertexInputAttributeDescription2EXT-binding-06229");
m_errorMonitor->SetDesiredError("VUID-vkCmdSetVertexInputEXT-binding-04793");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 1, &attribute);
m_errorMonitor->VerifyFound();
}
if (m_device->Physical().limits_.maxVertexInputAttributeOffset <
std::numeric_limits<decltype(m_device->Physical().limits_.maxVertexInputAttributeOffset)>::max()) {
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_VERTEX, 1};
VkVertexInputAttributeDescription2EXT attribute = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_FORMAT_R32G32B32A32_SFLOAT,
m_device->Physical().limits_.maxVertexInputAttributeOffset + 1u};
m_errorMonitor->SetDesiredError("VUID-VkVertexInputAttributeDescription2EXT-offset-06230");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 1, &attribute);
m_errorMonitor->VerifyFound();
}
{
const VkFormat format = VK_FORMAT_D16_UNORM;
VkFormatProperties format_props;
vk::GetPhysicalDeviceFormatProperties(Gpu(), format, &format_props);
if ((format_props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0) {
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_VERTEX, 1};
VkVertexInputAttributeDescription2EXT attribute = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT, nullptr, 0, 0, format, 0};
m_errorMonitor->SetDesiredError("VUID-VkVertexInputAttributeDescription2EXT-format-04805");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 1, &attribute);
m_errorMonitor->VerifyFound();
}
}
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, VertexInputDynamicStateDivisor) {
TEST_DESCRIPTION("Validate VK_EXT_vertex_input_dynamic_state VUs when VK_EXT_vertex_attribute_divisor is enabled");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::vertexInputDynamicState);
AddRequiredFeature(vkt::Feature::vertexAttributeInstanceRateDivisor);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT vertex_attribute_divisor_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(vertex_attribute_divisor_properties);
m_command_buffer.Begin();
// VUID-VkVertexInputBindingDescription2EXT-divisor-06226
if (vertex_attribute_divisor_properties.maxVertexAttribDivisor < 0xFFFFFFFFu) {
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_INSTANCE,
vertex_attribute_divisor_properties.maxVertexAttribDivisor + 1u};
m_errorMonitor->SetDesiredError("VUID-VkVertexInputBindingDescription2EXT-divisor-06226");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 0, nullptr);
m_errorMonitor->VerifyFound();
}
// VUID-VkVertexInputBindingDescription2EXT-divisor-06227
{
VkVertexInputBindingDescription2EXT binding = {
VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT, nullptr, 0, 0, VK_VERTEX_INPUT_RATE_VERTEX,
vertex_attribute_divisor_properties.maxVertexAttribDivisor};
m_errorMonitor->SetDesiredError("VUID-VkVertexInputBindingDescription2EXT-divisor-06227");
vk::CmdSetVertexInputEXT(m_command_buffer, 1, &binding, 0, nullptr);
m_errorMonitor->VerifyFound();
}
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, RasterizationSamples) {
TEST_DESCRIPTION("Make sure VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT is updating rasterizationSamples");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddOptionalExtensions(VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPipelineMultisampleStateCreateInfo ms_state_ci = vku::InitStructHelper();
ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT; // is ignored since dynamic
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe.ms_ci_ = ms_state_ci;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_4_BIT);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08644");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
// Should be valid now
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_1_BIT);
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, RasterizationSamplesMismatch) {
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::dynamicRendering);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
RETURN_IF_SKIP(Init());
InitDynamicRenderTarget();
VkFormat color_format = VK_FORMAT_B8G8R8A8_UNORM;
VkPipelineRenderingCreateInfo pipeline_rendering_ci = vku::InitStructHelper();
pipeline_rendering_ci.colorAttachmentCount = 1;
pipeline_rendering_ci.pColorAttachmentFormats = &color_format;
CreatePipelineHelper pipe(*this, &pipeline_rendering_ci);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe.gp_ci_.renderPass = VK_NULL_HANDLE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea());
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_2_BIT);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08644");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRendering();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorBlendAttchment) {
TEST_DESCRIPTION("Test all color blend attachments are dynamically set at draw time.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEnable);
RETURN_IF_SKIP(Init());
constexpr uint32_t color_attachments = 2;
InitRenderTarget(color_attachments);
std::ostringstream fsSource;
fsSource << "#version 450\n";
for (uint32_t i = 0; i < color_attachments; ++i) {
fsSource << "layout(location = " << i << ") out vec4 c" << i << ";\n";
}
fsSource << " void main() {\n";
for (uint32_t i = 0; i < color_attachments; ++i) {
fsSource << "c" << i << " = vec4(0.0f);\n";
}
fsSource << "}";
VkShaderObj fs(*m_device, fsSource.str().c_str(), VK_SHADER_STAGE_FRAGMENT_BIT);
VkPipelineColorBlendAttachmentState cb_attachments[color_attachments];
memset(cb_attachments, 0, sizeof(VkPipelineColorBlendAttachmentState) * color_attachments);
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
pipe.cb_ci_.attachmentCount = color_attachments;
pipe.cb_ci_.pAttachments = cb_attachments;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
VkBool32 color_blend_enabled[2] = {VK_FALSE, VK_FALSE};
vk::CmdSetColorBlendEnableEXT(m_command_buffer, 0, 1, &color_blend_enabled[0]);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-firstAttachment-07476");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
// all are set now so should work
vk::CmdSetColorBlendEnableEXT(m_command_buffer, 0, 2, &color_blend_enabled[0]);
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
void NegativeDynamicState::InitLineRasterizationFeatureDisabled() {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3LineRasterizationMode);
AddRequiredFeature(vkt::Feature::extendedDynamicState3LineStippleEnable);
AddRequiredFeature(vkt::Feature::rectangularLines);
AddRequiredFeature(vkt::Feature::bresenhamLines);
AddRequiredFeature(vkt::Feature::smoothLines);
RETURN_IF_SKIP(Init());
InitRenderTarget();
}
TEST_F(NegativeDynamicState, RasterizationLineModeDefault) {
TEST_DESCRIPTION("tests VK_EXT_line_rasterization dynamic state with VK_LINE_RASTERIZATION_MODE_DEFAULT");
RETURN_IF_SKIP(InitLineRasterizationFeatureDisabled());
// set both from dynamic state, don't need a VkPipelineRasterizationLineStateCreateInfo in pNext
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
pipe.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR; // ignored
pipe.line_state_ci_.stippledLineEnable = VK_TRUE; // ignored
pipe.line_state_ci_.lineStippleFactor = 1;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetLineStippleEnableEXT(m_command_buffer, VK_TRUE);
vk::CmdSetLineRasterizationModeEXT(m_command_buffer, VK_LINE_RASTERIZATION_MODE_DEFAULT);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-stippledLineEnable-07498");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
// is valid now
vk::CmdSetLineStippleEnableEXT(m_command_buffer, VK_FALSE);
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, RasterizationLineModeRectangular) {
TEST_DESCRIPTION("tests VK_EXT_line_rasterization dynamic state with VK_LINE_RASTERIZATION_MODE_RECTANGULAR");
RETURN_IF_SKIP(InitLineRasterizationFeatureDisabled());
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
pipe.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR;
pipe.line_state_ci_.stippledLineEnable = VK_TRUE; // ignored
pipe.line_state_ci_.lineStippleFactor = 1;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetLineStippleEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-stippledLineEnable-07495");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, RasterizationLineModeBresenham) {
TEST_DESCRIPTION("tests VK_EXT_line_rasterization dynamic state with VK_LINE_RASTERIZATION_MODE_BRESENHAM");
RETURN_IF_SKIP(InitLineRasterizationFeatureDisabled());
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
pipe.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM;
pipe.line_state_ci_.lineStippleFactor = 1;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetLineStippleEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-stippledLineEnable-07496");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, RasterizationLineModeSmooth) {
TEST_DESCRIPTION("tests VK_EXT_line_rasterization dynamic state with VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH");
RETURN_IF_SKIP(InitLineRasterizationFeatureDisabled());
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
pipe.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH;
pipe.line_state_ci_.lineStippleFactor = 1;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetLineStippleEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-stippledLineEnable-07497");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, PipelineColorWriteCreateInfoEXTDynaimcState3) {
TEST_DESCRIPTION("Test VkPipelineColorWriteCreateInfoEXT in color blend state pNext with VK_EXT_extended_dynamic_state3");
AddRequiredExtensions(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPipelineColorWriteCreateInfoEXT color_write = vku::InitStructHelper();
CreatePipelineHelper pipe(*this);
pipe.cb_ci_.pNext = &color_write;
m_errorMonitor->SetDesiredError("VUID-VkPipelineColorWriteCreateInfoEXT-attachmentCount-07608");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, PipelineFeatureDisabledConservativeRasterizationMode) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-extendedDynamicState3ConservativeRasterizationMode-07382");
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicState-09639");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, RasterizationConservative) {
AddRequiredExtensions(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ConservativeRasterizationMode);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicState-09639");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, MaxFragmentDualSrcAttachmentsDynamicBlendEnable) {
TEST_DESCRIPTION(
"Test drawing with dual source blending with too many fragment output attachments, but using dynamic blending.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::dualSrcBlend);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEnable);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEquation);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorWriteMask);
RETURN_IF_SKIP(Init());
const uint32_t count = m_device->Physical().limits_.maxFragmentDualSrcAttachments + 1;
if (count != 2) {
GTEST_SKIP() << "Test is designed for a maxFragmentDualSrcAttachments of 1";
}
InitRenderTarget(count);
const char *fs_src = R"glsl(
#version 460
layout(location = 0) out vec4 c0;
layout(location = 1) out vec4 c1;
void main() {
c0 = vec4(0.0f);
c1 = vec4(0.0f);
}
)glsl";
VkShaderObj fs(*m_device, fs_src, VK_SHADER_STAGE_FRAGMENT_BIT);
// This is all ignored, but checking it will be ignored
VkPipelineColorBlendAttachmentState cb_attachments = DefaultColorBlendAttachmentState();
cb_attachments.srcColorBlendFactor = VK_BLEND_FACTOR_SRC1_COLOR; // bad, but ignored
CreatePipelineHelper pipe(*this);
pipe.cb_ci_.pAttachments = &cb_attachments;
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
VkColorBlendEquationEXT dual_color_blend_equation = {
VK_BLEND_FACTOR_SRC1_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_OP_ADD,
VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_OP_ADD};
VkColorBlendEquationEXT normal_color_blend_equation = {
VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_OP_ADD,
VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_OP_ADD};
vk::CmdSetColorBlendEquationEXT(m_command_buffer, 0, 1, &dual_color_blend_equation);
vk::CmdSetColorBlendEquationEXT(m_command_buffer, 1, 1, &normal_color_blend_equation);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
// The normal blend is disabled
VkBool32 color_blend_enabled[2] = {VK_TRUE, VK_FALSE};
vk::CmdSetColorBlendEnableEXT(m_command_buffer, 0, 2, color_blend_enabled);
VkColorComponentFlags color_component_flags[2] = {VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_R_BIT};
vk::CmdSetColorWriteMaskEXT(m_command_buffer, 0, 2, color_component_flags);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-maxFragmentDualSrcAttachments-09239");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorWriteDisabled) {
TEST_DESCRIPTION("Validate VK_EXT_color_write_enable VUs when disabled");
AddRequiredExtensions(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
// VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04800
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04800");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, ColorWriteNotSet) {
TEST_DESCRIPTION("Validate dynamic state color write enable was set before draw command");
AddRequiredExtensions(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::colorWriteEnable);
// 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(2);
VkPipelineColorBlendAttachmentState color_blend[2] = {};
color_blend[0] = DefaultColorBlendAttachmentState();
color_blend[1] = DefaultColorBlendAttachmentState();
CreatePipelineHelper pipe(*this);
pipe.cb_ci_.attachmentCount = 2;
pipe.cb_ci_.pAttachments = color_blend;
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07749");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
VkBool32 color_write_enable[] = {VK_TRUE, VK_FALSE};
vk::CmdSetColorWriteEnableEXT(m_command_buffer, 1, color_write_enable);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-attachmentCount-07750");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdSetColorWriteEnableEXT(m_command_buffer, 2, color_write_enable);
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorWriteNotSet2) {
TEST_DESCRIPTION("https://gitlab.khronos.org/vulkan/vulkan/-/issues/4116");
AddRequiredExtensions(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::colorWriteEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget(2);
VkPipelineColorBlendAttachmentState color_blend[2] = {};
color_blend[0] = DefaultColorBlendAttachmentState();
color_blend[1] = DefaultColorBlendAttachmentState();
CreatePipelineHelper pipe(*this);
pipe.cb_ci_.attachmentCount = 2;
pipe.cb_ci_.pAttachments = color_blend;
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
VkBool32 color_write_enable[] = {VK_TRUE, VK_FALSE};
vk::CmdSetColorWriteEnableEXT(m_command_buffer, 2, color_write_enable);
// This second call invalidates the previous call
vk::CmdSetColorWriteEnableEXT(m_command_buffer, 1, color_write_enable);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-attachmentCount-07750");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorWriteInvalidateStaticPipeline) {
TEST_DESCRIPTION("Set the dynamic state, but then invalidate it with a static state pipeline");
AddRequiredExtensions(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::colorWriteEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe_dynamic(*this);
pipe_dynamic.AddDynamicState(VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
pipe_dynamic.CreateGraphicsPipeline();
CreatePipelineHelper pipe_static(*this);
pipe_static.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
VkBool32 color_write_enable[] = {VK_FALSE};
vk::CmdSetColorWriteEnableEXT(m_command_buffer, 1, color_write_enable);
// invalidate
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_static);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_dynamic);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07749");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorWriteEnableAttachmentCount) {
TEST_DESCRIPTION("Invalid usage of attachmentCount for vkCmdSetColorWriteEnableEXT");
AddRequiredExtensions(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::colorWriteEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
// need a valid array to index into
std::vector<VkBool32> color_write_enable(m_device->Physical().limits_.maxColorAttachments + 1, VK_TRUE);
CreatePipelineHelper helper(*this);
helper.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, helper);
// Value can't be zero
m_errorMonitor->SetDesiredError("VUID-vkCmdSetColorWriteEnableEXT-attachmentCount-arraylength");
vk::CmdSetColorWriteEnableEXT(m_command_buffer, 0, color_write_enable.data());
m_errorMonitor->VerifyFound();
// over the limit
m_errorMonitor->SetDesiredError("VUID-vkCmdSetColorWriteEnableEXT-attachmentCount-06656");
vk::CmdSetColorWriteEnableEXT(m_command_buffer, m_device->Physical().limits_.maxColorAttachments + 1,
color_write_enable.data());
m_errorMonitor->VerifyFound();
// mismatch of attachmentCount value is allowed for dynamic
// see https://gitlab.khronos.org/vulkan/vulkan/-/issues/2868
vk::CmdSetColorWriteEnableEXT(m_command_buffer, 2, color_write_enable.data());
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorWriteEnableFeature) {
TEST_DESCRIPTION("Invalid usage of vkCmdSetColorWriteEnableEXT with feature not enabled");
AddRequiredExtensions(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkBool32 color_write_enable[2] = {VK_TRUE, VK_FALSE};
CreatePipelineHelper helper(*this);
helper.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, helper);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetColorWriteEnableEXT-None-04803");
vk::CmdSetColorWriteEnableEXT(m_command_buffer, 1, color_write_enable);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DiscardRectanglesInvalidateStaticPipeline) {
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPipelineDiscardRectangleStateCreateInfoEXT discard_rect_ci = vku::InitStructHelper();
discard_rect_ci.discardRectangleMode = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT;
discard_rect_ci.discardRectangleCount = 2;
CreatePipelineHelper pipe(*this, &discard_rect_ci);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
pipe.CreateGraphicsPipeline();
CreatePipelineHelper pipe_static(*this);
pipe_static.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
VkRect2D discard_rectangles[2] = {{{0, 0}, {16, 16}}, {{0, 0}, {16, 16}}};
vk::CmdSetDiscardRectangleEXT(m_command_buffer, 0, 2, discard_rectangles);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_static);
// only fill back in the first one
vk::CmdSetDiscardRectangleEXT(m_command_buffer, 0, 1, discard_rectangles);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07751");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DiscardRectanglesNotSet) {
TEST_DESCRIPTION("Validate dynamic state for VK_EXT_discard_rectangles");
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPipelineDiscardRectangleStateCreateInfoEXT discard_rect_ci = vku::InitStructHelper();
discard_rect_ci.discardRectangleMode = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT;
discard_rect_ci.discardRectangleCount = 4;
CreatePipelineHelper pipe(*this, &discard_rect_ci);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07751");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
// only fill in [0, 1, 3] index
VkRect2D discard_rectangles[2] = {{{0, 0}, {16, 16}}, {{0, 0}, {16, 16}}};
vk::CmdSetDiscardRectangleEXT(m_command_buffer, 0, 2, discard_rectangles);
vk::CmdSetDiscardRectangleEXT(m_command_buffer, 3, 1, discard_rectangles);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07751");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DiscardRectanglesNotSetMaxDiscardRectangles) {
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceDiscardRectanglePropertiesEXT discard_rectangle_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(discard_rectangle_properties);
std::vector<VkRect2D> discard_rectangles(discard_rectangle_properties.maxDiscardRectangles);
if (discard_rectangle_properties.maxDiscardRectangles < 2) {
GTEST_SKIP() << "maxDiscardRectangles too small";
}
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
// VkPipelineDiscardRectangleStateCreateInfoEXT is not used now
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetDiscardRectangleEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-rasterizerDiscardEnable-09236");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdSetDiscardRectangleEXT(m_command_buffer, 0, discard_rectangles.size() - 1, discard_rectangles.data());
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-rasterizerDiscardEnable-09236");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DiscardRectanglesEnableNotSet) {
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
if (!DeviceExtensionSupported(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME, 2)) {
GTEST_SKIP() << "need VK_EXT_discard_rectangles version 2";
}
InitRenderTarget();
VkRect2D discard_rectangle = {{0, 0}, {16, 16}};
VkPipelineDiscardRectangleStateCreateInfoEXT discard_rect_ci = vku::InitStructHelper();
discard_rect_ci.discardRectangleMode = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT;
discard_rect_ci.discardRectangleCount = 1;
discard_rect_ci.pDiscardRectangles = &discard_rectangle;
CreatePipelineHelper pipe(*this, &discard_rect_ci);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07880");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DiscardRectanglesModeNotSet) {
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
if (!DeviceExtensionSupported(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME, 2)) {
GTEST_SKIP() << "need VK_EXT_discard_rectangles version 2";
}
InitRenderTarget();
VkRect2D discard_rectangle = {{0, 0}, {16, 16}};
VkPipelineDiscardRectangleStateCreateInfoEXT discard_rect_ci = vku::InitStructHelper();
discard_rect_ci.discardRectangleCount = 1;
discard_rect_ci.pDiscardRectangles = &discard_rectangle;
CreatePipelineHelper pipe(*this, &discard_rect_ci);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetDiscardRectangleEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07881");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, StateNotSetWithCommandBufferResetBitmask) {
TEST_DESCRIPTION("Make sure state tracker of dynamic state accounts for resetting command buffers");
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPipelineDiscardRectangleStateCreateInfoEXT discard_rect_ci = vku::InitStructHelper();
discard_rect_ci.discardRectangleMode = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT;
discard_rect_ci.discardRectangleCount = 1;
CreatePipelineHelper pipe(*this, &discard_rect_ci);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
pipe.CreateGraphicsPipeline();
VkRect2D discard_rectangles = {{0, 0}, {16, 16}};
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetDiscardRectangleEXT(m_command_buffer, 0, 1, &discard_rectangles);
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
// The dynamic state was not set for this lifetime of this command buffer
// implicitly via vkBeginCommandBuffer
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07751");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
// set again for this command buffer
vk::CmdSetDiscardRectangleEXT(m_command_buffer, 0, 1, &discard_rectangles);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
// reset command buffer from the pool
vk::ResetCommandPool(device(), m_command_pool, 0);
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07751");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, StateNotSetWithCommandBufferReset) {
TEST_DESCRIPTION("Make sure state tracker of dynamic state accounts for resetting command buffers");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceSampleLocationsPropertiesEXT sample_locations_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(sample_locations_props);
if ((sample_locations_props.sampleLocationSampleCounts & VK_SAMPLE_COUNT_1_BIT) == 0) {
GTEST_SKIP() << "Required sample location sample count VK_SAMPLE_COUNT_1_BIT not supported";
}
VkSampleLocationEXT sample_location = {0.5f, 0.5f};
VkSampleLocationsInfoEXT sample_locations_info = vku::InitStructHelper();
sample_locations_info.sampleLocationsPerPixel = VK_SAMPLE_COUNT_1_BIT;
sample_locations_info.sampleLocationGridSize = {1u, 1u};
sample_locations_info.sampleLocationsCount = 1;
sample_locations_info.pSampleLocations = &sample_location;
VkPipelineSampleLocationsStateCreateInfoEXT sample_location_state = vku::InitStructHelper();
sample_location_state.sampleLocationsEnable = VK_TRUE;
sample_location_state.sampleLocationsInfo = sample_locations_info; // ignored
VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = vku::InitStructHelper(&sample_location_state);
pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
pipe_ms_state_ci.sampleShadingEnable = 0;
pipe_ms_state_ci.minSampleShading = 1.0;
pipe_ms_state_ci.pSampleMask = nullptr;
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
pipe.ms_ci_ = pipe_ms_state_ci;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sample_locations_info);
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
// The dynamic state was not set for this lifetime of this command buffer
// implicitly via vkBeginCommandBuffer
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-06666");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
// set again for this command buffer
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sample_locations_info);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
// reset command buffer from the pool
vk::ResetCommandPool(device(), m_command_pool, 0);
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-06666");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SampleLocations) {
TEST_DESCRIPTION("Test invalid cases of VK_EXT_sample_location");
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceSampleLocationsPropertiesEXT sample_locations_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(sample_locations_props);
if ((sample_locations_props.sampleLocationSampleCounts & VK_SAMPLE_COUNT_1_BIT) == 0) {
GTEST_SKIP() << "VK_SAMPLE_COUNT_1_BIT sampleLocationSampleCounts is not supported";
}
const bool support_64_sample_count = ((sample_locations_props.sampleLocationSampleCounts & VK_SAMPLE_COUNT_64_BIT) != 0);
VkImageCreateInfo image_create_info = vku::InitStructHelper();
image_create_info.imageType = VK_IMAGE_TYPE_2D;
image_create_info.extent = {128, 128, 1};
image_create_info.mipLevels = 1;
image_create_info.arrayLayers = 1;
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_create_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
// If S8_UINT is supported, check not having depth with sample location compatible bit
VkFormatProperties format_properties;
vk::GetPhysicalDeviceFormatProperties(Gpu(), VK_FORMAT_S8_UINT, &format_properties);
if ((format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0) {
image_create_info.flags = VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT;
image_create_info.format = VK_FORMAT_S8_UINT;
CreateImageTest(image_create_info, "VUID-VkImageCreateInfo-flags-01533");
}
const VkFormat depth_format = FindSupportedDepthStencilFormat(Gpu());
image_create_info.flags = 0; // image will not have needed flag
image_create_info.format = depth_format;
vkt::Image depth_image(*m_device, image_create_info, vkt::set_layout);
vkt::Image color_image(*m_device, 128, 128, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
rp.AddAttachmentDescription(depth_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
rp.AddAttachmentReference({1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL});
rp.AddColorAttachment(0);
rp.AddDepthStencilAttachment(1);
rp.CreateRenderPass();
// Create a framebuffer
vkt::ImageView color_view = color_image.CreateView();
vkt::ImageView depth_view = depth_image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT);
const std::array<VkImageView, 2> attachments = {color_view, depth_view};
vkt::Framebuffer fb(*m_device, rp, static_cast<uint32_t>(attachments.size()), attachments.data(), 128, 128);
VkMultisamplePropertiesEXT multisample_prop = vku::InitStructHelper();
vk::GetPhysicalDeviceMultisamplePropertiesEXT(Gpu(), VK_SAMPLE_COUNT_1_BIT, &multisample_prop);
// 1 from VK_SAMPLE_COUNT_1_BIT
const uint32_t valid_count =
multisample_prop.maxSampleLocationGridSize.width * multisample_prop.maxSampleLocationGridSize.height * 1;
if (valid_count <= 1) {
GTEST_SKIP() << "Need a maxSampleLocationGridSize width x height greater than 1";
}
std::vector<VkSampleLocationEXT> sample_location(valid_count, {0.5, 0.5});
VkSampleLocationsInfoEXT sample_locations_info = vku::InitStructHelper();
sample_locations_info.sampleLocationsPerPixel = VK_SAMPLE_COUNT_1_BIT;
sample_locations_info.sampleLocationGridSize = multisample_prop.maxSampleLocationGridSize;
sample_locations_info.sampleLocationsCount = valid_count;
sample_locations_info.pSampleLocations = sample_location.data();
VkPipelineSampleLocationsStateCreateInfoEXT sample_location_state = vku::InitStructHelper();
sample_location_state.sampleLocationsEnable = VK_TRUE;
sample_location_state.sampleLocationsInfo = sample_locations_info;
VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = vku::InitStructHelper(&sample_location_state);
pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
pipe_ms_state_ci.sampleShadingEnable = 0;
pipe_ms_state_ci.minSampleShading = 1.0;
pipe_ms_state_ci.pSampleMask = nullptr;
VkPipelineDepthStencilStateCreateInfo pipe_ds_state_ci = vku::InitStructHelper();
pipe_ds_state_ci.depthTestEnable = VK_TRUE;
pipe_ds_state_ci.stencilTestEnable = VK_FALSE;
{
CreatePipelineHelper pipe(*this);
pipe.ms_ci_ = pipe_ms_state_ci;
pipe.gp_ci_.renderPass = rp;
pipe.gp_ci_.pDepthStencilState = &pipe_ds_state_ci;
// Set invalid grid size width
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.width =
multisample_prop.maxSampleLocationGridSize.width + 1;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-07610");
m_errorMonitor->SetDesiredError("VUID-VkSampleLocationsInfoEXT-sampleLocationsCount-01527");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.width = multisample_prop.maxSampleLocationGridSize.width;
// Set invalid grid size height
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.height =
multisample_prop.maxSampleLocationGridSize.height + 1;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-07611");
m_errorMonitor->SetDesiredError("VUID-VkSampleLocationsInfoEXT-sampleLocationsCount-01527");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.height = multisample_prop.maxSampleLocationGridSize.height;
// Test to make sure the modulo is correct due to akward wording in spec
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.height =
multisample_prop.maxSampleLocationGridSize.height * 2;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-07611");
m_errorMonitor->SetDesiredError("VUID-VkSampleLocationsInfoEXT-sampleLocationsCount-01527");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.height = multisample_prop.maxSampleLocationGridSize.height;
if (multisample_prop.maxSampleLocationGridSize.height > 1) {
// Expects there to be no 07611 vuid
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.height =
multisample_prop.maxSampleLocationGridSize.height / 2;
m_errorMonitor->SetDesiredError("VUID-VkSampleLocationsInfoEXT-sampleLocationsCount-01527");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.height =
multisample_prop.maxSampleLocationGridSize.height;
}
// non-matching rasterizationSamples
pipe.ms_ci_.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-07612");
// if grid size is different
m_errorMonitor->SetUnexpectedError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-07610");
m_errorMonitor->SetUnexpectedError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-07611");
m_errorMonitor->SetUnexpectedError("VUID-VkGraphicsPipelineCreateInfo-multisampledRenderToSingleSampled-06853");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
pipe.ms_ci_.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
}
// Creates valid pipelines with dynamic state
CreatePipelineHelper dynamic_pipe(*this);
dynamic_pipe.ms_ci_ = pipe_ms_state_ci;
dynamic_pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
dynamic_pipe.gp_ci_.renderPass = rp;
dynamic_pipe.gp_ci_.pDepthStencilState = &pipe_ds_state_ci;
dynamic_pipe.CreateGraphicsPipeline();
vkt::Buffer vbo(*m_device, sizeof(float) * 3, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, fb, 128, 128);
vk::CmdBindVertexBuffers(m_command_buffer, 1, 1, &vbo.handle(), &kZeroDeviceSize);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, dynamic_pipe);
// test trying to use unsupported sample count
if (support_64_sample_count == false) {
sample_locations_info.sampleLocationsPerPixel = VK_SAMPLE_COUNT_64_BIT;
sample_locations_info.sampleLocationsCount = valid_count * 64;
m_errorMonitor->SetDesiredError("VUID-VkSampleLocationsInfoEXT-sampleLocationsPerPixel-01526");
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sample_locations_info);
m_errorMonitor->VerifyFound();
sample_locations_info.sampleLocationsPerPixel = VK_SAMPLE_COUNT_1_BIT;
sample_locations_info.sampleLocationsCount = valid_count;
}
// Test invalid sample location count
sample_locations_info.sampleLocationsCount = valid_count + 1;
m_errorMonitor->SetDesiredError("VUID-VkSampleLocationsInfoEXT-sampleLocationsCount-01527");
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sample_locations_info);
m_errorMonitor->VerifyFound();
sample_locations_info.sampleLocationsCount = valid_count;
// Test image was never created with VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sample_locations_info);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsEnable-02689");
vk::CmdDraw(m_command_buffer, 1, 0, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SetViewportParam) {
TEST_DESCRIPTION("Test parameters of vkCmdSetViewport without multiViewport feature");
SetTargetApiVersion(VK_API_VERSION_1_1);
VkPhysicalDeviceFeatures features{};
RETURN_IF_SKIP(Init(&features));
const VkViewport vp = {0.0, 0.0, 64.0, 64.0, 0.0, 1.0};
const VkViewport viewports[] = {vp, vp};
m_command_buffer.Begin();
// array tests
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-firstViewport-01224");
vk::CmdSetViewport(m_command_buffer, 1, 1, viewports);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-viewportCount-arraylength");
vk::CmdSetViewport(m_command_buffer, 0, 0, nullptr);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-viewportCount-01225");
vk::CmdSetViewport(m_command_buffer, 0, 2, viewports);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-firstViewport-01224");
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-viewportCount-01225");
vk::CmdSetViewport(m_command_buffer, 1, 2, viewports);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-pViewports-parameter");
vk::CmdSetViewport(m_command_buffer, 0, 1, nullptr);
m_errorMonitor->VerifyFound();
// core viewport tests
struct TestCase {
VkViewport vp;
std::string vuid;
};
// not necessarily boundary values (unspecified cast rounding), but guaranteed to be over limit
const auto one_past_max_w = NearestGreater(static_cast<float>(m_device->Physical().limits_.maxViewportDimensions[0]));
const auto one_past_max_h = NearestGreater(static_cast<float>(m_device->Physical().limits_.maxViewportDimensions[1]));
const float min_bound = m_device->Physical().limits_.viewportBoundsRange[0];
const float max_bound = m_device->Physical().limits_.viewportBoundsRange[1];
const float one_before_min_bounds = NearestSmaller(min_bound);
const float one_past_max_bounds = NearestGreater(max_bound);
const float below_zero = NearestSmaller(0.0f);
const float past_one = NearestGreater(1.0f);
std::vector<TestCase> test_cases = {
{{0.0, 0.0, 0.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-width-01770"},
{{0.0, 0.0, one_past_max_w, 64.0, 0.0, 1.0}, "VUID-VkViewport-width-01771"},
{{0.0, 0.0, NAN, 64.0, 0.0, 1.0}, "VUID-VkViewport-width-01770"},
{{0.0, 0.0, 64.0, one_past_max_h, 0.0, 1.0}, "VUID-VkViewport-height-01773"},
{{one_before_min_bounds, 0.0, 64.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-x-01774"},
{{one_past_max_bounds, 0.0, 64.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-x-01232"},
{{NAN, 0.0, 64.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-x-01774"},
{{0.0, one_before_min_bounds, 64.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-y-01775"},
{{0.0, NAN, 64.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-y-01775"},
{{max_bound, 0.0, 1.0, 64.0, 0.0, 1.0}, "VUID-VkViewport-x-01232"},
{{0.0, max_bound, 64.0, 1.0, 0.0, 1.0}, "VUID-VkViewport-y-01233"},
{{0.0, 0.0, 64.0, 64.0, below_zero, 1.0}, "VUID-VkViewport-minDepth-01234"},
{{0.0, 0.0, 64.0, 64.0, past_one, 1.0}, "VUID-VkViewport-minDepth-01234"},
{{0.0, 0.0, 64.0, 64.0, NAN, 1.0}, "VUID-VkViewport-minDepth-01234"},
{{0.0, 0.0, 64.0, 64.0, 0.0, below_zero}, "VUID-VkViewport-maxDepth-01235"},
{{0.0, 0.0, 64.0, 64.0, 0.0, past_one}, "VUID-VkViewport-maxDepth-01235"},
{{0.0, 0.0, 64.0, 64.0, 0.0, NAN}, "VUID-VkViewport-maxDepth-01235"},
};
if (DeviceValidationVersion() < VK_API_VERSION_1_1) {
test_cases.push_back({{0.0, 0.0, 64.0, 0.0, 0.0, 1.0}, "VUID-VkViewport-apiVersion-07917"});
test_cases.push_back({{0.0, 0.0, 64.0, NAN, 0.0, 1.0}, "VUID-VkViewport-apiVersion-07917"});
} else {
test_cases.push_back({{0.0, 0.0, 64.0, NAN, 0.0, 1.0}, "VUID-VkViewport-height-01773"});
}
for (const auto &test_case : test_cases) {
m_errorMonitor->SetDesiredError(test_case.vuid.c_str());
vk::CmdSetViewport(m_command_buffer, 0, 1, &test_case.vp);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDynamicState, SetViewportParamMaintenance1) {
TEST_DESCRIPTION("Verify errors are detected on misuse of SetViewport with a negative viewport extension enabled.");
AddRequiredExtensions(VK_KHR_MAINTENANCE_1_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
const auto &limits = m_device->Physical().limits_;
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-VkViewport-height-01773");
// not necessarily boundary values (unspecified cast rounding), but guaranteed to be over limit
const float one_before_min_h = NearestSmaller(-static_cast<float>(limits.maxViewportDimensions[1]));
VkViewport viewport = {0.0, 0.0, 64.0, one_before_min_h, 0.0, 1.0};
vk::CmdSetViewport(m_command_buffer, 0, 1, &viewport);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkViewport-height-01773");
const float one_past_max_h = NearestGreater(static_cast<float>(limits.maxViewportDimensions[1]));
viewport = {0.0, 0.0, 64.0, one_past_max_h, 0.0, 1.0};
vk::CmdSetViewport(m_command_buffer, 0, 1, &viewport);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkViewport-height-01773");
viewport = {0.0, 0.0, 64.0, NAN, 0.0, 1.0};
vk::CmdSetViewport(m_command_buffer, 0, 1, &viewport);
m_errorMonitor->VerifyFound();
const float min_bound = limits.viewportBoundsRange[0];
const float max_bound = limits.viewportBoundsRange[1];
const float one_before_min_bound = NearestSmaller(min_bound);
const float one_past_max_bound = NearestGreater(max_bound);
m_errorMonitor->SetDesiredError("VUID-VkViewport-y-01775");
viewport = {0.0, one_before_min_bound, 64.0, 1.0, 0.0, 1.0};
vk::CmdSetViewport(m_command_buffer, 0, 1, &viewport);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkViewport-y-01776");
viewport = {0.0, one_past_max_bound, 64.0, -1.0, 0.0, 1.0};
vk::CmdSetViewport(m_command_buffer, 0, 1, &viewport);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkViewport-y-01777");
viewport = {0.0, min_bound, 64.0, -1.0, 0.0, 1.0};
vk::CmdSetViewport(m_command_buffer, 0, 1, &viewport);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-VkViewport-y-01233");
viewport = {0.0, max_bound, 64.0, 1.0, 0.0, 1.0};
vk::CmdSetViewport(m_command_buffer, 0, 1, &viewport);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, SetViewportParamMultiviewport) {
TEST_DESCRIPTION("Test parameters of vkCmdSetViewport with multiViewport feature enabled");
AddRequiredFeature(vkt::Feature::multiViewport);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-viewportCount-arraylength");
vk::CmdSetViewport(m_command_buffer, 0, 0, nullptr);
m_errorMonitor->VerifyFound();
const auto max_viewports = m_device->Physical().limits_.maxViewports;
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-pViewports-parameter");
vk::CmdSetViewport(m_command_buffer, 0, max_viewports, nullptr);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, SetViewportParamMultiviewportLimit) {
TEST_DESCRIPTION("Test parameters of vkCmdSetViewport with multiViewport feature enabled");
AddRequiredFeature(vkt::Feature::multiViewport);
RETURN_IF_SKIP(Init());
const auto max_viewports = m_device->Physical().limits_.maxViewports;
const uint32_t too_big_max_viewports = 65536 + 1; // let's say this is too much to allocate
if (max_viewports >= too_big_max_viewports) {
GTEST_SKIP() << "maxViewports is too large to practically test against";
}
m_command_buffer.Begin();
const VkViewport vp = {0.0, 0.0, 64.0, 64.0, 0.0, 1.0};
const std::vector<VkViewport> viewports(max_viewports + 1, vp);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-firstViewport-01223");
vk::CmdSetViewport(m_command_buffer, 0, max_viewports + 1, viewports.data());
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-firstViewport-01223");
vk::CmdSetViewport(m_command_buffer, max_viewports, 1, viewports.data());
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-firstViewport-01223");
vk::CmdSetViewport(m_command_buffer, 1, max_viewports, viewports.data());
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetViewport-viewportCount-arraylength");
vk::CmdSetViewport(m_command_buffer, 1, 0, viewports.data());
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, CmdSetDiscardRectangleEXTOffsets) {
TEST_DESCRIPTION("Test CmdSetDiscardRectangleEXT with invalid offsets in pDiscardRectangles");
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceDiscardRectanglePropertiesEXT discard_rectangle_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(discard_rectangle_properties);
if (discard_rectangle_properties.maxDiscardRectangles == 0) {
GTEST_SKIP() << "Discard rectangles are not supported";
}
VkRect2D discard_rectangles = {};
discard_rectangles.offset = {-1, 0};
discard_rectangles.extent = {64, 64};
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDiscardRectangleEXT-x-00587");
vk::CmdSetDiscardRectangleEXT(m_command_buffer, 0, 1, &discard_rectangles);
m_errorMonitor->VerifyFound();
discard_rectangles.offset.x = 0;
discard_rectangles.offset.y = -32;
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDiscardRectangleEXT-x-00587");
vk::CmdSetDiscardRectangleEXT(m_command_buffer, 0, 1, &discard_rectangles);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, CmdSetDiscardRectangleEXTRectangleCountOverflow) {
TEST_DESCRIPTION("Test CmdSetDiscardRectangleEXT with invalid offsets in pDiscardRectangles");
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkRect2D discard_rectangles = {};
discard_rectangles.offset = {1, 0};
discard_rectangles.extent = {vvl::kU32Max, 64};
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDiscardRectangleEXT-offset-00588");
vk::CmdSetDiscardRectangleEXT(m_command_buffer, 0, 1, &discard_rectangles);
m_errorMonitor->VerifyFound();
discard_rectangles.offset = {0, vvl::kI32Max};
discard_rectangles.extent = {64, 1};
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDiscardRectangleEXT-offset-00589");
vk::CmdSetDiscardRectangleEXT(m_command_buffer, 0, 1, &discard_rectangles);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, CmdSetDiscardRectangleEXTRectangleCount) {
TEST_DESCRIPTION("Test CmdSetDiscardRectangleEXT with invalid offsets in pDiscardRectangles");
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceDiscardRectanglePropertiesEXT discard_rectangle_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(discard_rectangle_properties);
VkRect2D discard_rectangles = {};
discard_rectangles.offset = {0, 0};
discard_rectangles.extent = {64, 64};
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDiscardRectangleEXT-firstDiscardRectangle-00585");
vk::CmdSetDiscardRectangleEXT(m_command_buffer, discard_rectangle_properties.maxDiscardRectangles, 1, &discard_rectangles);
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, DiscardRectanglesVersion) {
TEST_DESCRIPTION("check version of VK_EXT_discard_rectangles");
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
if (DeviceExtensionSupported(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME, 2)) {
GTEST_SKIP() << "need VK_EXT_discard_rectangles version 1";
}
InitRenderTarget();
const VkDynamicState dyn_states[] = {VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT};
VkPipelineDynamicStateCreateInfo dyn_state_ci = vku::InitStructHelper();
dyn_state_ci.dynamicStateCount = size32(dyn_states);
dyn_state_ci.pDynamicStates = dyn_states;
CreatePipelineHelper pipe(*this);
pipe.dyn_state_ci_ = dyn_state_ci;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-07855");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
pipe.dyn_state_ci_.dynamicStateCount = 0;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDiscardRectangleEnableEXT-specVersion-07851");
vk::CmdSetDiscardRectangleEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
// Not possible to hit the desired failure messages given invalid enums.
TEST_F(NegativeDynamicState, ExtensionNotEnabled) {
TEST_DESCRIPTION("Create a graphics pipeline with Extension dynamic states without enabling the required Extensions.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
m_errorMonitor->SetDesiredError("VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-parameter", 3);
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, ViewportAndScissorUndefinedDrawState) {
TEST_DESCRIPTION("Test viewport and scissor dynamic state that is not set before draw");
// TODO: should also test on !multiViewport
AddRequiredFeature(vkt::Feature::multiViewport);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkViewport viewport = {0, 0, 16, 16, 0, 1};
VkRect2D scissor = {{0, 0}, {16, 16}};
CreatePipelineHelper pipeline_dyn_vp(*this);
pipeline_dyn_vp.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
pipeline_dyn_vp.CreateGraphicsPipeline();
CreatePipelineHelper pipeline_dyn_sc(*this);
pipeline_dyn_sc.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR);
pipeline_dyn_sc.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07831");
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_dyn_vp);
vk::CmdSetViewport(m_command_buffer, 1, 1, &viewport);
vk::CmdDraw(m_command_buffer, 1, 0, 0, 0);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07832");
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_dyn_sc);
vk::CmdSetScissor(m_command_buffer, 1, 1, &scissor);
vk::CmdDraw(m_command_buffer, 1, 0, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, Duplicate) {
TEST_DESCRIPTION("Create a pipeline with duplicate dynamic states set.");
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkDynamicState dynamic_states[4] = {VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE};
CreatePipelineHelper pipe(*this);
pipe.dyn_state_ci_ = vku::InitStructHelper();
pipe.dyn_state_ci_.flags = 0;
pipe.dyn_state_ci_.dynamicStateCount = 4;
pipe.dyn_state_ci_.pDynamicStates = dynamic_states;
m_errorMonitor->SetDesiredError("VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
// Should error twice since 2 sets of duplicates now
dynamic_states[3] = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK;
m_errorMonitor->SetDesiredError("VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442");
m_errorMonitor->SetDesiredError("VUID-VkPipelineDynamicStateCreateInfo-pDynamicStates-01442");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, NonGraphics) {
TEST_DESCRIPTION("Create a pipeline with non graphics dynamic states set.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR);
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-03578");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, ViewportCountWithExtendedDynamicState) {
TEST_DESCRIPTION("Create a pipeline with invalid viewport count with extended dynamic state.");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkDynamicState dynamic_state = VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT;
CreatePipelineHelper pipe(*this);
pipe.dyn_state_ci_ = vku::InitStructHelper();
pipe.dyn_state_ci_.dynamicStateCount = 1;
pipe.dyn_state_ci_.pDynamicStates = &dynamic_state;
pipe.vp_state_ci_.viewportCount = 1;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-03379");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
pipe.dyn_state_ci_.dynamicStateCount = 0;
pipe.vp_state_ci_.viewportCount = 0;
m_errorMonitor->SetDesiredError("VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134");
m_errorMonitor->SetDesiredError("VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, PipelineColorBlendStateCreateInfoArrayNonDynamic) {
TEST_DESCRIPTION("Validate VkPipelineColorBlendStateCreateInfo array with no extensions");
RETURN_IF_SKIP(Init());
InitRenderTarget();
const auto set_info = [](CreatePipelineHelper &helper) { helper.cb_ci_.pAttachments = nullptr; };
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-07353");
}
TEST_F(NegativeDynamicState, PipelineColorBlendStateCreateInfoArrayDynamic) {
TEST_DESCRIPTION("Validate VkPipelineColorBlendStateCreateInfo array with VK_EXT_extended_dynamic_state3");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEnable);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEquation);
RETURN_IF_SKIP(Init());
InitRenderTarget();
{
const auto set_info = [](CreatePipelineHelper &helper) { helper.cb_ci_.pAttachments = nullptr; };
CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit,
"VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-07353");
}
// invalid if using only some dynamic state
{
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
pipe.cb_ci_.pAttachments = nullptr;
m_errorMonitor->SetDesiredError("VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-07353");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDynamicState, SettingCommands) {
TEST_DESCRIPTION("Verify if pipeline doesn't setup dynamic state, but set dynamic commands");
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
VkViewport viewport = {0, 0, 16, 16, 0, 1};
vk::CmdSetViewport(m_command_buffer, 0, 1, &viewport);
VkRect2D scissor = {{0, 0}, {16, 16}};
vk::CmdSetScissor(m_command_buffer, 0, 1, &scissor);
vk::CmdSetLineWidth(m_command_buffer, 1);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08608");
vk::CmdDraw(m_command_buffer, 1, 0, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
void NegativeDynamicState::ExtendedDynamicStateDrawNotSet(VkDynamicState dynamic_state, const char *vuid) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(dynamic_state);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError(vuid);
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetCullMode) {
ExtendedDynamicStateDrawNotSet(VK_DYNAMIC_STATE_CULL_MODE, "VUID-vkCmdDraw-None-07840");
}
TEST_F(NegativeDynamicState, DrawNotSetFrontFace) {
ExtendedDynamicStateDrawNotSet(VK_DYNAMIC_STATE_FRONT_FACE, "VUID-vkCmdDraw-None-07841");
}
TEST_F(NegativeDynamicState, DrawNotSetPrimitiveTopology) {
ExtendedDynamicStateDrawNotSet(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY, "VUID-vkCmdDraw-None-07842");
}
TEST_F(NegativeDynamicState, DrawNotSetDepthTestEnable) {
ExtendedDynamicStateDrawNotSet(VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE, "VUID-vkCmdDraw-None-07843");
}
TEST_F(NegativeDynamicState, DrawNotSetDepthBoundsTestEnable) {
AddRequiredFeature(vkt::Feature::depthBounds);
ExtendedDynamicStateDrawNotSet(VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE, "VUID-vkCmdDraw-None-07846");
}
TEST_F(NegativeDynamicState, DrawNotSetStencilTestEnable) {
ExtendedDynamicStateDrawNotSet(VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE, "VUID-vkCmdDraw-None-07847");
}
TEST_F(NegativeDynamicState, DrawNotSetStencilOp) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
m_depth_stencil_fmt = FindSupportedDepthStencilFormat(Gpu());
vkt::Image depth_image(*m_device, m_width, m_height, m_depth_stencil_fmt, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkt::ImageView depth_image_view = depth_image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
InitRenderTarget(1, &depth_image_view.handle());
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_OP);
pipe.ds_ci_ = vku::InitStructHelper();
pipe.ds_ci_.stencilTestEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07848");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DepthRangeUnrestricted) {
TEST_DESCRIPTION("Test setting minDepthBounds and maxDepthBounds without VK_EXT_depth_range_unrestricted");
// Extension doesn't have feature bit, so not enabling extension invokes restrictions
AddRequiredFeature(vkt::Feature::depthBounds);
RETURN_IF_SKIP(Init());
// Need to set format framework uses for InitRenderTarget
m_depth_stencil_fmt = FindSupportedDepthStencilFormat(Gpu());
m_depthStencil->Init(*m_device, m_width, m_height, 1, m_depth_stencil_fmt,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vkt::ImageView depth_image_view = m_depthStencil->CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
InitRenderTarget(&depth_image_view.handle());
VkPipelineDepthStencilStateCreateInfo ds_ci = vku::InitStructHelper();
ds_ci.depthTestEnable = VK_TRUE;
ds_ci.depthBoundsTestEnable = VK_TRUE;
CreatePipelineHelper pipe(*this);
pipe.ds_ci_ = ds_ci;
pipe.ds_ci_.minDepthBounds = 1.5f;
pipe.ds_ci_.maxDepthBounds = 1.0f;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-02510");
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-10913");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
pipe.ds_ci_.minDepthBounds = 1.0f;
pipe.ds_ci_.maxDepthBounds = 1.5f;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-02510");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
pipe.ds_ci_.minDepthBounds = 0.6f;
pipe.ds_ci_.maxDepthBounds = 0.4f;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-10913");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
// Add dynamic depth stencil state instead
pipe.ds_ci_.minDepthBounds = 0.0f;
pipe.ds_ci_.maxDepthBounds = 0.0f;
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthBounds-minDepthBounds-00600");
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthBounds-minDepthBounds-10912");
vk::CmdSetDepthBounds(m_command_buffer, 1.5f, 0.0f);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthBounds-maxDepthBounds-00601");
vk::CmdSetDepthBounds(m_command_buffer, 0.0f, 1.5f);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthBounds-minDepthBounds-10912");
vk::CmdSetDepthBounds(m_command_buffer, 0.5f, 0.45f);
m_errorMonitor->VerifyFound();
vk::CmdSetDepthBounds(m_command_buffer, 1.0f, 1.0f);
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DepthBoundsTestEnableState) {
TEST_DESCRIPTION("Dynamically set depthBoundsTestEnable and not call vkCmdSetDepthBounds before the draw");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::depthBounds);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
// Need to set format framework uses for InitRenderTarget
m_depth_stencil_fmt = FindSupportedDepthStencilFormat(Gpu());
m_depthStencil->Init(*m_device, m_width, m_height, 1, m_depth_stencil_fmt,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
vkt::ImageView depth_image_view = m_depthStencil->CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
InitRenderTarget(&depth_image_view.handle());
CreatePipelineHelper pipe(*this);
pipe.ds_ci_ = vku::InitStructHelper();
pipe.ds_ci_.depthTestEnable = VK_FALSE; // ignored
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetDepthBoundsTestEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07836");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_command_buffer.EndRenderPass();
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ViewportStateIgnored) {
TEST_DESCRIPTION("Ignore null pViewportState");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.rs_state_ci_.rasterizerDiscardEnable = VK_FALSE;
pipe.gp_ci_.pViewportState = nullptr;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-09024");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
// missing VK_EXT_extended_dynamic_state3
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-09024");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, Viewport) {
TEST_DESCRIPTION("Test VkPipelineViewportStateCreateInfo viewport and scissor count validation for non-multiViewport");
RETURN_IF_SKIP(Init());
InitRenderTarget();
if (m_device->Physical().limits_.maxViewports < 3) {
GTEST_SKIP() << "maxViewports is not large enough";
}
VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f};
VkViewport viewports[] = {viewport, viewport};
VkRect2D scissor = {{0, 0}, {64, 64}};
VkRect2D scissors[] = {scissor, scissor};
// test viewport and scissor arrays
struct TestCase {
uint32_t viewport_count;
VkViewport *viewports;
uint32_t scissor_count;
VkRect2D *scissors;
std::vector<std::string> vuids;
};
std::vector<TestCase> dyn_test_cases = {
{0,
viewports,
1,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}},
{2,
viewports,
1,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}},
{1,
viewports,
0,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}},
{1,
viewports,
2,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}},
{2,
viewports,
2,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}},
{2,
viewports,
2,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}},
{0,
viewports,
2,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}},
{2,
viewports,
0,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136", "VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}},
{2,
nullptr,
3,
nullptr,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}},
{0,
nullptr,
0,
nullptr,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136"}},
};
const VkDynamicState dyn_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
for (const auto &test_case : dyn_test_cases) {
const auto break_vp = [&](CreatePipelineHelper &helper) {
VkPipelineDynamicStateCreateInfo dyn_state_ci = vku::InitStructHelper();
dyn_state_ci.dynamicStateCount = size32(dyn_states);
dyn_state_ci.pDynamicStates = dyn_states;
helper.dyn_state_ci_ = dyn_state_ci;
helper.vp_state_ci_.viewportCount = test_case.viewport_count;
helper.vp_state_ci_.pViewports = test_case.viewports;
helper.vp_state_ci_.scissorCount = test_case.scissor_count;
helper.vp_state_ci_.pScissors = test_case.scissors;
};
CreatePipelineHelper::OneshotTest(*this, break_vp, kErrorBit, test_case.vuids);
}
}
TEST_F(NegativeDynamicState, MultiViewport) {
TEST_DESCRIPTION("Test VkPipelineViewportStateCreateInfo viewport and scissor count validation for multiViewport feature");
AddRequiredFeature(vkt::Feature::multiViewport);
RETURN_IF_SKIP(Init()); // enables all supported features
// at least 16 viewports supported from here on
InitRenderTarget();
VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f};
VkViewport viewports[] = {viewport, viewport};
VkRect2D scissor = {{0, 0}, {64, 64}};
VkRect2D scissors[] = {scissor, scissor};
struct TestCase {
uint32_t viewport_count;
VkViewport *viewports;
uint32_t scissor_count;
VkRect2D *scissors;
std::vector<std::string> vuids;
};
std::vector<TestCase> test_cases = {
{0,
viewports,
2,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}},
{2,
viewports,
0,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}},
{0,
viewports,
0,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136"}},
{2, nullptr, 2, scissors, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04130"}},
{2, viewports, 2, nullptr, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04131"}},
{2,
nullptr,
2,
nullptr,
{"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04130", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04131"}},
{0,
nullptr,
0,
nullptr,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136"}},
};
const auto max_viewports = m_device->Physical().limits_.maxViewports;
const bool max_viewports_maxxed = max_viewports == std::numeric_limits<decltype(max_viewports)>::max();
if (max_viewports_maxxed) {
printf("VkPhysicalDeviceLimits::maxViewports is UINT32_MAX -- skipping part of test requiring to exceed maxViewports.\n");
} else {
const auto too_much_viewports = max_viewports + 1;
// avoid potentially big allocations by using only nullptr
test_cases.push_back({too_much_viewports,
nullptr,
2,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134",
"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04130"}});
test_cases.push_back({2,
viewports,
too_much_viewports,
nullptr,
{"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134",
"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04131"}});
test_cases.push_back(
{too_much_viewports,
nullptr,
too_much_viewports,
nullptr,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04130",
"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04131"}});
}
for (const auto &test_case : test_cases) {
const auto break_vp = [&test_case](CreatePipelineHelper &helper) {
helper.vp_state_ci_.viewportCount = test_case.viewport_count;
helper.vp_state_ci_.pViewports = test_case.viewports;
helper.vp_state_ci_.scissorCount = test_case.scissor_count;
helper.vp_state_ci_.pScissors = test_case.scissors;
};
CreatePipelineHelper::OneshotTest(*this, break_vp, kErrorBit, test_case.vuids);
}
std::vector<TestCase> dyn_test_cases = {
{0,
viewports,
2,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}},
{2,
viewports,
0,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}},
{0,
viewports,
0,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136"}},
{0,
nullptr,
0,
nullptr,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-04135",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136"}},
};
if (!max_viewports_maxxed) {
const auto too_much_viewports = max_viewports + 1;
// avoid potentially big allocations by using only nullptr
dyn_test_cases.push_back({too_much_viewports,
nullptr,
2,
scissors,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}});
dyn_test_cases.push_back({2,
viewports,
too_much_viewports,
nullptr,
{"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}});
dyn_test_cases.push_back({too_much_viewports,
nullptr,
too_much_viewports,
nullptr,
{"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218",
"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219"}});
}
const VkDynamicState dyn_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
for (const auto &test_case : dyn_test_cases) {
const auto break_vp = [&](CreatePipelineHelper &helper) {
VkPipelineDynamicStateCreateInfo dyn_state_ci = vku::InitStructHelper();
dyn_state_ci.dynamicStateCount = size32(dyn_states);
dyn_state_ci.pDynamicStates = dyn_states;
helper.dyn_state_ci_ = dyn_state_ci;
helper.vp_state_ci_.viewportCount = test_case.viewport_count;
helper.vp_state_ci_.pViewports = test_case.viewports;
helper.vp_state_ci_.scissorCount = test_case.scissor_count;
helper.vp_state_ci_.pScissors = test_case.scissors;
};
CreatePipelineHelper::OneshotTest(*this, break_vp, kErrorBit, test_case.vuids);
}
}
TEST_F(NegativeDynamicState, ScissorWithCount) {
TEST_DESCRIPTION("Validate creating graphics pipeline with dynamic state scissor with count.");
SetTargetApiVersion(VK_API_VERSION_1_3);
RETURN_IF_SKIP(Init());
InitRenderTarget();
{
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
pipe.vp_state_ci_.scissorCount = 0;
pipe.vp_state_ci_.viewportCount = 0;
m_errorMonitor->SetDesiredError("VUID-VkPipelineViewportStateCreateInfo-scissorCount-04136");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
{
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
VkRect2D scissors = {};
pipe.vp_state_ci_.scissorCount = 1;
pipe.vp_state_ci_.pScissors = &scissors;
pipe.vp_state_ci_.viewportCount = 0;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-03380");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDynamicState, DrawNotSetSampleLocations) {
TEST_DESCRIPTION("Validate dynamic sample locations.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceSampleLocationsPropertiesEXT sample_locations_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(sample_locations_props);
if ((sample_locations_props.sampleLocationSampleCounts & VK_SAMPLE_COUNT_1_BIT) == 0) {
GTEST_SKIP() << "Required sample location sample count VK_SAMPLE_COUNT_1_BIT not supported";
}
VkSampleLocationEXT sample_location = {0.5f, 0.5f};
VkSampleLocationsInfoEXT sample_locations_info = vku::InitStructHelper();
sample_locations_info.sampleLocationsPerPixel = VK_SAMPLE_COUNT_1_BIT;
sample_locations_info.sampleLocationGridSize = {1u, 1u};
sample_locations_info.sampleLocationsCount = 1;
sample_locations_info.pSampleLocations = &sample_location;
VkPipelineSampleLocationsStateCreateInfoEXT sample_location_state = vku::InitStructHelper();
sample_location_state.sampleLocationsEnable = VK_TRUE;
sample_location_state.sampleLocationsInfo = sample_locations_info; // ignored
VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = vku::InitStructHelper(&sample_location_state);
pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
pipe_ms_state_ci.sampleShadingEnable = 0;
pipe_ms_state_ci.minSampleShading = 1.0;
pipe_ms_state_ci.pSampleMask = nullptr;
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
pipe.ms_ci_ = pipe_ms_state_ci;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-06666");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sample_locations_info);
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetSampleLocationsEnable) {
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
AddRequiredFeature(vkt::Feature::extendedDynamicState3SampleLocationsEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_1_BIT);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07634");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, LineWidth) {
TEST_DESCRIPTION("Test non-1.0 lineWidth errors when pipeline is created and in vkCmdSetLineWidth");
VkPhysicalDeviceFeatures features{};
RETURN_IF_SKIP(Init(&features));
InitRenderTarget();
const std::array test_cases = {-1.0f, 0.0f, NearestSmaller(1.0f), NearestGreater(1.0f),
std::numeric_limits<float>::quiet_NaN()};
// test VkPipelineRasterizationStateCreateInfo::lineWidth
for (const auto test_case : test_cases) {
const auto set_lineWidth = [&](CreatePipelineHelper &helper) { helper.rs_state_ci_.lineWidth = test_case; };
CreatePipelineHelper::OneshotTest(*this, set_lineWidth, kErrorBit,
"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00749");
}
// test vk::CmdSetLineWidth
m_command_buffer.Begin();
for (const auto test_case : test_cases) {
m_errorMonitor->SetDesiredError("VUID-vkCmdSetLineWidth-lineWidth-00788");
vk::CmdSetLineWidth(m_command_buffer, test_case);
m_errorMonitor->VerifyFound();
}
}
TEST_F(NegativeDynamicState, SetAfterStaticPipeline) {
TEST_DESCRIPTION("Pipeline without state is set and tried to use vkCmdSet");
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe_line(*this);
pipe_line.AddDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH);
pipe_line.CreateGraphicsPipeline();
CreatePipelineHelper pipe_static(*this);
pipe_static.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetLineWidth(m_command_buffer, 1.0f);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_static); // ignored
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_line);
vk::CmdDraw(m_command_buffer, 1, 0, 0, 0);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_static);
vk::CmdSetLineWidth(m_command_buffer, 1.0f);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08608");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetAttachmentFeedbackLoopEnable) {
TEST_DESCRIPTION("Set state in pipeline, but never set in command buffer before draw");
AddRequiredExtensions(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::attachmentFeedbackLoopDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08877");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, AttachmentFeedbackLoopEnableFeatures) {
TEST_DESCRIPTION("Call vkCmdSetAttachmentFeedbackLoopEnableEXT without features enabled");
AddRequiredExtensions(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError(
"VUID-vkCmdSetAttachmentFeedbackLoopEnableEXT-attachmentFeedbackLoopDynamicState-08862"); // attachmentFeedbackLoopDynamicState
m_errorMonitor->SetDesiredError(
"VUID-vkCmdSetAttachmentFeedbackLoopEnableEXT-attachmentFeedbackLoopLayout-08864"); // attachmentFeedbackLoopLayout
vk::CmdSetAttachmentFeedbackLoopEnableEXT(m_command_buffer, VK_IMAGE_ASPECT_COLOR_BIT);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, AttachmentFeedbackLoopEnableAspectMask) {
TEST_DESCRIPTION("Bad aspect masks for vkCmdSetAttachmentFeedbackLoopEnableEXT");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::attachmentFeedbackLoopDynamicState);
AddRequiredFeature(vkt::Feature::attachmentFeedbackLoopLayout);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetAttachmentFeedbackLoopEnableEXT-aspectMask-08863");
vk::CmdSetAttachmentFeedbackLoopEnableEXT(m_command_buffer, VK_IMAGE_ASPECT_PLANE_0_BIT);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SetDepthBias2EXTDepthBiasClampDisabled) {
TEST_DESCRIPTION("Call vkCmdSetDepthBias2EXT with VkPhysicalDeviceFeatures::depthBiasClamp feature disabled");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
AddRequiredFeature(vkt::Feature::depthBiasControl);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
vk::CmdSetDepthBiasEnableEXT(m_command_buffer, VK_TRUE);
VkDepthBiasInfoEXT depth_bias_info = vku::InitStructHelper();
depth_bias_info.depthBiasConstantFactor = 1.0f;
depth_bias_info.depthBiasClamp = 1.0f;
depth_bias_info.depthBiasSlopeFactor = 1.0f;
m_errorMonitor->SetDesiredError("VUID-VkDepthBiasInfoEXT-depthBiasClamp-08950");
vk::CmdSetDepthBias2EXT(m_command_buffer, &depth_bias_info);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SetDepthBias2EXTDepthBiasControlFeaturesDisabled) {
TEST_DESCRIPTION(
"Call vkCmdSetDepthBias2EXT with VkPhysicalDeviceFeatures::depthBiasClamp and VkPhysicalDeviceDepthBiasControlFeaturesEXT "
"features disabled");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
AddRequiredFeature(vkt::Feature::depthBiasControl);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe_line(*this);
pipe_line.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdSetDepthBiasEnableEXT(m_command_buffer, VK_TRUE);
VkDepthBiasInfoEXT depth_bias_info = vku::InitStructHelper();
depth_bias_info.depthBiasConstantFactor = 1.0f;
depth_bias_info.depthBiasClamp = 0.0f;
depth_bias_info.depthBiasSlopeFactor = 1.0f;
vk::CmdSetDepthBias2EXT(m_command_buffer, &depth_bias_info);
VkDepthBiasRepresentationInfoEXT depth_bias_representation = vku::InitStructHelper();
depth_bias_representation.depthBiasRepresentation = VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT;
depth_bias_representation.depthBiasExact = VK_TRUE;
depth_bias_info.pNext = &depth_bias_representation;
m_errorMonitor->SetDesiredError("VUID-VkDepthBiasRepresentationInfoEXT-leastRepresentableValueForceUnormRepresentation-08947");
m_errorMonitor->SetDesiredError("VUID-VkDepthBiasRepresentationInfoEXT-depthBiasExact-08949");
vk::CmdSetDepthBias2EXT(m_command_buffer, &depth_bias_info);
m_errorMonitor->VerifyFound();
depth_bias_representation.depthBiasRepresentation = VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT;
depth_bias_representation.depthBiasExact = VK_FALSE;
m_errorMonitor->SetDesiredError("VUID-VkDepthBiasRepresentationInfoEXT-floatRepresentation-08948");
vk::CmdSetDepthBias2EXT(m_command_buffer, &depth_bias_info);
m_errorMonitor->VerifyFound();
// Perform a successful call to vk::CmdSetDepthBias2EXT, but bound pipeline has not set depth bias as a dynamic state
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_line);
depth_bias_representation.depthBiasRepresentation = VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT;
vk::CmdSetDepthBias2EXT(m_command_buffer, &depth_bias_info);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08608");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, AlphaToCoverageOutputNoAlpha) {
TEST_DESCRIPTION("Dynamically set alphaToCoverageEnabled to true and not have component set.");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3AlphaToCoverageEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
const char *fsSource = R"glsl(
#version 450
layout(location=0) out vec3 x;
void main(){
x = vec3(1);
}
)glsl";
VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT);
VkPipelineMultisampleStateCreateInfo ms_state_ci = vku::InitStructHelper();
ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
ms_state_ci.alphaToCoverageEnable = VK_FALSE; // should be ignored
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
pipe.AddDynamicState(VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
pipe.ms_ci_ = ms_state_ci;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetAlphaToCoverageEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-alphaToCoverageEnable-08919");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ShadingRateImageEnableNotSet) {
TEST_DESCRIPTION("Create pipeline with VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV but dont set the dynamic state.");
AddRequiredExtensions(VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::shadingRateImage);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ShadingRateImageEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
pipe.AddDynamicState(VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07647");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, CoverageReductionModeNotSet) {
TEST_DESCRIPTION("Create pipeline with VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV but dont set the dynamic state.");
AddRequiredExtensions(VK_NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::coverageReductionMode);
AddRequiredFeature(vkt::Feature::extendedDynamicState3CoverageReductionMode);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
pipe.AddDynamicState(VK_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07649");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetExclusiveScissor) {
TEST_DESCRIPTION("Validate dynamic exclusive scissor.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::exclusiveScissor);
RETURN_IF_SKIP(Init());
if (!DeviceExtensionSupported(VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME, 2)) {
GTEST_SKIP() << "need VK_NV_scissor_exclusive version 2";
}
InitRenderTarget();
CreatePipelineHelper pipe1(*this);
pipe1.AddDynamicState(VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV);
pipe1.CreateGraphicsPipeline();
CreatePipelineHelper pipe2(*this);
pipe2.AddDynamicState(VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV);
pipe2.AddDynamicState(VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV);
pipe2.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07878");
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe1);
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07879");
VkBool32 exclusiveScissorEnable = VK_TRUE;
vk::CmdSetExclusiveScissorEnableNV(m_command_buffer, 0u, 1u, &exclusiveScissorEnable);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe2);
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SetDepthBiasClampDisabled) {
TEST_DESCRIPTION("Call vkCmdSetDepthBias with depthBiasClamp disabled");
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthBias-depthBiasClamp-00790");
vk::CmdSetDepthBias(m_command_buffer, 0.0f, 1.0f, 0.0);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, MultisampleStateIgnored) {
TEST_DESCRIPTION("dont ignore null pMultisampleState because missing some dynamic states");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
AddRequiredFeature(vkt::Feature::extendedDynamicState3SampleMask);
AddRequiredFeature(vkt::Feature::extendedDynamicState3AlphaToCoverageEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_MASK_EXT);
// missing VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT
pipe.gp_ci_.pMultisampleState = nullptr;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pMultisampleState-09026");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, MultisampleStateIgnoredAlphaToOne) {
TEST_DESCRIPTION("Ignore null pMultisampleState with alphaToOne enabled");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
AddRequiredFeature(vkt::Feature::extendedDynamicState3SampleMask);
AddRequiredFeature(vkt::Feature::extendedDynamicState3AlphaToCoverageEnable);
AddRequiredFeature(vkt::Feature::extendedDynamicState3AlphaToOneEnable);
AddRequiredFeature(vkt::Feature::alphaToOne);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_MASK_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
// missing VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT
pipe.gp_ci_.pMultisampleState = nullptr;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pMultisampleState-09026");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, InputAssemblyStateIgnored) {
TEST_DESCRIPTION("Ignore null pInputAssemblyState");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
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";
}
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY);
pipe.gp_ci_.pInputAssemblyState = nullptr;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-dynamicPrimitiveTopologyUnrestricted-09031");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, ColorBlendStateIgnored) {
TEST_DESCRIPTION("Ignore null pColorBlendState");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3LogicOpEnable);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEnable);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEquation);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorWriteMask);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
// Missing VK_DYNAMIC_STATE_LOGIC_OP_EXT
pipe.AddDynamicState(VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS);
VkPipelineColorBlendAttachmentState att_state = DefaultColorBlendAttachmentState();
att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR;
att_state.blendEnable = VK_TRUE;
pipe.cb_attachments_ = att_state;
pipe.gp_ci_.pColorBlendState = nullptr;
m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-09030");
pipe.CreateGraphicsPipeline();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, VertexInputLocationMissing) {
TEST_DESCRIPTION("Shader uses a location not provided with dynamic vertex input");
AddRequiredExtensions(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::vertexInputDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
const char *vsSource = R"glsl(
#version 450
layout(location = 0) in vec4 x;
layout(location = 1) in vec4 y;
layout(location = 0) out vec4 c;
void main() {
c = x * y;
}
)glsl";
VkShaderObj vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT);
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
pipe.AddDynamicState(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
pipe.CreateGraphicsPipeline();
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-Input-07939");
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vkt::Buffer buffer(*m_device, 16, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
VkDeviceSize offset = 0u;
vk::CmdBindVertexBuffers(m_command_buffer, 0u, 1u, &buffer.handle(), &offset);
VkVertexInputBindingDescription2EXT vertexInputBindingDescription = vku::InitStructHelper();
vertexInputBindingDescription.binding = 0u;
vertexInputBindingDescription.stride = sizeof(float) * 4;
vertexInputBindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
vertexInputBindingDescription.divisor = 1u;
VkVertexInputAttributeDescription2EXT vertexAttributeDescription = vku::InitStructHelper();
vertexAttributeDescription.location = 0u;
vertexAttributeDescription.binding = 0u;
vertexAttributeDescription.format = VK_FORMAT_R32G32B32A32_SFLOAT;
vertexAttributeDescription.offset = 0u;
vk::CmdSetVertexInputEXT(m_command_buffer, 1u, &vertexInputBindingDescription, 1u, &vertexAttributeDescription);
vk::CmdDraw(m_command_buffer, 4u, 1u, 0u, 0u);
m_command_buffer.EndRenderPass();
m_command_buffer.End();
m_errorMonitor->VerifyFound();
}
TEST_F(NegativeDynamicState, MissingCmdSetVertexInput) {
TEST_DESCRIPTION("Validate VK_EXT_color_write_enable VUs when disabled");
AddRequiredExtensions(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
AddRequiredFeature(vkt::Feature::vertexInputDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-04914");
vk::CmdDraw(m_command_buffer, 4u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, MissingCmdBindVertexBuffers2) {
TEST_DESCRIPTION("Validate VK_EXT_color_write_enable VUs when disabled");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-pStrides-04913");
vk::CmdDraw(m_command_buffer, 4u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
vk::CmdBindVertexBuffers2EXT(m_command_buffer, 0u, 0u, nullptr, nullptr, nullptr, nullptr);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-pStrides-04913");
vk::CmdDraw(m_command_buffer, 4u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, CmdBindVertexBuffers2NullOffset) {
SetTargetApiVersion(VK_API_VERSION_1_3);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
vkt::Buffer buffer(*m_device, 16, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
VkDeviceSize size = 16;
m_errorMonitor->SetDesiredError("VUID-vkCmdBindVertexBuffers2-pOffsets-parameter");
vk::CmdBindVertexBuffers2(m_command_buffer, 0, 1, &buffer.handle(), nullptr, &size, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, AdvancedBlendMaxAttachments) {
TEST_DESCRIPTION("Attempt to use more than maximum attachments in subpass when advanced blend is enabled");
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::dynamicRendering);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEnable);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendAdvanced);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT blend_advanced_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(blend_advanced_props);
uint32_t attachment_count = blend_advanced_props.advancedBlendMaxColorAttachments + 1;
if (attachment_count > m_device->Physical().limits_.maxColorAttachments) {
GTEST_SKIP() << "advancedBlendMaxColorAttachments is equal to maxColorAttachments";
}
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.imageType = VK_IMAGE_TYPE_2D;
image_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_ci.extent = {32, 32, 1};
image_ci.mipLevels = 1u;
image_ci.arrayLayers = 1u;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
std::vector<std::unique_ptr<vkt::Image>> images(attachment_count);
std::vector<vkt::ImageView> image_views(attachment_count);
std::vector<VkFormat> formats(attachment_count);
std::vector<VkPipelineColorBlendAttachmentState> pipeline_color_blends(attachment_count);
std::vector<VkRenderingAttachmentInfo> rendering_attachment_info(attachment_count);
for (uint32_t i = 0; i < attachment_count; ++i) {
images[i] = std::make_unique<vkt::Image>(*m_device, image_ci);
image_views[i] = images[i]->CreateView();
formats[i] = VK_FORMAT_R8G8B8A8_UNORM;
pipeline_color_blends[i] = DefaultColorBlendAttachmentState();
rendering_attachment_info[i] = vku::InitStructHelper();
rendering_attachment_info[i].imageView = image_views[i];
rendering_attachment_info[i].imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
rendering_attachment_info[i].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
rendering_attachment_info[i].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
rendering_attachment_info[i].clearValue.color = m_clear_color;
}
VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper();
pipeline_rendering_info.colorAttachmentCount = attachment_count;
pipeline_rendering_info.pColorAttachmentFormats = formats.data();
CreatePipelineHelper pipe(*this, &pipeline_rendering_info);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT);
pipe.cb_ci_.attachmentCount = attachment_count;
pipe.cb_ci_.pAttachments = pipeline_color_blends.data();
pipe.CreateGraphicsPipeline();
VkRenderingInfo rendering_info = vku::InitStructHelper();
rendering_info.renderArea = {{0, 0}, {32, 32}};
rendering_info.layerCount = 1u;
rendering_info.colorAttachmentCount = attachment_count;
rendering_info.pColorAttachments = rendering_attachment_info.data();
m_command_buffer.Begin();
m_command_buffer.BeginRendering(rendering_info);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
for (uint32_t i = 0; i < attachment_count; ++i) {
VkBool32 color_blend_enable = i == 0;
vk::CmdSetColorBlendEnableEXT(m_command_buffer, i, 1u, &color_blend_enable);
VkColorBlendAdvancedEXT color_blend_advanced;
color_blend_advanced.advancedBlendOp = VK_BLEND_OP_ADD;
color_blend_advanced.srcPremultiplied = VK_FALSE;
color_blend_advanced.dstPremultiplied = VK_FALSE;
color_blend_advanced.blendOverlap = VK_BLEND_OVERLAP_UNCORRELATED_EXT;
color_blend_advanced.clampResults = VK_FALSE;
vk::CmdSetColorBlendAdvancedEXT(m_command_buffer, i, 1u, &color_blend_advanced);
}
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-advancedBlendMaxColorAttachments-07480");
vk::CmdDraw(m_command_buffer, 4u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRendering();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, MissingColorAttachmentBlendBit) {
TEST_DESCRIPTION(
"Dynamically enable blend for color attachment that does not have VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkFormat format = VK_FORMAT_R32G32B32A32_SINT;
VkFormatProperties format_properties;
vk::GetPhysicalDeviceFormatProperties(Gpu(), format, &format_properties);
if ((format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0 ||
(format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) != 0) {
GTEST_SKIP() << "Required foramt features not available";
}
vkt::Image image(*m_device, 32u, 32u, format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView image_view = image.CreateView();
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(format, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
rp.AddColorAttachment(0);
rp.CreateRenderPass();
vkt::Framebuffer framebuffer(*m_device, rp, 1, &image_view.handle());
CreatePipelineHelper pipe(*this);
pipe.gp_ci_.renderPass = rp;
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, framebuffer);
VkBool32 enable = VK_TRUE;
vk::CmdSetColorBlendEnableEXT(m_command_buffer, 0u, 1u, &enable);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-blendEnable-04727");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SampleLocationsSamplesMismatch) {
TEST_DESCRIPTION("Dynamically set sample locations samples that don't match that of the pipeline");
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
AddRequiredFeature(vkt::Feature::extendedDynamicState3SampleLocationsEnable);
RETURN_IF_SKIP(Init());
RETURN_IF_SKIP(InitRenderTarget());
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
pipe.CreateGraphicsPipeline();
VkSampleLocationEXT sample_locations[2] = {{0.5f, 0.5f}, {0.5f, 0.5f}};
VkSampleLocationsInfoEXT sapmle_locations_info = vku::InitStructHelper();
sapmle_locations_info.sampleLocationsPerPixel = VK_SAMPLE_COUNT_2_BIT;
sapmle_locations_info.sampleLocationGridSize = {1u, 1u};
sapmle_locations_info.sampleLocationsCount = 2u;
sapmle_locations_info.pSampleLocations = sample_locations;
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetSampleLocationsEnableEXT(m_command_buffer, VK_TRUE);
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sapmle_locations_info);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsPerPixel-07482");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DynamicSampleLocationsRasterizationSamplesMismatch) {
TEST_DESCRIPTION("Dynamically set sample locations and rasterizationSamples that dont match");
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
AddRequiredFeature(vkt::Feature::extendedDynamicState3SampleLocationsEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe.CreateGraphicsPipeline();
VkSampleLocationEXT sample_locations[2] = {{0.5f, 0.5f}, {0.5f, 0.5f}};
VkSampleLocationsInfoEXT sapmle_locations_info = vku::InitStructHelper();
sapmle_locations_info.sampleLocationsPerPixel = VK_SAMPLE_COUNT_2_BIT;
sapmle_locations_info.sampleLocationGridSize = {1u, 1u};
sapmle_locations_info.sampleLocationsCount = 2u;
sapmle_locations_info.pSampleLocations = sample_locations;
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sapmle_locations_info);
vk::CmdSetSampleLocationsEnableEXT(m_command_buffer, VK_TRUE);
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_1_BIT);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsPerPixel-07483");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DynamicRasterizationSamples) {
TEST_DESCRIPTION("Test invalid rasterization samples with zero attachment subpass");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
RETURN_IF_SKIP(Init());
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
VkRenderPassCreateInfo render_pass_ci = vku::InitStructHelper();
render_pass_ci.subpassCount = 1u;
render_pass_ci.pSubpasses = &subpass;
vkt::RenderPass render_pass(*m_device, render_pass_ci);
vkt::Framebuffer framebuffer(*m_device, render_pass, 0, nullptr);
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe.gp_ci_.renderPass = render_pass;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(render_pass, framebuffer, 32, 32);
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_1_BIT);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_2_BIT);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-rasterizationSamples-07471");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SampleLocationsEnable) {
TEST_DESCRIPTION("Test sample locations enable");
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceSampleLocationsPropertiesEXT sample_location_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(sample_location_properties);
if (!sample_location_properties.variableSampleLocations) {
GTEST_SKIP() << "variableSampleLocations not supported";
}
VkMultisamplePropertiesEXT multisample_prop = vku::InitStructHelper();
vk::GetPhysicalDeviceMultisamplePropertiesEXT(Gpu(), VK_SAMPLE_COUNT_1_BIT, &multisample_prop);
// 1 from VK_SAMPLE_COUNT_1_BIT
const uint32_t valid_count =
multisample_prop.maxSampleLocationGridSize.width * multisample_prop.maxSampleLocationGridSize.height * 1;
if (valid_count <= 1) {
GTEST_SKIP() << "Need a maxSampleLocationGridSize width x height greater than 1";
}
std::vector<VkSampleLocationEXT> sample_location(valid_count, {0.5f, 0.5f});
VkSampleLocationsInfoEXT sample_locations_info = vku::InitStructHelper();
sample_locations_info.sampleLocationsPerPixel = VK_SAMPLE_COUNT_1_BIT;
sample_locations_info.sampleLocationGridSize.width = multisample_prop.maxSampleLocationGridSize.width;
sample_locations_info.sampleLocationGridSize.height = multisample_prop.maxSampleLocationGridSize.height;
sample_locations_info.sampleLocationsCount = valid_count;
sample_locations_info.pSampleLocations = sample_location.data();
VkPipelineSampleLocationsStateCreateInfoEXT sample_location_state = vku::InitStructHelper();
sample_location_state.sampleLocationsEnable = VK_TRUE;
sample_location_state.sampleLocationsInfo = sample_locations_info;
VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = vku::InitStructHelper(&sample_location_state);
pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
pipe_ms_state_ci.sampleShadingEnable = 0;
pipe_ms_state_ci.minSampleShading = 1.0;
pipe_ms_state_ci.pSampleMask = nullptr;
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.width = multisample_prop.maxSampleLocationGridSize.width + 1u;
CreatePipelineHelper pipe1(*this);
pipe1.ms_ci_ = pipe_ms_state_ci;
pipe1.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe1.CreateGraphicsPipeline();
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.width = multisample_prop.maxSampleLocationGridSize.width;
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.height = multisample_prop.maxSampleLocationGridSize.height + 1;
CreatePipelineHelper pipe2(*this);
pipe2.ms_ci_ = pipe_ms_state_ci;
pipe2.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe2.CreateGraphicsPipeline();
sample_location_state.sampleLocationsInfo.sampleLocationGridSize.height = multisample_prop.maxSampleLocationGridSize.height;
pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT;
sample_location_state.sampleLocationsInfo.sampleLocationsPerPixel = VK_SAMPLE_COUNT_2_BIT;
VkMultisamplePropertiesEXT multisample_prop2 = vku::InitStructHelper();
vk::GetPhysicalDeviceMultisamplePropertiesEXT(Gpu(), VK_SAMPLE_COUNT_2_BIT, &multisample_prop2);
// 2 from VK_SAMPLE_COUNT_2_BIT
const uint32_t valid_count2 =
multisample_prop.maxSampleLocationGridSize.width * multisample_prop.maxSampleLocationGridSize.height * 2;
std::vector<VkSampleLocationEXT> sample_location2(valid_count2, {0.5f, 0.5f});
sample_location_state.sampleLocationsInfo.pSampleLocations = sample_location2.data();
CreatePipelineHelper pipe3(*this);
pipe3.ms_ci_ = pipe_ms_state_ci;
pipe3.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe3.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe1);
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_1_BIT);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsEnable-07936");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe2);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsEnable-07937");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe3);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsEnable-07938");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, InvalidSampleMaskSamples) {
TEST_DESCRIPTION("Test using pipeline with invalid dynamic sample mask samples");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3SampleMask);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
RETURN_IF_SKIP(Init());
const VkPhysicalDeviceLimits &dev_limits = m_device->Physical().limits_;
if ((dev_limits.sampledImageColorSampleCounts & VK_SAMPLE_COUNT_2_BIT) == 0) {
GTEST_SKIP() << "Required VkSampleCountFlagBits are not supported; skipping";
}
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.imageType = VK_IMAGE_TYPE_2D;
image_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_ci.extent = {32u, 32u, 1u};
image_ci.mipLevels = 1u;
image_ci.arrayLayers = 1u;
image_ci.samples = VK_SAMPLE_COUNT_2_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
vkt::Image image(*m_device, image_ci, vkt::set_layout);
vkt::ImageView image_view = image.CreateView();
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_2_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL});
rp.AddColorAttachment(0);
rp.CreateRenderPass();
vkt::Framebuffer framebuffer(*m_device, rp, 1, &image_view.handle());
VkPipelineMultisampleStateCreateInfo ms_state_ci = vku::InitStructHelper();
ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT;
CreatePipelineHelper pipe1(*this);
pipe1.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_MASK_EXT);
pipe1.ms_ci_ = ms_state_ci;
pipe1.gp_ci_.renderPass = rp;
pipe1.CreateGraphicsPipeline();
CreatePipelineHelper pipe2(*this);
pipe2.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_MASK_EXT);
pipe2.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe2.ms_ci_ = ms_state_ci;
pipe2.gp_ci_.renderPass = rp;
pipe2.CreateGraphicsPipeline();
VkSampleMask sample_mask = 1u;
VkClearValue clear_value;
clear_value.color = {{0, 0, 0, 0}};
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, framebuffer, 32, 32, 1, &clear_value);
vk::CmdSetSampleMaskEXT(m_command_buffer, VK_SAMPLE_COUNT_1_BIT, &sample_mask);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe1);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-samples-07472");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_2_BIT);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe2);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-samples-07473");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_1_BIT);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe2);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08644");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, InvalidConservativeRasterizationMode) {
TEST_DESCRIPTION("Test pipeline with invalid dynamic conservative rasterization mode");
AddRequiredExtensions(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ConservativeRasterizationMode);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservative_rasterization_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(conservative_rasterization_props);
if (conservative_rasterization_props.conservativePointAndLineRasterization) {
GTEST_SKIP() << "conservativePointAndLineRasterization is required to be VK_FALSE";
}
VkPipelineRasterizationConservativeStateCreateInfoEXT cs_info = vku::InitStructHelper();
cs_info.conservativeRasterizationMode = VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
cs_info.extraPrimitiveOverestimationSize = 0.0f;
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
pipe.rs_state_ci_.pNext = &cs_info;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetConservativeRasterizationModeEXT(m_command_buffer, VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-conservativePointAndLineRasterization-07499");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DynamicSampleLocationsEnable) {
TEST_DESCRIPTION("Test dynamically enabling sample locations");
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3SampleLocationsEnable);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceSampleLocationsPropertiesEXT sample_location_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(sample_location_properties);
if (!sample_location_properties.variableSampleLocations) {
GTEST_SKIP() << "variableSampleLocations not supported";
} else if ((sample_location_properties.sampleLocationSampleCounts & VK_SAMPLE_COUNT_1_BIT) == 0) {
GTEST_SKIP() << "VK_SAMPLE_COUNT_1_BIT sampleLocationSampleCounts is not supported";
}
VkFormat format = FindSupportedDepthStencilFormat(Gpu());
vkt::Image image(*m_device, 32u, 32u, format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkt::ImageView image_view = image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(format, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL});
rp.AddDepthStencilAttachment(0);
rp.CreateRenderPass();
vkt::Framebuffer framebuffer(*m_device, rp, 1, &image_view.handle());
VkClearValue clear_value;
clear_value.depthStencil = {1.0f, 0u};
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
pipe.gp_ci_.renderPass = rp;
pipe.ds_ci_ = vku::InitStructHelper();
pipe.CreateGraphicsPipeline();
VkSampleLocationEXT sample_location = {0.5f, 0.5f};
VkSampleLocationsInfoEXT sample_locations_info = vku::InitStructHelper();
sample_locations_info.sampleLocationsPerPixel = VK_SAMPLE_COUNT_1_BIT;
sample_locations_info.sampleLocationGridSize = {1u, 1u};
sample_locations_info.sampleLocationsCount = 1;
sample_locations_info.pSampleLocations = &sample_location;
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, framebuffer, 32, 32, 1, &clear_value);
vk::CmdSetSampleLocationsEnableEXT(m_command_buffer, VK_TRUE);
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sample_locations_info);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsEnable-07484");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DynamicRenderingDynamicSampleLocationsEnable) {
TEST_DESCRIPTION("Test dynamically enabling sample locations with dynamicRendering");
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3SampleLocationsEnable);
AddRequiredFeature(vkt::Feature::dynamicRendering);
RETURN_IF_SKIP(Init());
VkPhysicalDeviceSampleLocationsPropertiesEXT sample_location_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(sample_location_properties);
if (!sample_location_properties.variableSampleLocations) {
GTEST_SKIP() << "variableSampleLocations not supported";
} else if ((sample_location_properties.sampleLocationSampleCounts & VK_SAMPLE_COUNT_1_BIT) == 0) {
GTEST_SKIP() << "VK_SAMPLE_COUNT_1_BIT sampleLocationSampleCounts is not supported";
}
VkFormat format = FindSupportedDepthStencilFormat(Gpu());
vkt::Image image(*m_device, 32u, 32u, format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
vkt::ImageView image_view = image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
VkClearValue clear_value;
clear_value.depthStencil = {1.0f, 0u};
VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper();
pipeline_rendering_info.depthAttachmentFormat = format;
CreatePipelineHelper pipe(*this, &pipeline_rendering_info);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
pipe.ds_ci_ = vku::InitStructHelper();
pipe.CreateGraphicsPipeline();
VkRenderingAttachmentInfo depth_attachment = vku::InitStructHelper();
depth_attachment.imageView = image_view.handle();
depth_attachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
VkRenderingInfo rendering_info = vku::InitStructHelper();
rendering_info.renderArea = {{0, 0}, {32u, 32u}};
rendering_info.layerCount = 1u;
rendering_info.pDepthAttachment = &depth_attachment;
VkSampleLocationEXT sample_location = {0.5f, 0.5f};
VkSampleLocationsInfoEXT sample_locations_info = vku::InitStructHelper();
sample_locations_info.sampleLocationsPerPixel = VK_SAMPLE_COUNT_1_BIT;
sample_locations_info.sampleLocationGridSize = {1u, 1u};
sample_locations_info.sampleLocationsCount = 1;
sample_locations_info.pSampleLocations = &sample_location;
m_command_buffer.Begin();
m_command_buffer.BeginRendering(rendering_info);
vk::CmdSetSampleLocationsEnableEXT(m_command_buffer, VK_TRUE);
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sample_locations_info);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsEnable-07484");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRendering();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DynamicSampleLocationsGridSize) {
TEST_DESCRIPTION("Test sample locations grid size");
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
AddRequiredFeature(vkt::Feature::extendedDynamicState3SampleLocationsEnable);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceSampleLocationsPropertiesEXT sample_location_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(sample_location_properties);
if (!sample_location_properties.variableSampleLocations) {
GTEST_SKIP() << "variableSampleLocations not supported";
}
VkMultisamplePropertiesEXT multisample_prop = vku::InitStructHelper();
vk::GetPhysicalDeviceMultisamplePropertiesEXT(Gpu(), VK_SAMPLE_COUNT_1_BIT, &multisample_prop);
// 1 from VK_SAMPLE_COUNT_1_BIT
const uint32_t valid_count =
multisample_prop.maxSampleLocationGridSize.width * multisample_prop.maxSampleLocationGridSize.height * 1;
if (valid_count <= 1) {
GTEST_SKIP() << "Need a maxSampleLocationGridSize width x height greater than 1";
}
std::vector<VkSampleLocationEXT> sample_location(valid_count, {0.5f, 0.5f});
VkSampleLocationsInfoEXT sample_locations_info = vku::InitStructHelper();
sample_locations_info.sampleLocationsPerPixel = VK_SAMPLE_COUNT_1_BIT;
sample_locations_info.sampleLocationGridSize.width = multisample_prop.maxSampleLocationGridSize.width;
sample_locations_info.sampleLocationGridSize.height = multisample_prop.maxSampleLocationGridSize.height;
sample_locations_info.sampleLocationsCount = valid_count;
sample_locations_info.pSampleLocations = sample_location.data();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_1_BIT);
vk::CmdSetSampleLocationsEnableEXT(m_command_buffer, VK_TRUE);
sample_locations_info.sampleLocationGridSize.width = multisample_prop.maxSampleLocationGridSize.width + 1u;
sample_locations_info.sampleLocationsCount =
sample_locations_info.sampleLocationGridSize.width * sample_locations_info.sampleLocationGridSize.height;
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sample_locations_info);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsEnable-07485");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
sample_locations_info.sampleLocationGridSize.width = multisample_prop.maxSampleLocationGridSize.width;
sample_locations_info.sampleLocationGridSize.height = multisample_prop.maxSampleLocationGridSize.height + 1u;
sample_locations_info.sampleLocationsCount =
sample_locations_info.sampleLocationGridSize.width * sample_locations_info.sampleLocationGridSize.height;
vk::CmdSetSampleLocationsEXT(m_command_buffer, &sample_locations_info);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsEnable-07486");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, InterpolateAtSample) {
TEST_DESCRIPTION("Test using spirv instruction InterpolateAtSample");
AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3SampleLocationsEnable);
AddRequiredFeature(vkt::Feature::sampleRateShading);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceSampleLocationsPropertiesEXT sample_location_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(sample_location_properties);
if (!sample_location_properties.variableSampleLocations) {
GTEST_SKIP() << "variableSampleLocations not supported";
}
const char vs_src[] = R"glsl(
#version 460
layout(location = 0) out vec2 uv;
void main() {
uv = vec2(gl_VertexIndex & 1, (gl_VertexIndex >> 1) & 1);
gl_Position = vec4(uv, 0.0f, 1.0f);
}
)glsl";
const char fs_src[] = R"glsl(
#version 460
layout(location = 0) out vec4 uFragColor;
layout(location = 0) in vec2 v;
void main() {
vec2 sample1 = interpolateAtSample(v, 0);
uFragColor = vec4(0.1f);
}
)glsl";
VkShaderObj vs(*m_device, vs_src, VK_SHADER_STAGE_VERTEX_BIT);
VkShaderObj fs(*m_device, fs_src, VK_SHADER_STAGE_FRAGMENT_BIT);
CreatePipelineHelper pipe(*this);
pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
pipe.AddDynamicState(VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetSampleLocationsEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsEnable-07487");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DynamicRasterizationSamplesWithMSRTSS) {
TEST_DESCRIPTION("Test dynamic rasterization samples with MSRTSS");
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::dynamicRendering);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
AddRequiredFeature(vkt::Feature::multisampledRenderToSingleSampled);
RETURN_IF_SKIP(Init());
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.flags = VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
image_ci.imageType = VK_IMAGE_TYPE_2D;
image_ci.format = VK_FORMAT_R8G8B8A8_UNORM;
image_ci.extent = {32u, 32u, 1u};
image_ci.mipLevels = 1u;
image_ci.arrayLayers = 1u;
image_ci.samples = VK_SAMPLE_COUNT_1_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
image_ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImageFormatProperties image_format_properties;
GetImageFormatProps(Gpu(), image_ci, image_format_properties);
if ((image_format_properties.sampleCounts & VK_SAMPLE_COUNT_2_BIT) == 0) {
GTEST_SKIP() << "Required sample count not supported";
}
vkt::Image image(*m_device, image_ci, vkt::set_layout);
vkt::ImageView image_view = image.CreateView();
VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper();
pipeline_rendering_info.colorAttachmentCount = 1u;
pipeline_rendering_info.pColorAttachmentFormats = &image_ci.format;
CreatePipelineHelper pipe(*this, &pipeline_rendering_info);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe.gp_ci_.renderPass = VK_NULL_HANDLE;
pipe.CreateGraphicsPipeline();
VkMultisampledRenderToSingleSampledInfoEXT msrtss_info = vku::InitStructHelper();
msrtss_info.multisampledRenderToSingleSampledEnable = VK_TRUE;
msrtss_info.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT;
VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper();
color_attachment.imageView = image_view;
color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
color_attachment.clearValue.color = m_clear_color;
color_attachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
color_attachment.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkRenderingInfo rendering_info = vku::InitStructHelper(&msrtss_info);
rendering_info.renderArea = {{0, 0}, {32, 32}};
rendering_info.layerCount = 1u;
rendering_info.colorAttachmentCount = 1u;
rendering_info.pColorAttachments = &color_attachment;
m_command_buffer.Begin();
m_command_buffer.BeginRendering(rendering_info);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_1_BIT);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-09211");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRendering();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, PGQNonZeroRasterizationStreams) {
TEST_DESCRIPTION("Use primitives generated query with dynamic rasterization stream");
AddRequiredExtensions(VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_PRIMITIVES_GENERATED_QUERY_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::transformFeedback);
AddRequiredFeature(vkt::Feature::primitivesGeneratedQuery);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationStream);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(transform_feedback_props);
if (!transform_feedback_props.transformFeedbackRasterizationStreamSelect) {
GTEST_SKIP() << "transformFeedbackRasterizationStreamSelect not supported";
}
vkt::QueryPool pg_query_pool(*m_device, VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT, 1);
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
vk::CmdBeginQuery(m_command_buffer, pg_query_pool, 0u, 0u);
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetRasterizationStreamEXT(m_command_buffer, 1u);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-primitivesGeneratedQueryWithNonZeroStreams-07481");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
vk::CmdEndQuery(m_command_buffer, pg_query_pool, 0u);
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, MissingScissorWithCount) {
TEST_DESCRIPTION("Create pipeline with VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT, but set dynamic state with vkCmdSetScissor");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
pipe.vp_state_ci_.viewportCount = 0u;
pipe.vp_state_ci_.scissorCount = 0u;
pipe.CreateGraphicsPipeline();
const VkViewport viewport = {0, 0, 32.0f, 32.0f, 0.0f, 1.0f};
const VkRect2D scissor = {{0, 0}, {32u, 32u}};
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetViewport(m_command_buffer, 0u, 1u, &viewport);
vk::CmdSetScissor(m_command_buffer, 0u, 1u, &scissor);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-viewportCount-03417");
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-scissorCount-03418");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, RebindSamePipeline) {
TEST_DESCRIPTION(
"Test that a warning is produced for a shader consuming an input attachment with a format having a different fundamental "
"type");
AddRequiredExtensions(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
RETURN_IF_SKIP(Init());
InitRenderTarget();
VkPhysicalDeviceDriverProperties driver_properties = vku::InitStructHelper();
GetPhysicalDeviceProperties2(driver_properties);
if (driver_properties.conformanceVersion.major > 1 || driver_properties.conformanceVersion.minor > 3 ||
(driver_properties.conformanceVersion.minor == 3 && driver_properties.conformanceVersion.subminor > 7)) {
GTEST_SKIP() << "conformanceVersion is greater than the version the test requires";
}
if (driver_properties.conformanceVersion.major == 0) {
GTEST_SKIP() << "conformanceVersion is invalid"; // happens in some non-conformant mesa drivers/MockICD
}
CreatePipelineHelper pipe(*this);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetPrimitiveTopologyEXT(m_command_buffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
m_errorMonitor->SetDesiredWarning("UNASSIGNED-vkCmdBindPipeline-Pipeline-Rebind");
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorBlendEnableNotSet) {
TEST_DESCRIPTION("Create pipeline with VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT dynamic state but dont set it.");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEnable);
RETURN_IF_SKIP(Init());
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddColorAttachment(0);
rp.CreateRenderPass();
vkt::Image image(*m_device, 32u, 32u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView image_view = image.CreateView();
vkt::Framebuffer framebuffer(*m_device, rp, 1, &image_view.handle());
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
pipe.gp_ci_.renderPass = rp;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, framebuffer, 32u, 32u);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07627");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorBlendEquationNotSet) {
TEST_DESCRIPTION("Create pipeline with VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT dynamic state but dont set it.");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEquation);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
pipe.cb_attachments_.blendEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-10862");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorWriteMaskNotSet) {
TEST_DESCRIPTION("Create pipeline with VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT dynamic state but dont set it.");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorWriteMask);
RETURN_IF_SKIP(Init());
RenderPassSingleSubpass rp(*this);
rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL});
rp.AddColorAttachment(0);
rp.CreateRenderPass();
vkt::Image image(*m_device, 32u, 32u, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView image_view = image.CreateView();
vkt::Framebuffer framebuffer(*m_device, rp, 1, &image_view.handle());
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT);
pipe.gp_ci_.renderPass = rp;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(rp, framebuffer, 32u, 32u);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07629");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, ColorBlendAdvancedNotSet) {
TEST_DESCRIPTION("Create pipeline with VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT dynamic state but dont set it.");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendAdvanced);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT);
pipe.cb_attachments_.blendEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-rasterizerDiscardEnable-10863");
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SetColorBlendEnableArrayLength) {
TEST_DESCRIPTION("vkCmdSetColorBlendEnableEXT with zero attachmentCount");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorBlendEnable);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
VkBool32 color_blend_enable = VK_TRUE;
m_errorMonitor->SetDesiredError("VUID-vkCmdSetColorBlendEnableEXT-attachmentCount-arraylength");
vk::CmdSetColorBlendEnableEXT(m_command_buffer, 0, 0, &color_blend_enable);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, SetColorBlendWriteMaskArrayLength) {
TEST_DESCRIPTION("vkCmdSetColorWriteMaskEXT with zero attachmentCount");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3ColorWriteMask);
RETURN_IF_SKIP(Init());
m_command_buffer.Begin();
VkColorComponentFlags write_mask = VK_COLOR_COMPONENT_R_BIT;
m_errorMonitor->SetDesiredError("VUID-vkCmdSetColorWriteMaskEXT-attachmentCount-arraylength");
vk::CmdSetColorWriteMaskEXT(m_command_buffer, 0, 0, &write_mask);
m_errorMonitor->VerifyFound();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, RasterizationSamplesDynamicRendering) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3RasterizationSamples);
AddRequiredFeature(vkt::Feature::dynamicRendering);
RETURN_IF_SKIP(Init());
VkFormat color_format = VK_FORMAT_B8G8R8A8_UNORM;
VkImageCreateInfo image_ci = vku::InitStructHelper();
image_ci.imageType = VK_IMAGE_TYPE_2D;
image_ci.format = color_format;
image_ci.extent = {32u, 32u, 1u};
image_ci.mipLevels = 1u;
image_ci.arrayLayers = 1u;
image_ci.samples = VK_SAMPLE_COUNT_4_BIT;
image_ci.tiling = VK_IMAGE_TILING_OPTIMAL;
image_ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
vkt::Image image(*m_device, image_ci, vkt::set_layout);
vkt::ImageView image_view = image.CreateView();
vkt::Image resolve_image(*m_device, 32u, 32u, color_format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView resolve_image_view = resolve_image.CreateView();
VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper();
pipeline_rendering_info.colorAttachmentCount = 1;
pipeline_rendering_info.pColorAttachmentFormats = &color_format;
CreatePipelineHelper pipe(*this, &pipeline_rendering_info);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
pipe.CreateGraphicsPipeline();
VkRenderingAttachmentInfo colorAttachment = vku::InitStructHelper();
colorAttachment.imageView = image_view;
colorAttachment.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
colorAttachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
colorAttachment.resolveImageView = resolve_image_view;
colorAttachment.resolveImageLayout = VK_IMAGE_LAYOUT_GENERAL;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.clearValue.color = m_clear_color;
VkRenderingInfo rendering_info = vku::InitStructHelper();
rendering_info.renderArea = {{0, 0}, {32u, 32u}};
rendering_info.layerCount = 1u;
rendering_info.colorAttachmentCount = 1u;
rendering_info.pColorAttachments = &colorAttachment;
m_command_buffer.Begin();
m_command_buffer.BeginRendering(rendering_info);
vk::CmdSetRasterizationSamplesEXT(m_command_buffer, VK_SAMPLE_COUNT_2_BIT);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08644");
vk::CmdDraw(m_command_buffer, 4u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRendering();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetDepthCompareOp) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_COMPARE_OP);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetRasterizerDiscardEnableEXT(m_command_buffer, VK_FALSE);
vk::CmdSetDepthTestEnableEXT(m_command_buffer, VK_TRUE);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07845");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
vk::CmdSetRasterizerDiscardEnableEXT(m_command_buffer, VK_TRUE);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
vk::CmdSetRasterizerDiscardEnableEXT(m_command_buffer, VK_FALSE);
vk::CmdSetDepthTestEnableEXT(m_command_buffer, VK_FALSE);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
vk::CmdSetDepthTestEnableEXT(m_command_buffer, VK_TRUE);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07845");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DrawNotSetDepthWriteEnable) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
AddRequiredFeature(vkt::Feature::extendedDynamicState2);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE);
pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE);
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetRasterizerDiscardEnableEXT(m_command_buffer, VK_FALSE);
vk::CmdSetDepthTestEnableEXT(m_command_buffer, VK_TRUE);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle());
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07844");
vk::CmdDraw(m_command_buffer, 1, 1, 0, 0);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DepthClampControl) {
AddRequiredExtensions(VK_EXT_DEPTH_CLAMP_CONTROL_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::depthClamp);
AddRequiredFeature(vkt::Feature::depthClampControl);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_CLAMP_RANGE_EXT);
pipe.rs_state_ci_.depthClampEnable = VK_TRUE;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-09650");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, DepthClampControlNullStruct) {
AddRequiredExtensions(VK_EXT_DEPTH_CLAMP_CONTROL_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::depthClampControl);
RETURN_IF_SKIP(Init());
InitRenderTarget();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
m_errorMonitor->SetDesiredError("VUID-vkCmdSetDepthClampRangeEXT-pDepthClampRange-09647");
vk::CmdSetDepthClampRangeEXT(m_command_buffer, VK_DEPTH_CLAMP_MODE_USER_DEFINED_RANGE_EXT, nullptr);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, LineRasterization) {
AddRequiredExtensions(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3LineRasterizationMode);
AddRequiredFeature(vkt::Feature::bresenhamLines);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
pipe.ms_ci_.alphaToCoverageEnable = VK_TRUE;
pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
vk::CmdSetLineRasterizationModeEXT(m_command_buffer, VK_LINE_RASTERIZATION_MODE_BRESENHAM);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-10608");
vk::CmdDraw(m_command_buffer, 4u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, MultiviewInvalidate) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/10699");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredExtensions(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState);
AddRequiredFeature(vkt::Feature::multiview);
RETURN_IF_SKIP(Init());
vkt::Image color_image(*m_device, m_width, m_height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
vkt::ImageView color_image_view = color_image.CreateView();
VkAttachmentDescription2 attachment_description = vku::InitStructHelper();
attachment_description.flags = 0u;
attachment_description.format = VK_FORMAT_R8G8B8A8_UNORM;
attachment_description.samples = VK_SAMPLE_COUNT_1_BIT;
attachment_description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attachment_description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attachment_description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
attachment_description.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attachment_description.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
attachment_description.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentReference2 attachment_reference = vku::InitStructHelper();
attachment_reference.attachment = 0u;
attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription2 subpass_descriptions[2];
subpass_descriptions[0] = vku::InitStructHelper();
subpass_descriptions[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass_descriptions[0].colorAttachmentCount = 1u;
subpass_descriptions[0].pColorAttachments = &attachment_reference;
subpass_descriptions[0].viewMask = 0x1u;
subpass_descriptions[1] = vku::InitStructHelper();
subpass_descriptions[1].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass_descriptions[1].colorAttachmentCount = 1u;
subpass_descriptions[1].pColorAttachments = &attachment_reference;
subpass_descriptions[1].viewMask = 0x1u;
VkRenderPassCreateInfo2 rpci = vku::InitStructHelper();
rpci.attachmentCount = 1;
rpci.pAttachments = &attachment_description;
rpci.subpassCount = 2u;
rpci.pSubpasses = subpass_descriptions;
vkt::RenderPass render_pass(*m_device, rpci);
vkt::Framebuffer framebuffer(*m_device, render_pass, 1u, &color_image_view.handle(), m_width, m_height);
VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f};
VkPipelineViewportStateCreateInfo viewport_state_ci = vku::InitStructHelper();
viewport_state_ci.viewportCount = 1u;
viewport_state_ci.pViewports = &viewport;
CreatePipelineHelper pipe1(*this);
pipe1.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
pipe1.gp_ci_.renderPass = render_pass;
pipe1.gp_ci_.pViewportState = &viewport_state_ci;
pipe1.CreateGraphicsPipeline();
CreatePipelineHelper pipe2(*this);
pipe2.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
pipe2.gp_ci_.renderPass = render_pass;
pipe2.gp_ci_.pViewportState = &viewport_state_ci;
pipe2.gp_ci_.subpass = 1u;
pipe2.CreateGraphicsPipeline();
VkClearValue clear_value = {};
clear_value.color.float32[0] = 0.0f;
clear_value.color.float32[1] = 0.0f;
clear_value.color.float32[2] = 0.0f;
clear_value.color.float32[3] = 1.0f;
VkRenderPassBeginInfo render_pass_bi = vku::InitStructHelper();
render_pass_bi.renderPass = render_pass;
render_pass_bi.framebuffer = framebuffer;
render_pass_bi.renderArea = {{0, 0}, {m_width, m_height}};
render_pass_bi.clearValueCount = 1u;
render_pass_bi.pClearValues = &clear_value;
VkRect2D scissor = {{0, 0}, {64, 64}};
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(render_pass_bi);
vk::CmdSetScissorWithCountEXT(m_command_buffer, 1u, &scissor);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe1);
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
// invalidated with multiview
vk::CmdNextSubpass(m_command_buffer, VK_SUBPASS_CONTENTS_INLINE);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe2);
// VUID-vkCmdDraw-scissorCount-03418
m_errorMonitor->SetDesiredError("When multiview is enabled, vkCmdNextSubpass will invalidate all dynamic state");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}
TEST_F(NegativeDynamicState, MeshPipelineInvalidtion) {
TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8378");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_MESH_SHADER_EXTENSION_NAME);
AddRequiredFeature(vkt::Feature::extendedDynamicState3LogicOpEnable);
AddRequiredFeature(vkt::Feature::logicOp);
AddRequiredFeature(vkt::Feature::meshShader);
RETURN_IF_SKIP(Init());
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT); // tied to the frag shader
pipe.CreateGraphicsPipeline();
VkShaderObj ms(*m_device, kMeshMinimalGlsl, VK_SHADER_STAGE_MESH_BIT_EXT, SPV_ENV_VULKAN_1_2);
CreatePipelineHelper mesh_pipe(*this);
mesh_pipe.shader_stages_ = {ms.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
mesh_pipe.CreateGraphicsPipeline();
m_command_buffer.Begin();
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetLogicOpEnableEXT(m_command_buffer, VK_TRUE);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mesh_pipe);
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-07626");
vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u);
m_errorMonitor->VerifyFound();
m_command_buffer.EndRenderPass();
m_command_buffer.End();
}