blob: 65562ae78b1512e26f1bae4ca2aa169ab18fea21 [file] [log] [blame]
/*
* Copyright (c) 2015-2023 The Khronos Group Inc.
* Copyright (c) 2015-2023 Valve Corporation
* Copyright (c) 2015-2023 LunarG, Inc.
* Copyright (c) 2015-2023 Google, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include "../framework/layer_validation_tests.h"
#include "../framework/pipeline_helper.h"
#include "generated/vk_extension_helper.h"
void DynamicStateTest::InitBasicExtendedDynamicState() {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extended_dynamic_state_features = vku::InitStructHelper();
GetPhysicalDeviceFeatures2(extended_dynamic_state_features);
if (!extended_dynamic_state_features.extendedDynamicState) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState";
}
RETURN_IF_SKIP(InitState(nullptr, &extended_dynamic_state_features));
}
void DynamicStateTest::InitBasicExtendedDynamicState3(VkPhysicalDeviceExtendedDynamicState3FeaturesEXT &features) {
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
GetPhysicalDeviceFeatures2(features);
RETURN_IF_SKIP(InitState(nullptr, &features));
}
TEST_F(PositiveDynamicState, DiscardRectanglesVersion) {
TEST_DESCRIPTION("check version of VK_EXT_discard_rectangles");
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
if (!InstanceExtensionSupported(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME, 2)) {
GTEST_SKIP() << "need VK_EXT_discard_rectangles version 2";
}
RETURN_IF_SKIP(InitState())
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
pipe.InitState();
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
vk::CmdSetDiscardRectangleEnableEXT(m_commandBuffer->handle(), VK_TRUE);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, ViewportWithCountNoMultiViewport) {
TEST_DESCRIPTION("DynamicViewportWithCount/ScissorWithCount without multiViewport feature not enabled.");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extended_dynamic_state_features = vku::InitStructHelper();
auto features2 = GetPhysicalDeviceFeatures2(extended_dynamic_state_features);
if (!extended_dynamic_state_features.extendedDynamicState) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState";
}
// Ensure multiViewport feature is *not* enabled for this device
features2.features.multiViewport = 0;
RETURN_IF_SKIP(InitState(nullptr, &features2))
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 = 0;
pipe.vp_state_ci_.scissorCount = 0;
pipe.InitState();
pipe.CreateGraphicsPipeline();
}
TEST_F(PositiveDynamicState, CmdSetVertexInputEXT) {
TEST_DESCRIPTION("Test CmdSetVertexInputEXT");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT vertex_input_dynamic_state_features = vku::InitStructHelper();
auto features2 = GetPhysicalDeviceFeatures2(vertex_input_dynamic_state_features);
if (!vertex_input_dynamic_state_features.vertexInputDynamicState) {
GTEST_SKIP() << "Feature vertexInputDynamicState is not supported.";
}
RETURN_IF_SKIP(InitState(nullptr, &features2))
InitRenderTarget();
// Fill with bad data as should be ignored with dynamic state
VkVertexInputBindingDescription input_binding = {5, 7, VK_VERTEX_INPUT_RATE_VERTEX};
VkVertexInputAttributeDescription input_attrib = {5, 7, VK_FORMAT_UNDEFINED, 9};
VkPipelineVertexInputStateCreateInfo vi_ci = vku::InitStructHelper();
vi_ci.pVertexBindingDescriptions = &input_binding;
vi_ci.vertexBindingDescriptionCount = 1;
vi_ci.pVertexAttributeDescriptions = &input_attrib;
vi_ci.vertexAttributeDescriptionCount = 1;
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
pipe.InitState();
pipe.gp_ci_.pVertexInputState = &vi_ci; // ignored
pipe.CreateGraphicsPipeline();
VkVertexInputBindingDescription2EXT binding = vku::InitStructHelper();
binding.binding = 0;
binding.stride = sizeof(float);
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
binding.divisor = 1;
VkVertexInputAttributeDescription2EXT attribute = vku::InitStructHelper();
attribute.location = 0;
attribute.binding = 0;
attribute.format = VK_FORMAT_R32_SFLOAT;
attribute.offset = 0;
vkt::Buffer vtx_buf(*m_device, 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
VkDeviceSize offset = 0;
m_commandBuffer->begin();
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
vk::CmdBindVertexBuffers(m_commandBuffer->handle(), 0, 1, &vtx_buf.handle(), &offset);
vk::CmdSetVertexInputEXT(m_commandBuffer->handle(), 1, &binding, 1, &attribute);
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdDraw(m_commandBuffer->handle(), 1, 0, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, CmdSetVertexInputEXTStride) {
TEST_DESCRIPTION("Test CmdSetVertexInputEXT");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extdyn_features = vku::InitStructHelper();
VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT vertex_input_dynamic_state_features =
vku::InitStructHelper(&extdyn_features);
auto features2 = GetPhysicalDeviceFeatures2(vertex_input_dynamic_state_features);
if (!vertex_input_dynamic_state_features.vertexInputDynamicState) {
GTEST_SKIP() << "Feature vertexInputDynamicState is not supported.";
}
if (!extdyn_features.extendedDynamicState) {
GTEST_SKIP() << "Feature extendedDynamicState is not supported.";
}
RETURN_IF_SKIP(InitState(nullptr, &features2))
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VERTEX_INPUT_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
pipe.InitState();
pipe.gp_ci_.pVertexInputState = nullptr;
pipe.CreateGraphicsPipeline();
VkVertexInputBindingDescription2EXT binding = vku::InitStructHelper();
binding.binding = 0;
binding.stride = sizeof(float);
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
binding.divisor = 1;
VkVertexInputAttributeDescription2EXT attribute = vku::InitStructHelper();
attribute.location = 0;
attribute.binding = 0;
attribute.format = VK_FORMAT_R32_SFLOAT;
attribute.offset = 0;
vkt::Buffer vtx_buf(*m_device, 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
VkDeviceSize offset = 0;
m_commandBuffer->begin();
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
vk::CmdBindVertexBuffers(m_commandBuffer->handle(), 0, 1, &vtx_buf.handle(), &offset);
vk::CmdSetVertexInputEXT(m_commandBuffer->handle(), 1, &binding, 1, &attribute);
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdDraw(m_commandBuffer->handle(), 1, 0, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, ExtendedDynamicStateBindVertexBuffersMaintenance5) {
TEST_DESCRIPTION("VK_KHR_maintenance5 lets you use VK_WHOLE_SIZE with VK_EXT_extended_dynamic_state");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceMaintenance5FeaturesKHR maintenance5_features = vku::InitStructHelper();
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extended_dynamic_state_features = vku::InitStructHelper(&maintenance5_features);
GetPhysicalDeviceFeatures2(extended_dynamic_state_features);
RETURN_IF_SKIP(InitState(nullptr, &extended_dynamic_state_features));
m_commandBuffer->begin();
vkt::Buffer buffer(*m_device, 16, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
VkDeviceSize size = VK_WHOLE_SIZE;
VkDeviceSize offset = 0;
vk::CmdBindVertexBuffers2EXT(m_commandBuffer->handle(), 0, 1, &buffer.handle(), &offset, &size, nullptr);
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, DiscardRectanglesWithDynamicState) {
TEST_DESCRIPTION("Don't check discard rectangles if dynamic state is not set");
AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
RETURN_IF_SKIP(InitState())
InitRenderTarget();
// pass in struct, but don't set the dynamic state in the pipeline
VkPipelineDiscardRectangleStateCreateInfoEXT discard_rect_ci = vku::InitStructHelper();
discard_rect_ci.discardRectangleMode = VK_DISCARD_RECTANGLE_MODE_INCLUSIVE_EXT;
discard_rect_ci.discardRectangleCount = 4;
std::vector<VkRect2D> discard_rectangles(4);
discard_rect_ci.pDiscardRectangles = discard_rectangles.data();
CreatePipelineHelper pipe(*this);
pipe.gp_ci_.pNext = &discard_rect_ci;
pipe.InitState();
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, DynamicColorWriteNoColorAttachments) {
TEST_DESCRIPTION("Create a graphics pipeline with no color attachments, but use dynamic color write enable.");
AddRequiredExtensions(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
// Extension enabed as a dependency of VK_EXT_color_write_enable
VkPhysicalDeviceColorWriteEnableFeaturesEXT color_write_features = vku::InitStructHelper();
auto features2 = GetPhysicalDeviceFeatures2(color_write_features);
if (!color_write_features.colorWriteEnable) {
GTEST_SKIP() << "colorWriteEnable feature not supported";
}
RETURN_IF_SKIP(InitState(nullptr, &features2))
m_depth_stencil_fmt = FindSupportedDepthStencilFormat(gpu());
m_depthStencil->Init(m_width, m_height, 1, m_depth_stencil_fmt, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
VK_IMAGE_TILING_OPTIMAL);
VkImageView depth_image_view =
m_depthStencil->targetView(m_depth_stencil_fmt, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
InitRenderTarget(&depth_image_view);
CreatePipelineHelper pipe(*this);
pipe.InitState();
// Create a render pass without any color attachments
VkAttachmentReference attach = {};
attach.attachment = 0;
attach.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpasses = {};
subpasses.pDepthStencilAttachment = &attach;
VkAttachmentDescription attach_desc = {};
attach_desc.format = m_depth_stencil_fmt;
attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
attach_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
attach_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attach_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
attach_desc.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attach_desc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
VkRenderPassCreateInfo rpci = vku::InitStructHelper();
rpci.attachmentCount = 1;
rpci.pAttachments = &attach_desc;
rpci.subpassCount = 1;
rpci.pSubpasses = &subpasses;
vkt::RenderPass rp(*m_device, rpci);
VkFramebufferCreateInfo &fbci = m_framebuffer_info;
fbci.renderPass = rp.handle();
fbci.attachmentCount = 1;
fbci.pAttachments = &depth_image_view;
vkt::Framebuffer fb(*m_device, fbci);
// Enable dynamic color write enable
pipe.gp_ci_.renderPass = rp.handle();
// pColorBlendState is not required since there are no color attachments
pipe.gp_ci_.pColorBlendState = nullptr;
pipe.AddDynamicState(VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
pipe.ds_ci_ = vku::InitStructHelper();
pipe.ds_ci_.depthTestEnable = VK_TRUE;
pipe.ds_ci_.stencilTestEnable = VK_TRUE;
ASSERT_EQ(VK_SUCCESS, pipe.CreateGraphicsPipeline());
m_commandBuffer->begin();
m_renderPassBeginInfo.renderPass = rp.handle();
m_renderPassBeginInfo.framebuffer = fb.handle();
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
VkBool32 color_write_enable = VK_TRUE;
vk::CmdSetColorWriteEnableEXT(m_commandBuffer->handle(), 1, &color_write_enable);
vk::CmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_layout_.handle(), 0, 1,
&pipe.descriptor_set_->set_, 0, nullptr);
vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, DepthTestEnableOverridesPipelineDepthWriteEnable) {
RETURN_IF_SKIP(InitBasicExtendedDynamicState())
m_depth_stencil_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
m_clear_via_load_op = false;
m_depth_stencil_fmt = FindSupportedDepthStencilFormat(gpu());
VkImageObj ds_image(m_device);
ds_image.Init(m_width, m_height, 1, m_depth_stencil_fmt, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL,
0);
auto ds_view = ds_image.targetView(m_depth_stencil_fmt, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
InitRenderTarget(1, &ds_view);
VkPipelineDepthStencilStateCreateInfo ds_state = vku::InitStructHelper();
ds_state.depthWriteEnable = VK_TRUE;
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT);
pipe.ds_ci_ = ds_state;
pipe.InitState();
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetDepthTestEnableEXT(m_commandBuffer->handle(), VK_FALSE);
vk::CmdDraw(m_commandBuffer->handle(), 1, 1, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, DepthTestEnableOverridesDynamicDepthWriteEnable) {
TEST_DESCRIPTION("setting vkCmdSetDepthTestEnable to false cancels what ever is written to vkCmdSetDepthWriteEnable.");
RETURN_IF_SKIP(InitBasicExtendedDynamicState())
m_depth_stencil_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
m_clear_via_load_op = false;
m_depth_stencil_fmt = FindSupportedDepthStencilFormat(gpu());
VkImageObj ds_image(m_device);
ds_image.Init(m_width, m_height, 1, m_depth_stencil_fmt, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL,
0);
auto ds_view = ds_image.targetView(m_depth_stencil_fmt, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
InitRenderTarget(1, &ds_view);
VkPipelineDepthStencilStateCreateInfo ds_state = vku::InitStructHelper();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT);
pipe.ds_ci_ = ds_state;
pipe.InitState();
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetDepthTestEnableEXT(m_commandBuffer->handle(), VK_FALSE);
vk::CmdSetDepthWriteEnableEXT(m_commandBuffer->handle(), VK_TRUE);
vk::CmdDraw(m_commandBuffer->handle(), 1, 1, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, DynamicStateDoublePipelineBind) {
TEST_DESCRIPTION("Validate binding a non-dynamic pipeline doesn't trigger dynamic static errors");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceExtendedDynamicState2FeaturesEXT extended_dynamic_state2_features = vku::InitStructHelper();
GetPhysicalDeviceFeatures2(extended_dynamic_state2_features);
if (!extended_dynamic_state2_features.extendedDynamicState2) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState2, skipping";
}
RETURN_IF_SKIP(InitState(nullptr, &extended_dynamic_state2_features));
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT);
pipe.InitState();
pipe.CreateGraphicsPipeline();
CreatePipelineHelper pipe_no_dynamic(*this);
pipe_no_dynamic.InitState();
pipe_no_dynamic.CreateGraphicsPipeline();
vkt::CommandBuffer command_buffer(m_device, m_commandPool);
command_buffer.begin();
vk::CmdSetPrimitiveRestartEnableEXT(command_buffer.handle(), VK_TRUE);
command_buffer.BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_no_dynamic.pipeline_);
vk::CmdBindPipeline(command_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
vk::CmdDraw(command_buffer.handle(), 1, 1, 0, 0);
vk::CmdEndRenderPass(command_buffer.handle());
command_buffer.end();
}
TEST_F(PositiveDynamicState, SetBeforePipeline) {
TEST_DESCRIPTION("Pipeline set state, but prior to last bound pipeline that had it");
RETURN_IF_SKIP(Init())
InitRenderTarget();
CreatePipelineHelper pipe_line(*this);
pipe_line.AddDynamicState(VK_DYNAMIC_STATE_LINE_WIDTH);
pipe_line.InitState();
pipe_line.CreateGraphicsPipeline();
CreatePipelineHelper pipe_blend(*this);
pipe_blend.AddDynamicState(VK_DYNAMIC_STATE_BLEND_CONSTANTS);
pipe_blend.InitState();
pipe_blend.CreateGraphicsPipeline();
m_commandBuffer->begin();
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdSetLineWidth(m_commandBuffer->handle(), 1.0f);
float blends[4] = {1.0f, 1.0f, 1.0f, 1.0f};
vk::CmdSetBlendConstants(m_commandBuffer->handle(), blends);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_line.pipeline_);
vk::CmdDraw(m_commandBuffer->handle(), 1, 0, 0, 0);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_blend.pipeline_);
vk::CmdDraw(m_commandBuffer->handle(), 1, 0, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, AttachmentFeedbackLoopEnable) {
TEST_DESCRIPTION("Use vkCmdSetAttachmentFeedbackLoopEnableEXT correctly");
AddRequiredExtensions(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT feedback_loop_dynamic_features = vku::InitStructHelper();
VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT feedback_loop_features =
vku::InitStructHelper(&feedback_loop_dynamic_features);
GetPhysicalDeviceFeatures2(feedback_loop_features);
RETURN_IF_SKIP(InitState(nullptr, &feedback_loop_features));
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
pipe.InitState();
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
vk::CmdSetAttachmentFeedbackLoopEnableEXT(m_commandBuffer->handle(), VK_IMAGE_ASPECT_COLOR_BIT);
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(*m_commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
vk::CmdDraw(*m_commandBuffer, 3, 1, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, SetDepthBias2EXTDepthBiasClampEnabled) {
TEST_DESCRIPTION("Call vkCmdSetDepthBias2EXT with VkPhysicalDeviceFeatures::depthBiasClamp feature enabled");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceExtendedDynamicState2FeaturesEXT extended_dynamic_state2_features = vku::InitStructHelper();
VkPhysicalDeviceDepthBiasControlFeaturesEXT depth_bias_control_features =
vku::InitStructHelper(&extended_dynamic_state2_features);
auto features2 = GetPhysicalDeviceFeatures2(depth_bias_control_features);
if (!extended_dynamic_state2_features.extendedDynamicState2) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState2, skipping";
}
if (!depth_bias_control_features.depthBiasControl) {
GTEST_SKIP() << "depthBiasControl not supported";
}
if (!features2.features.depthBiasClamp) {
GTEST_SKIP() << "depthBiasClamp not supported";
}
RETURN_IF_SKIP(InitState(nullptr, &features2))
InitRenderTarget();
// Create a pipeline with a dynamically set depth bias
CreatePipelineHelper pipe(*this);
pipe.InitState();
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS);
VkPipelineRasterizationStateCreateInfo raster_state = vku::InitStructHelper();
raster_state.depthBiasEnable = VK_TRUE;
pipe.rs_state_ci_ = raster_state;
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
vk::CmdSetDepthBiasEnableEXT(m_commandBuffer->handle(), 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;
vk::CmdSetDepthBias2EXT(m_commandBuffer->handle(), &depth_bias_info);
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle());
vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0,
0); // Without correct state tracking, VUID-vkCmdDraw-None-07834 would be thrown here
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, 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);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceExtendedDynamicState2FeaturesEXT extended_dynamic_state2_features = vku::InitStructHelper();
VkPhysicalDeviceDepthBiasControlFeaturesEXT depth_bias_control_features =
vku::InitStructHelper(&extended_dynamic_state2_features);
auto features2 = GetPhysicalDeviceFeatures2(depth_bias_control_features);
if (!extended_dynamic_state2_features.extendedDynamicState2) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState2, skipping";
}
if (!depth_bias_control_features.depthBiasControl) {
GTEST_SKIP() << "depthBiasControl not supported";
}
features2.features.depthBiasClamp = VK_FALSE;
RETURN_IF_SKIP(InitState(nullptr, &features2))
InitRenderTarget();
// Create a pipeline with a dynamically set depth bias
CreatePipelineHelper pipe(*this);
pipe.InitState();
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS);
VkPipelineRasterizationStateCreateInfo raster_state = vku::InitStructHelper();
raster_state.depthBiasEnable = VK_TRUE;
pipe.rs_state_ci_ = raster_state;
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
vk::CmdSetDepthBiasEnableEXT(m_commandBuffer->handle(), VK_TRUE);
VkDepthBiasInfoEXT depth_bias_info = vku::InitStructHelper();
depth_bias_info.depthBiasConstantFactor = 1.0f;
depth_bias_info.depthBiasClamp = 0.0f; // depthBiasClamp feature is disabled, so depth_bias_info.depthBiasClamp must be 0
depth_bias_info.depthBiasSlopeFactor = 1.0f;
vk::CmdSetDepthBias2EXT(m_commandBuffer->handle(), &depth_bias_info);
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle());
vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0,
0); // Without correct state tracking, VUID-vkCmdDraw-None-07834 would be thrown here
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, SetDepthBias2EXTDepthBiasWithDepthBiasRepresentationInfo) {
TEST_DESCRIPTION(
"Call vkCmdSetDepthBias2EXT with VkDepthBiasRepresentationInfoEXT and VkPhysicalDeviceFeatures::depthBiasClamp and "
"VkPhysicalDeviceDepthBiasControlFeaturesEXT "
"features enabled");
SetTargetApiVersion(VK_API_VERSION_1_2);
AddRequiredExtensions(VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceExtendedDynamicState2FeaturesEXT extended_dynamic_state2_features = vku::InitStructHelper();
VkPhysicalDeviceDepthBiasControlFeaturesEXT depth_bias_control_features =
vku::InitStructHelper(&extended_dynamic_state2_features);
auto features2 = GetPhysicalDeviceFeatures2(depth_bias_control_features);
if (!extended_dynamic_state2_features.extendedDynamicState2) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState2, skipping";
}
if (!depth_bias_control_features.leastRepresentableValueForceUnormRepresentation) {
GTEST_SKIP() << "leastRepresentableValueForceUnormRepresentation not supported";
}
if (!depth_bias_control_features.floatRepresentation) {
GTEST_SKIP() << "floatRepresentation not supported";
}
if (!depth_bias_control_features.depthBiasExact) {
GTEST_SKIP() << "depthBiasExact not supported";
}
if (!features2.features.depthBiasClamp) {
GTEST_SKIP() << "depthBiasClamp not supported";
}
RETURN_IF_SKIP(InitState(nullptr, &features2))
InitRenderTarget();
// Create a pipeline with a dynamically set depth bias
CreatePipelineHelper pipe(*this);
pipe.InitState();
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS);
VkPipelineRasterizationStateCreateInfo raster_state = vku::InitStructHelper();
raster_state.depthBiasEnable = VK_TRUE;
pipe.rs_state_ci_ = raster_state;
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
vk::CmdSetDepthBiasEnableEXT(m_commandBuffer->handle(), 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;
vk::CmdSetDepthBias2EXT(m_commandBuffer->handle(), &depth_bias_info);
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.Handle());
// Without correct state tracking, VUID-vkCmdDraw-None-07834 would be thrown here and in the follow-up calls
vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
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;
vk::CmdSetDepthBias2EXT(m_commandBuffer->handle(), &depth_bias_info);
vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
depth_bias_representation.depthBiasRepresentation = VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT;
vk::CmdSetDepthBias2EXT(m_commandBuffer->handle(), &depth_bias_info);
vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, AlphaToCoverageSetFalse) {
TEST_DESCRIPTION("Dynamically set alphaToCoverageEnabled to false so its not checked.");
VkPhysicalDeviceExtendedDynamicState3FeaturesEXT extended_dynamic_state_features = vku::InitStructHelper();
RETURN_IF_SKIP(InitBasicExtendedDynamicState3(extended_dynamic_state_features))
if (!extended_dynamic_state_features.extendedDynamicState3AlphaToCoverageEnable) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState3AlphaToCoverageEnable";
}
InitRenderTarget();
char const *fsSource = R"glsl(
#version 450
layout(location = 0) out float x;
void main(){
x = 1.0;
}
)glsl";
VkShaderObj fs(this, 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_TRUE; // 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.pipe_ms_state_ci_ = ms_state_ci;
pipe.InitState();
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
vk::CmdSetAlphaToCoverageEnableEXT(m_commandBuffer->handle(), VK_FALSE);
vk::CmdDraw(m_commandBuffer->handle(), 1, 0, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, AlphaToCoverageSetTrue) {
TEST_DESCRIPTION("Dynamically set alphaToCoverageEnabled to true, but have component set.");
VkPhysicalDeviceExtendedDynamicState3FeaturesEXT extended_dynamic_state_features = vku::InitStructHelper();
RETURN_IF_SKIP(InitBasicExtendedDynamicState3(extended_dynamic_state_features))
if (!extended_dynamic_state_features.extendedDynamicState3AlphaToCoverageEnable) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState3AlphaToCoverageEnable";
}
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
pipe.InitState();
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
vk::CmdSetAlphaToCoverageEnableEXT(m_commandBuffer->handle(), VK_TRUE);
vk::CmdDraw(m_commandBuffer->handle(), 1, 0, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, MultisampleStateIgnored) {
TEST_DESCRIPTION("Ignore null pMultisampleState, with alphaToOne disabled");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceExtendedDynamicState3FeaturesEXT extended_dynamic_state3_features = vku::InitStructHelper();
auto features2 = GetPhysicalDeviceFeatures2(extended_dynamic_state3_features);
if (!extended_dynamic_state3_features.extendedDynamicState3RasterizationSamples) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState3RasterizationSamples";
}
if (!extended_dynamic_state3_features.extendedDynamicState3SampleMask) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState3SampleMask";
}
if (!extended_dynamic_state3_features.extendedDynamicState3AlphaToCoverageEnable) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState3AlphaToCoverageEnable";
}
if (!extended_dynamic_state3_features.extendedDynamicState3AlphaToOneEnable) {
GTEST_SKIP() << "extendedDynamicState3AlphaToOneEnable not supported";
}
features2.features.alphaToOne = VK_FALSE;
RETURN_IF_SKIP(InitState(nullptr, &features2))
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);
pipe.gp_ci_.pMultisampleState = nullptr;
pipe.InitState();
pipe.CreateGraphicsPipeline();
}
TEST_F(PositiveDynamicState, MultisampleStateIgnoredAlphaToOne) {
TEST_DESCRIPTION("Ignore null pMultisampleState with alphaToOne enabled");
VkPhysicalDeviceExtendedDynamicState3FeaturesEXT extended_dynamic_state3_features = vku::InitStructHelper();
RETURN_IF_SKIP(InitBasicExtendedDynamicState3(extended_dynamic_state3_features))
if (!extended_dynamic_state3_features.extendedDynamicState3RasterizationSamples) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState3RasterizationSamples";
}
if (!extended_dynamic_state3_features.extendedDynamicState3SampleMask) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState3SampleMask";
}
if (!extended_dynamic_state3_features.extendedDynamicState3AlphaToCoverageEnable) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState3AlphaToCoverageEnable";
}
if (!extended_dynamic_state3_features.extendedDynamicState3AlphaToOneEnable) {
GTEST_SKIP() << "Test requires (unsupported) extendedDynamicState3AlphaToOneEnable";
}
if (!m_device->phy().features().alphaToOne) {
GTEST_SKIP() << "Test requires (unsupported) alphaToOne";
}
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);
pipe.AddDynamicState(VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT);
pipe.gp_ci_.pMultisampleState = nullptr;
pipe.InitState();
pipe.CreateGraphicsPipeline();
}
TEST_F(PositiveDynamicState, InputAssemblyStateIgnored) {
TEST_DESCRIPTION("Ignore null pInputAssemblyState");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extended_dynamic_state_features = vku::InitStructHelper();
VkPhysicalDeviceExtendedDynamicState2FeaturesEXT extended_dynamic_state2_features =
vku::InitStructHelper(&extended_dynamic_state_features);
VkPhysicalDeviceExtendedDynamicState3FeaturesEXT extended_dynamic_state3_features =
vku::InitStructHelper(&extended_dynamic_state2_features);
RETURN_IF_SKIP(InitBasicExtendedDynamicState3(extended_dynamic_state3_features))
InitRenderTarget();
VkPhysicalDeviceExtendedDynamicState3PropertiesEXT dynamic_state_3_props = vku::InitStructHelper();
GetPhysicalDeviceProperties2(dynamic_state_3_props);
if (!dynamic_state_3_props.dynamicPrimitiveTopologyUnrestricted) {
GTEST_SKIP() << "dynamicPrimitiveTopologyUnrestricted is VK_FALSE";
}
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
pipe.AddDynamicState(VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY);
pipe.gp_ci_.pInputAssemblyState = nullptr;
pipe.InitState();
pipe.CreateGraphicsPipeline();
}
TEST_F(PositiveDynamicState, ViewportStateIgnored) {
TEST_DESCRIPTION("Ignore null pViewportState");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extended_dynamic_state_features = vku::InitStructHelper();
GetPhysicalDeviceFeatures2(extended_dynamic_state_features);
RETURN_IF_SKIP(InitState(nullptr, &extended_dynamic_state_features));
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.rs_state_ci_.rasterizerDiscardEnable = VK_FALSE;
pipe.gp_ci_.pViewportState = nullptr;
pipe.InitState();
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT);
pipe.CreateGraphicsPipeline();
}
TEST_F(PositiveDynamicState, ColorBlendStateIgnored) {
TEST_DESCRIPTION("Ignore null pColorBlendState");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
VkPhysicalDeviceExtendedDynamicState2FeaturesEXT extended_dynamic_state2_features = vku::InitStructHelper();
VkPhysicalDeviceExtendedDynamicState3FeaturesEXT extended_dynamic_state3_features =
vku::InitStructHelper(&extended_dynamic_state2_features);
RETURN_IF_SKIP(InitBasicExtendedDynamicState3(extended_dynamic_state3_features))
InitRenderTarget();
if (!extended_dynamic_state3_features.extendedDynamicState3LogicOpEnable) {
GTEST_SKIP() << "extendedDynamicState3LogicOpEnable not supported";
}
if (!extended_dynamic_state3_features.extendedDynamicState3ColorBlendEnable) {
GTEST_SKIP() << "extendedDynamicState3ColorBlendEnable not supported";
}
if (!extended_dynamic_state3_features.extendedDynamicState3ColorBlendEquation) {
GTEST_SKIP() << "extendedDynamicState3ColorBlendEquation not supported";
}
if (!extended_dynamic_state3_features.extendedDynamicState3ColorWriteMask) {
GTEST_SKIP() << "extendedDynamicState3ColorWriteMask not supported";
}
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_LOGIC_OP_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 = {};
att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR;
att_state.blendEnable = VK_TRUE;
pipe.cb_attachments_[0] = att_state;
pipe.gp_ci_.pColorBlendState = nullptr;
pipe.InitState();
pipe.CreateGraphicsPipeline();
}
TEST_F(PositiveDynamicState, DepthBoundsTestEnableState) {
TEST_DESCRIPTION("Dynamically set depthBoundsTestEnable and not call vkCmdSetDepthBounds before the draw");
AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT extended_dynamic_state_features = vku::InitStructHelper();
GetPhysicalDeviceFeatures2(extended_dynamic_state_features);
RETURN_IF_SKIP(InitState(nullptr, &extended_dynamic_state_features));
if (!extended_dynamic_state_features.extendedDynamicState) {
GTEST_SKIP() << "extendedDynamicState no supported";
}
// Need to set format framework uses for InitRenderTarget
m_depth_stencil_fmt = FindSupportedDepthStencilFormat(gpu());
m_depthStencil->Init(m_width, m_height, 1, m_depth_stencil_fmt,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_TILING_OPTIMAL);
VkImageView depth_image_view =
m_depthStencil->targetView(m_depth_stencil_fmt, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
InitRenderTarget(&depth_image_view);
CreatePipelineHelper pipe(*this);
pipe.InitState();
pipe.ds_ci_ = vku::InitStructHelper();
pipe.ds_ci_.depthTestEnable = VK_TRUE; // ignored
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS);
pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE);
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
vk::CmdSetDepthBoundsTestEnableEXT(m_commandBuffer->handle(), VK_FALSE);
// don't need vkCmdSetDepthBounds since test is disabled now
vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
}
TEST_F(PositiveDynamicState, ViewportInheritance) {
TEST_DESCRIPTION("Dynamically set viewport multiple times");
AddRequiredExtensions(VK_NV_INHERITED_VIEWPORT_SCISSOR_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
auto inherited_viewport_scissor_features = vku::InitStruct<VkPhysicalDeviceInheritedViewportScissorFeaturesNV>();
GetPhysicalDeviceFeatures2(inherited_viewport_scissor_features);
RETURN_IF_SKIP(InitState(nullptr, &inherited_viewport_scissor_features));
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.InitState();
pipe.vp_state_ci_.viewportCount = 2u;
pipe.vp_state_ci_.scissorCount = 2u;
pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR);
pipe.CreateGraphicsPipeline();
vkt::CommandBuffer cmd_buffer(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
vkt::CommandBuffer set_state(m_device, m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
const VkViewport viewports[2] = {{0.0f, 0.0f, 100.0f, 100.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 100.0f, 100.0f, 0.0f, 1.0f}};
const VkRect2D scissors[2] = {{{0, 0}, {100u, 100u}}, {{0, 0}, {100u, 100u}}};
auto viewport_scissor_inheritance = vku::InitStruct<VkCommandBufferInheritanceViewportScissorInfoNV>();
viewport_scissor_inheritance.viewportScissor2D = VK_TRUE;
viewport_scissor_inheritance.viewportDepthCount = 2u;
viewport_scissor_inheritance.pViewportDepths = viewports;
auto hinfo = vku::InitStruct<VkCommandBufferInheritanceInfo>(&viewport_scissor_inheritance);
hinfo.renderPass = m_renderPass;
hinfo.subpass = 0;
hinfo.framebuffer = m_framebuffer;
auto info = vku::InitStruct<VkCommandBufferBeginInfo>();
info.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
info.pInheritanceInfo = &hinfo;
cmd_buffer.begin(&info);
vk::CmdBindPipeline(cmd_buffer.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
vk::CmdDraw(cmd_buffer.handle(), 3, 1, 0, 0);
cmd_buffer.end();
set_state.begin();
vk::CmdSetViewport(set_state.handle(), 1u, 1u, &viewports[1]);
set_state.end();
m_commandBuffer->begin();
vk::CmdSetViewport(m_commandBuffer->handle(), 0u, 2u, viewports);
vk::CmdSetViewport(m_commandBuffer->handle(), 0u, 1u, viewports);
vk::CmdSetScissor(m_commandBuffer->handle(), 0u, 2u, scissors);
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
vk::CmdExecuteCommands(m_commandBuffer->handle(), 1u, &cmd_buffer.handle());
m_commandBuffer->EndRenderPass();
m_commandBuffer->end();
auto submit_info = vku::InitStruct<VkSubmitInfo>();
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &m_commandBuffer->handle();
vk::QueueSubmit(m_default_queue, 1, &submit_info, VK_NULL_HANDLE);
vk::QueueWaitIdle(m_default_queue);
}
TEST_F(PositiveDynamicState, AttachmentFeedbackLoopEnableAspectMask) {
TEST_DESCRIPTION("Valid aspect masks for vkCmdSetAttachmentFeedbackLoopEnableEXT");
AddRequiredExtensions(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_DYNAMIC_STATE_EXTENSION_NAME);
RETURN_IF_SKIP(InitFramework())
VkPhysicalDeviceAttachmentFeedbackLoopDynamicStateFeaturesEXT feedback_loop_dynamic_features = vku::InitStructHelper();
VkPhysicalDeviceAttachmentFeedbackLoopLayoutFeaturesEXT feedback_loop_features =
vku::InitStructHelper(&feedback_loop_dynamic_features);
GetPhysicalDeviceFeatures2(feedback_loop_features);
RETURN_IF_SKIP(InitState(nullptr, &feedback_loop_features));
InitRenderTarget();
CreatePipelineHelper pipe(*this);
pipe.AddDynamicState(VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
pipe.InitState();
pipe.CreateGraphicsPipeline();
m_commandBuffer->begin();
vk::CmdSetAttachmentFeedbackLoopEnableEXT(m_commandBuffer->handle(), VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
m_commandBuffer->end();
}