| /* |
| * 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) 2020 Advanced Micro Devices, Inc. All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| */ |
| |
| #include <vulkan/vulkan_core.h> |
| #include "utils/cast_utils.h" |
| #include "../framework/layer_validation_tests.h" |
| #include "../framework/pipeline_helper.h" |
| #include "../framework/descriptor_helper.h" |
| #include "../framework/render_pass_helper.h" |
| #include "../framework/shader_helper.h" |
| |
| class NegativePipeline : public VkLayerTest {}; |
| |
| TEST_F(NegativePipeline, NotBound) { |
| TEST_DESCRIPTION("Pass in an invalid pipeline object handle into a Vulkan API call."); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdBindPipeline-pipeline-parameter"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipeline badPipeline = CastToHandle<VkPipeline, uintptr_t>(0xbaadb1be); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, badPipeline); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, WrongBindPointGraphics) { |
| TEST_DESCRIPTION("Bind a compute pipeline in the graphics bind point"); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdBindPipeline-pipelineBindPoint-00779"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, BasicCompute) { |
| TEST_DESCRIPTION("Bind a compute pipeline (no subpasses)"); |
| RETURN_IF_SKIP(Init()); |
| |
| const char *cs = R"glsl(#version 450 |
| layout(local_size_x=1) in; |
| layout(set=0, binding=0) uniform block { vec4 x; }; |
| void main(){ |
| vec4 v = 2.0 * x; |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, cs, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.CreateComputePipeline(); |
| |
| vkt::Buffer buffer(*m_device, 1024, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); |
| pipe.descriptor_set_.WriteDescriptorBufferInfo(0, buffer, 0, 1024); |
| pipe.descriptor_set_.UpdateDescriptorSets(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe.pipeline_layout_, 0, 1, |
| &pipe.descriptor_set_.set_, 0, nullptr); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| } |
| |
| TEST_F(NegativePipeline, WrongBindPointCompute) { |
| TEST_DESCRIPTION("Bind a graphics pipeline in the compute bind point"); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdBindPipeline-pipelineBindPoint-00780"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, DisabledIndependentBlend) { |
| TEST_DESCRIPTION( |
| "Generate INDEPENDENT_BLEND by disabling independent blend and then specifying different blend states for two " |
| "attachments"); |
| VkPhysicalDeviceFeatures features = {}; |
| features.independentBlend = VK_FALSE; |
| RETURN_IF_SKIP(Init(&features)); |
| |
| // Create a renderPass with two color attachments |
| RenderPassSingleSubpass rp(*this); |
| rp.AddAttachmentDescription(VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_GENERAL); |
| rp.AddAttachmentDescription(VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_GENERAL); |
| rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL}); |
| rp.AddAttachmentReference({1, VK_IMAGE_LAYOUT_GENERAL}); |
| rp.AddColorAttachment(0); |
| rp.AddColorAttachment(1); |
| rp.CreateRenderPass(); |
| |
| VkPipelineColorBlendAttachmentState cb_attachments[2]; |
| memset(cb_attachments, 0, sizeof(VkPipelineColorBlendAttachmentState) * 2); |
| cb_attachments[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR; |
| cb_attachments[0].blendEnable = VK_TRUE; |
| cb_attachments[1].dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR; |
| cb_attachments[1].blendEnable = VK_FALSE; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.renderPass = rp; |
| pipe.cb_ci_.attachmentCount = 2; |
| pipe.cb_ci_.pAttachments = cb_attachments; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, BlendingOnFormatWithoutBlendingSupport) { |
| TEST_DESCRIPTION("Test that blending is not enabled with a format not support blending"); |
| VkPhysicalDeviceFeatures features = {}; |
| features.independentBlend = VK_FALSE; |
| RETURN_IF_SKIP(Init(&features)); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-06041"); |
| |
| VkFormat non_blending_format = VK_FORMAT_UNDEFINED; |
| for (uint32_t i = 1; i <= VK_FORMAT_ASTC_12x12_SRGB_BLOCK; i++) { |
| VkFormatFeatureFlags2 format_features = m_device->FormatFeaturesOptimal(static_cast<VkFormat>(i)); |
| if ((format_features & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) && |
| !(format_features & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)) { |
| non_blending_format = static_cast<VkFormat>(i); |
| break; |
| } |
| } |
| |
| if (non_blending_format == VK_FORMAT_UNDEFINED) { |
| GTEST_SKIP() << "Unable to find a color attachment format with no blending support"; |
| } |
| |
| RenderPassSingleSubpass rp(*this); |
| rp.AddAttachmentDescription(non_blending_format, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_GENERAL); |
| rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL}); |
| rp.AddColorAttachment(0); |
| rp.CreateRenderPass(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.renderPass = rp; |
| pipe.cb_attachments_.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR; |
| pipe.cb_attachments_.blendEnable = VK_TRUE; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, ColorWriteMaskE5B9G9R9) { |
| RETURN_IF_SKIP(Init()); |
| if (!(m_device->FormatFeaturesOptimal(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT)) { |
| GTEST_SKIP() << "Device does not support VK_FORMAT_E5B9G9R9_UFLOAT_PACK32"; |
| } |
| |
| RenderPassSingleSubpass rp(*this); |
| rp.AddAttachmentDescription(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); |
| rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL}); |
| rp.AddColorAttachment(0); |
| rp.CreateRenderPass(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.renderPass = rp; |
| pipe.cb_attachments_.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_A_BIT; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-None-09043"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| |
| pipe.cb_attachments_.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-None-09043"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Is the Pipeline compatible with the expectations of the Renderpass/subpasses? |
| TEST_F(NegativePipeline, PipelineRenderpassCompatibility) { |
| TEST_DESCRIPTION( |
| "Create a graphics pipeline that is incompatible with the requirements of its contained Renderpass/subpasses."); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineColorBlendAttachmentState att_state1 = {}; |
| att_state1.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR; |
| att_state1.blendEnable = VK_TRUE; |
| |
| auto set_info = [&](CreatePipelineHelper &helper) { |
| helper.cb_attachments_ = att_state1; |
| helper.gp_ci_.pColorBlendState = nullptr; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-renderPass-09030"); |
| } |
| |
| TEST_F(NegativePipeline, CmdBufferPipelineDestroyed) { |
| TEST_DESCRIPTION("Attempt to draw with a command buffer that is invalid due to a pipeline dependency being destroyed."); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| { |
| // Use helper to create graphics pipeline |
| CreatePipelineHelper helper(*this); |
| helper.CreateGraphicsPipeline(); |
| |
| // Bind helper pipeline to command buffer |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, helper); |
| m_command_buffer.End(); |
| |
| // pipeline will be destroyed when helper goes out of scope |
| } |
| |
| // Cause error by submitting command buffer that references destroyed pipeline |
| m_errorMonitor->SetDesiredError("VUID-vkQueueSubmit-pCommandBuffers-00070"); |
| m_default_queue->SubmitAndWait(m_command_buffer); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, BadPipelineObject) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| constexpr uint64_t fake_pipeline_handle = 0xbaad6001; |
| VkPipeline bad_pipeline = CastFromUint64<VkPipeline>(fake_pipeline_handle); |
| |
| // Enable VK_KHR_draw_indirect_count for KHR variants |
| AddOptionalExtensions(VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()); |
| |
| VkPhysicalDeviceVulkan12Features features12 = vku::InitStructHelper(); |
| GetPhysicalDeviceFeatures2(features12); |
| bool has_khr_indirect = IsExtensionsEnabled(VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME); |
| if (has_khr_indirect && !features12.drawIndirectCount) { |
| GTEST_SKIP() << VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME << " is enabled, but the drawIndirectCount is not supported."; |
| } |
| |
| if (features12.drawIndirectCount) { |
| AddRequiredFeature(vkt::Feature::drawIndirectCount); |
| } |
| RETURN_IF_SKIP(InitState()); |
| InitRenderTarget(); |
| |
| // Attempt to bind an invalid Pipeline to a valid Command Buffer |
| m_errorMonitor->SetDesiredError("VUID-vkCmdBindPipeline-pipeline-parameter"); |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bad_pipeline); |
| m_errorMonitor->VerifyFound(); |
| |
| // Try each of the 6 flavors of Draw() |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); // Draw*() calls must be submitted within a renderpass |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08606"); |
| vk::CmdDraw(m_command_buffer, 1, 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| vkt::Buffer index_buffer(*m_device, 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); |
| vk::CmdBindIndexBuffer(m_command_buffer, index_buffer, 2, VK_INDEX_TYPE_UINT16); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDrawIndexed-None-08606"); |
| vk::CmdDrawIndexed(m_command_buffer, 1, 1, 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| vkt::Buffer buffer(*m_device, 1024, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDrawIndirect-None-08606"); |
| vk::CmdDrawIndirect(m_command_buffer, buffer, 0, 1, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDrawIndexedIndirect-None-08606"); |
| vk::CmdDrawIndexedIndirect(m_command_buffer, buffer, 0, 1, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| if (has_khr_indirect) { |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDrawIndirectCount-None-08606"); |
| // stride must be a multiple of 4 and must be greater than or equal to sizeof(VkDrawIndirectCommand) |
| vk::CmdDrawIndirectCountKHR(m_command_buffer, buffer, 0, buffer, 512, 1, 512); |
| m_errorMonitor->VerifyFound(); |
| |
| if (DeviceValidationVersion() >= VK_API_VERSION_1_2) { |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDrawIndirectCount-None-08606"); |
| // stride must be a multiple of 4 and must be greater than or equal to sizeof(VkDrawIndirectCommand) |
| vk::CmdDrawIndirectCount(m_command_buffer, buffer, 0, buffer, 512, 1, 512); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDrawIndexedIndirectCount-None-08606"); |
| // stride must be a multiple of 4 and must be greater than or equal to sizeof(VkDrawIndexedIndirectCommand) |
| vk::CmdDrawIndexedIndirectCountKHR(m_command_buffer, buffer, 0, buffer, 512, 1, 512); |
| m_errorMonitor->VerifyFound(); |
| |
| if (DeviceValidationVersion() >= VK_API_VERSION_1_2) { |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDrawIndexedIndirectCount-None-08606"); |
| // stride must be a multiple of 4 and must be greater than or equal to sizeof(VkDrawIndexedIndirectCommand) |
| vk::CmdDrawIndexedIndirectCount(m_command_buffer, buffer, 0, buffer, 512, 1, 512); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| // Also try the Dispatch variants |
| m_command_buffer.EndRenderPass(); // Compute submissions must be outside a renderpass |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-08606"); |
| vk::CmdDispatch(m_command_buffer, 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDispatchIndirect-None-08606"); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDispatchIndirect-offset-00407"); |
| vk::CmdDispatchIndirect(m_command_buffer, buffer, 1024); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, NoPipelineDynamicState) { |
| TEST_DESCRIPTION("Call vkCmdDraw when there are no shaders or pipeline bound."); |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| RETURN_IF_SKIP(Init()); |
| InitDynamicRenderTarget(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderingColor(GetDynamicRenderTarget(), GetRenderTargetArea()); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-None-08606"); |
| vk::CmdDraw(m_command_buffer, 4, 1, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativePipeline, ShaderStageName) { |
| TEST_DESCRIPTION("Create Pipelines with invalid state set"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkShaderObj vs(*m_device, kVertexMinimalGlsl, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(*m_device, kFragmentMinimalGlsl, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| // Attempt to Create Gfx Pipeline w/o a VS |
| VkPipelineShaderStageCreateInfo shaderStage = fs.GetStageCreateInfo(); // should be: vs.GetStageCreateInfo(); |
| |
| auto set_info = [&](CreatePipelineHelper &helper) { helper.shader_stages_ = {shaderStage}; }; |
| constexpr std::array vuids = {"VUID-VkGraphicsPipelineCreateInfo-pStages-06896", |
| "VUID-VkGraphicsPipelineCreateInfo-stage-02096"}; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, vuids); |
| |
| // Finally, check the string validation for the shader stage pName variable. Correct the shader stage data, and bork the |
| // string before calling again |
| shaderStage = vs.GetStageCreateInfo(); |
| const uint8_t cont_char = 0xf8; |
| char bad_string[] = {static_cast<char>(cont_char), static_cast<char>(cont_char), static_cast<char>(cont_char), |
| static_cast<char>(cont_char)}; |
| shaderStage.pName = bad_string; |
| |
| // VUID-VkPipelineShaderStageCreateInfo-pName-parameter |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "contains invalid characters or is badly formed"); |
| } |
| |
| TEST_F(NegativePipeline, ShaderStageBit) { |
| TEST_DESCRIPTION("Create Pipelines with invalid state set"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| // Make sure compute pipeline has a compute shader stage set |
| const char *csSource = R"glsl( |
| #version 450 |
| layout(local_size_x=1, local_size_y=1, local_size_z=1) in; |
| void main(){ |
| if (gl_GlobalInvocationID.x >= 0) { return; } |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper cs_pipeline(*this); |
| cs_pipeline.cs_ = VkShaderObj(*m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT); |
| cs_pipeline.pipeline_layout_ = vkt::PipelineLayout(*m_device, {}); |
| cs_pipeline.LateBindPipelineInfo(); |
| cs_pipeline.cp_ci_.stage.stage = VK_SHADER_STAGE_VERTEX_BIT; // override with wrong value |
| m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-stage-00701"); |
| cs_pipeline.CreateComputePipeline(false); // need false to prevent late binding |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, SampleRateFeatureDisable) { |
| // Enable sample shading in pipeline when the feature is disabled. |
| // Disable sampleRateShading here |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| // Cause the error by enabling sample shading... |
| auto set_shading_enable = [](CreatePipelineHelper &helper) { helper.ms_ci_.sampleShadingEnable = VK_TRUE; }; |
| CreatePipelineHelper::OneshotTest(*this, set_shading_enable, kErrorBit, |
| "VUID-VkPipelineMultisampleStateCreateInfo-sampleShadingEnable-00784"); |
| } |
| |
| TEST_F(NegativePipeline, SampleRateFeatureEnable) { |
| // Enable sample shading in pipeline when the feature is disabled. |
| AddRequiredFeature(vkt::Feature::sampleRateShading); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| auto range_test = [this](float value, bool positive_test) { |
| auto info_override = [value](CreatePipelineHelper &helper) { |
| helper.ms_ci_.sampleShadingEnable = VK_TRUE; |
| helper.ms_ci_.minSampleShading = value; |
| }; |
| if (positive_test) { |
| CreatePipelineHelper::OneshotTest(*this, info_override, kErrorBit); |
| } else { |
| CreatePipelineHelper::OneshotTest(*this, info_override, kErrorBit, |
| "VUID-VkPipelineMultisampleStateCreateInfo-minSampleShading-00786"); |
| } |
| }; |
| |
| range_test(NearestSmaller(0.0F), false); |
| range_test(NearestGreater(1.0F), false); |
| range_test(0.0F, /* positive_test= */ true); |
| range_test(1.0F, /* positive_test= */ true); |
| } |
| |
| TEST_F(NegativePipeline, DepthClipControlFeatureDisable) { |
| // Enable negativeOneToOne (VK_EXT_depth_clip_control) in pipeline when the feature is disabled. |
| AddRequiredExtensions(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineViewportDepthClipControlCreateInfoEXT clip_control = vku::InitStructHelper(); |
| clip_control.negativeOneToOne = VK_TRUE; |
| auto set_shading_enable = [clip_control](CreatePipelineHelper &helper) { helper.vp_state_ci_.pNext = &clip_control; }; |
| CreatePipelineHelper::OneshotTest(*this, set_shading_enable, kErrorBit, |
| "VUID-VkPipelineViewportDepthClipControlCreateInfoEXT-negativeOneToOne-06470"); |
| } |
| |
| TEST_F(NegativePipeline, SamplePNextUnknown) { |
| TEST_DESCRIPTION("Pass unknown pNext into VkPipelineMultisampleStateCreateInfo"); |
| AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineSampleLocationsStateCreateInfoEXT sample_locations = vku::InitStructHelper(); |
| sample_locations.sampleLocationsInfo = vku::InitStructHelper(); |
| auto good_chain = [&sample_locations](CreatePipelineHelper &helper) { helper.ms_ci_.pNext = &sample_locations; }; |
| CreatePipelineHelper::OneshotTest(*this, good_chain, kErrorBit); |
| |
| VkInstanceCreateInfo instance_ci = vku::InitStructHelper(); |
| auto bad_chain = [&instance_ci](CreatePipelineHelper &helper) { helper.ms_ci_.pNext = &instance_ci; }; |
| CreatePipelineHelper::OneshotTest(*this, bad_chain, kErrorBit, "VUID-VkPipelineMultisampleStateCreateInfo-pNext-pNext"); |
| } |
| |
| TEST_F(NegativePipeline, SubpassRasterizationSamples) { |
| TEST_DESCRIPTION("Test creating two pipelines referring to the same subpass but with different rasterization samples count"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| // Create a render pass with 1 subpass. This subpass uses no attachment. |
| std::array<VkAttachmentReference, 1> attachmentRefs = {}; |
| attachmentRefs[0].layout = VK_IMAGE_LAYOUT_GENERAL; |
| attachmentRefs[0].attachment = VK_ATTACHMENT_UNUSED; |
| |
| VkSubpassDescription subpass = {}; |
| subpass.colorAttachmentCount = 1; |
| subpass.pColorAttachments = attachmentRefs.data(); |
| |
| VkAttachmentDescription attach_desc = {}; |
| attach_desc.format = m_renderTargets[0]->Format(); |
| attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; |
| attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; |
| attach_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL; |
| |
| VkRenderPassCreateInfo rpci = vku::InitStructHelper(); |
| rpci.subpassCount = 1; |
| rpci.pSubpasses = &subpass; |
| rpci.attachmentCount = 1; |
| rpci.pAttachments = &attach_desc; |
| |
| vkt::RenderPass renderpass(*m_device, rpci); |
| ASSERT_TRUE(renderpass.initialized()); |
| |
| auto render_target_view = m_renderTargets[0]->CreateView(); |
| |
| const uint32_t fb_width = m_renderTargets[0]->Width(); |
| const uint32_t fb_height = m_renderTargets[0]->Height(); |
| vkt::Framebuffer framebuffer(*m_device, renderpass, 1, &render_target_view.handle(), fb_width, fb_height); |
| |
| CreatePipelineHelper pipeline_1(*this); |
| pipeline_1.ms_ci_.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; |
| pipeline_1.gp_ci_.renderPass = renderpass; |
| pipeline_1.CreateGraphicsPipeline(); |
| |
| CreatePipelineHelper pipeline_2(*this); |
| pipeline_2.ms_ci_.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT; |
| pipeline_2.gp_ci_.renderPass = renderpass; |
| pipeline_2.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(renderpass, framebuffer, fb_width, fb_height); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_1); |
| |
| // VkPhysicalDeviceFeatures::variableMultisampleRate is false, |
| // the two pipelines refer to the same subpass, one that does not use any attachment, |
| // BUT the secondly created pipeline has a different sample samples count than the 1st, this is illegal |
| m_errorMonitor->SetDesiredError("VUID-vkCmdBindPipeline-pipeline-00781"); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_2); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.EndRenderPass(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativePipeline, RenderPassCustomeResolve) { |
| AddRequiredExtensions(VK_EXT_CUSTOM_RESOLVE_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::customResolve); |
| AddRequiredFeature(vkt::Feature::sampleRateShading); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| // Create a renderPass with two attachments (0=Color, 1=Input) |
| VkAttachmentReference attachment_refs[2] = {}; |
| attachment_refs[0].layout = VK_IMAGE_LAYOUT_GENERAL; |
| attachment_refs[0].attachment = 0; |
| attachment_refs[1].layout = VK_IMAGE_LAYOUT_GENERAL; |
| attachment_refs[1].attachment = 1; |
| |
| VkSubpassDescription subpass = {}; |
| subpass.flags = VK_SUBPASS_DESCRIPTION_FRAGMENT_REGION_BIT_EXT; |
| subpass.colorAttachmentCount = 1; |
| subpass.pColorAttachments = &attachment_refs[0]; |
| subpass.inputAttachmentCount = 1; |
| subpass.pInputAttachments = &attachment_refs[1]; |
| |
| VkRenderPassCreateInfo rpci = vku::InitStructHelper(); |
| rpci.subpassCount = 1; |
| rpci.pSubpasses = &subpass; |
| rpci.attachmentCount = 2; |
| |
| VkAttachmentDescription attach_desc[2] = {}; |
| attach_desc[0].format = VK_FORMAT_B8G8R8A8_UNORM; |
| attach_desc[0].samples = VK_SAMPLE_COUNT_1_BIT; |
| attach_desc[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; |
| attach_desc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| attach_desc[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL; |
| attach_desc[1].format = VK_FORMAT_B8G8R8A8_UNORM; |
| attach_desc[1].samples = VK_SAMPLE_COUNT_4_BIT; |
| attach_desc[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; |
| attach_desc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| attach_desc[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL; |
| |
| rpci.pAttachments = attach_desc; |
| |
| // renderpass has 1xMSAA colorAttachent and 4xMSAA inputAttachment |
| vkt::RenderPass renderpass(*m_device, rpci); |
| ASSERT_TRUE(renderpass.initialized()); |
| |
| // renderpass2 has 1xMSAA colorAttachent and 1xMSAA inputAttachment |
| attach_desc[1].samples = VK_SAMPLE_COUNT_1_BIT; |
| vkt::RenderPass renderpass2(*m_device, rpci); |
| ASSERT_TRUE(renderpass2.initialized()); |
| |
| // shader uses gl_SamplePosition which causes the SPIR-V to include SampleRateShading capability |
| static const char *shader_source = R"glsl( |
| #version 450 |
| layout(location = 0) out vec4 uFragColor; |
| void main() { |
| uFragColor = vec4(gl_SamplePosition.x,1,0,1); |
| } |
| )glsl"; |
| |
| VkShaderObj fs_sample_rate(*m_device, shader_source, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| VkPipelineMultisampleStateCreateInfo ms_state = vku::InitStructHelper(); |
| ms_state.flags = 0; |
| ms_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; |
| ms_state.sampleShadingEnable = VK_FALSE; |
| ms_state.minSampleShading = 0.0f; |
| ms_state.pSampleMask = nullptr; |
| ms_state.alphaToCoverageEnable = VK_FALSE; |
| ms_state.alphaToOneEnable = VK_FALSE; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.renderPass = renderpass; |
| pipe.cb_attachments_.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR; |
| pipe.cb_attachments_.blendEnable = VK_TRUE; |
| pipe.gp_ci_.pMultisampleState = &ms_state; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-rasterizationSamples-04899"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| |
| ms_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; |
| ms_state.sampleShadingEnable = VK_TRUE; |
| pipe.gp_ci_.renderPass = renderpass2; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-sampleShadingEnable-04900"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| |
| ms_state.sampleShadingEnable = VK_FALSE; |
| pipe.shader_stages_[1] = fs_sample_rate.GetStageCreateInfo(); |
| |
| m_errorMonitor->SetDesiredError("VUID-RuntimeSpirv-SampleRateShading-06378"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, CustomResolvePipelineFormat) { |
| AddRequiredExtensions(VK_EXT_CUSTOM_RESOLVE_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| AddRequiredFeature(vkt::Feature::customResolve); |
| RETURN_IF_SKIP(Init()); |
| |
| VkFormat color_formats[2] = {VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM}; |
| VkCustomResolveCreateInfoEXT custom_resolve_info = vku::InitStructHelper(); |
| custom_resolve_info.customResolve = VK_TRUE; |
| custom_resolve_info.colorAttachmentCount = 2; |
| custom_resolve_info.pColorAttachmentFormats = &color_formats[0]; |
| |
| VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper(&custom_resolve_info); |
| pipeline_rendering_info.colorAttachmentCount = 1; |
| pipeline_rendering_info.pColorAttachmentFormats = &color_formats[1]; |
| CreatePipelineHelper pipe(*this, &pipeline_rendering_info); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-11504"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, CustomResolveSampleShadingImplicit) { |
| AddRequiredExtensions(VK_EXT_CUSTOM_RESOLVE_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| AddRequiredFeature(vkt::Feature::customResolve); |
| AddRequiredFeature(vkt::Feature::sampleRateShading); |
| RETURN_IF_SKIP(Init()); |
| |
| char const *vs_source = R"glsl( |
| #version 460 |
| layout(location = 0) out vec4 samp; |
| void main(){ |
| gl_Position = vec4(1.0); |
| } |
| )glsl"; |
| |
| char const *fs_source = R"glsl( |
| #version 460 |
| layout(location = 0) in sample vec4 samp; // implicitly sets with Sample Decoration |
| layout(location = 0) out vec4 color; |
| void main() { |
| color = samp; |
| } |
| )glsl"; |
| VkShaderObj vs(*m_device, vs_source, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(*m_device, fs_source, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| VkFormat color_format = VK_FORMAT_B8G8R8A8_UNORM; |
| VkCustomResolveCreateInfoEXT custom_resolve_info = vku::InitStructHelper(); |
| custom_resolve_info.customResolve = VK_TRUE; |
| custom_resolve_info.colorAttachmentCount = 1; |
| custom_resolve_info.pColorAttachmentFormats = &color_format; |
| |
| VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper(&custom_resolve_info); |
| pipeline_rendering_info.colorAttachmentCount = 1; |
| pipeline_rendering_info.pColorAttachmentFormats = &color_format; |
| |
| CreatePipelineHelper pipe(*this, &pipeline_rendering_info); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.CreateGraphicsPipeline(); |
| |
| VkImageCreateInfo image_ci = vkt::Image::ImageCreateInfo2D(32, 32, 1, 1, color_format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); |
| image_ci.samples = VK_SAMPLE_COUNT_4_BIT; |
| vkt::Image color_image(*m_device, image_ci); |
| vkt::ImageView color_image_view = color_image.CreateView(); |
| |
| image_ci.samples = VK_SAMPLE_COUNT_1_BIT; |
| vkt::Image resolve_image(*m_device, image_ci); |
| vkt::ImageView resolve_image_view = resolve_image.CreateView(); |
| |
| VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper(); |
| color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| color_attachment.imageView = color_image_view; |
| color_attachment.resolveMode = VK_RESOLVE_MODE_CUSTOM_BIT_EXT; |
| color_attachment.resolveImageView = resolve_image_view; |
| color_attachment.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| |
| VkRenderingInfo begin_rendering_info = vku::InitStructHelper(); |
| begin_rendering_info.flags = VK_RENDERING_CUSTOM_RESOLVE_BIT_EXT | VK_RENDERING_FRAGMENT_REGION_BIT_EXT; |
| begin_rendering_info.colorAttachmentCount = 1; |
| begin_rendering_info.pColorAttachments = &color_attachment; |
| begin_rendering_info.layerCount = 1; |
| begin_rendering_info.renderArea = {{0, 0}, {1, 1}}; |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRendering(begin_rendering_info); |
| VkBeginCustomResolveInfoEXT begin_resolve_info = vku::InitStructHelper(); |
| vk::CmdBeginCustomResolveEXT(m_command_buffer, &begin_resolve_info); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-flags-11521"); |
| vk::CmdDraw(m_command_buffer, 3, 1, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativePipeline, RasterizerDiscardWithFragmentShader) { |
| TEST_DESCRIPTION("Create Graphics Pipeline with fragment shader and rasterizer discard"); |
| RETURN_IF_SKIP(Init()); |
| 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); |
| vkt::ImageView depth_image_view = m_depthStencil->CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); |
| InitRenderTarget(&depth_image_view.handle()); |
| |
| VkShaderObj vs(*m_device, kVertexMinimalGlsl, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(*m_device, kFragmentMinimalGlsl, VK_SHADER_STAGE_FRAGMENT_BIT); |
| const VkPipelineShaderStageCreateInfo stages[] = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| |
| const VkPipelineVertexInputStateCreateInfo pipeline_vertex_input_state_create_info{ |
| VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, nullptr, 0, 0, nullptr, 0, nullptr}; |
| |
| const VkPipelineInputAssemblyStateCreateInfo pipeline_input_assembly_state_create_info{ |
| VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_FALSE}; |
| |
| const VkPipelineRasterizationStateCreateInfo pipeline_rasterization_state_create_info{ |
| VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, |
| nullptr, |
| 0, |
| VK_FALSE, |
| VK_TRUE, |
| VK_POLYGON_MODE_FILL, |
| VK_CULL_MODE_NONE, |
| VK_FRONT_FACE_COUNTER_CLOCKWISE, |
| VK_FALSE, |
| 0.0f, |
| 0.0f, |
| 0.0f, |
| 1.0f}; |
| |
| VkPipelineLayout pipeline_layout; |
| VkPipelineLayoutCreateInfo pipeline_layout_create_info = vku::InitStructHelper(); |
| VkResult err = vk::CreatePipelineLayout(device(), &pipeline_layout_create_info, nullptr, &pipeline_layout); |
| ASSERT_EQ(VK_SUCCESS, err); |
| |
| VkGraphicsPipelineCreateInfo graphics_pipeline_create_info{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, |
| nullptr, |
| 0, |
| 2, |
| stages, |
| &pipeline_vertex_input_state_create_info, |
| &pipeline_input_assembly_state_create_info, |
| nullptr, |
| nullptr, |
| &pipeline_rasterization_state_create_info, |
| nullptr, |
| nullptr, |
| nullptr, |
| nullptr, |
| pipeline_layout, |
| m_renderPass, |
| 0, |
| VK_NULL_HANDLE, |
| -1}; |
| |
| VkPipeline pipeline; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pStages-06894"); |
| vk::CreateGraphicsPipelines(*m_device, VK_NULL_HANDLE, 1, &graphics_pipeline_create_info, nullptr, &pipeline); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::DestroyPipelineLayout(*m_device, pipeline_layout, nullptr); |
| } |
| |
| TEST_F(NegativePipeline, CreateGraphicsPipelineWithBadBasePointer) { |
| TEST_DESCRIPTION("Create Graphics Pipeline with pointers that must be ignored by layers"); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| 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); |
| vkt::ImageView depth_image_view = m_depthStencil->CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); |
| InitRenderTarget(&depth_image_view.handle()); |
| |
| VkShaderObj vs(*m_device, kVertexMinimalGlsl, VK_SHADER_STAGE_VERTEX_BIT); |
| |
| const VkPipelineVertexInputStateCreateInfo pipeline_vertex_input_state_create_info{ |
| VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, nullptr, 0, 0, nullptr, 0, nullptr}; |
| |
| const VkPipelineInputAssemblyStateCreateInfo pipeline_input_assembly_state_create_info{ |
| VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, VK_FALSE}; |
| |
| const VkPipelineRasterizationStateCreateInfo pipeline_rasterization_state_create_info_template{ |
| VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, |
| nullptr, |
| 0, |
| VK_FALSE, |
| VK_FALSE, |
| VK_POLYGON_MODE_FILL, |
| VK_CULL_MODE_NONE, |
| VK_FRONT_FACE_COUNTER_CLOCKWISE, |
| VK_FALSE, |
| 0.0f, |
| 0.0f, |
| 0.0f, |
| 1.0f}; |
| |
| VkPipelineLayout pipeline_layout; |
| VkPipelineLayoutCreateInfo pipeline_layout_create_info = vku::InitStructHelper(); |
| VkResult err = vk::CreatePipelineLayout(device(), &pipeline_layout_create_info, nullptr, &pipeline_layout); |
| ASSERT_EQ(VK_SUCCESS, err); |
| |
| VkPipelineRasterizationStateCreateInfo pipeline_rasterization_state_create_info = |
| pipeline_rasterization_state_create_info_template; |
| pipeline_rasterization_state_create_info.rasterizerDiscardEnable = VK_TRUE; |
| |
| constexpr uint64_t fake_pipeline_id = 0xCADECADE; |
| VkPipeline fake_pipeline_handle = CastFromUint64<VkPipeline>(fake_pipeline_id); |
| |
| VkGraphicsPipelineCreateInfo graphics_pipeline_create_info{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, |
| nullptr, |
| VK_PIPELINE_CREATE_DERIVATIVE_BIT, |
| 1, |
| &vs.GetStageCreateInfo(), |
| &pipeline_vertex_input_state_create_info, |
| &pipeline_input_assembly_state_create_info, |
| nullptr, |
| nullptr, |
| &pipeline_rasterization_state_create_info, |
| nullptr, |
| nullptr, |
| nullptr, |
| nullptr, |
| pipeline_layout, |
| m_renderPass, |
| 0, |
| fake_pipeline_handle, |
| -1}; |
| |
| VkPipeline pipeline; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-flags-07984"); |
| vk::CreateGraphicsPipelines(*m_device, VK_NULL_HANDLE, 1, &graphics_pipeline_create_info, nullptr, &pipeline); |
| m_errorMonitor->VerifyFound(); |
| |
| graphics_pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE; |
| graphics_pipeline_create_info.basePipelineIndex = 6; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-flags-07985"); |
| vk::CreateGraphicsPipelines(*m_device, VK_NULL_HANDLE, 1, &graphics_pipeline_create_info, nullptr, &pipeline); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::DestroyPipelineLayout(*m_device, pipeline_layout, nullptr); |
| } |
| |
| TEST_F(NegativePipeline, PipelineCreationCacheControl) { |
| TEST_DESCRIPTION("Test VK_EXT_pipeline_creation_cache_control"); |
| |
| AddRequiredExtensions(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const auto set_graphics_flags = [&](CreatePipelineHelper &helper) { |
| helper.gp_ci_.flags = VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, set_graphics_flags, kErrorBit, |
| "VUID-VkGraphicsPipelineCreateInfo-pipelineCreationCacheControl-02878"); |
| |
| const auto set_compute_flags = [&](CreateComputePipelineHelper &helper) { |
| helper.cp_ci_.flags = VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT; |
| }; |
| CreateComputePipelineHelper::OneshotTest(*this, set_compute_flags, kErrorBit, |
| "VUID-VkComputePipelineCreateInfo-pipelineCreationCacheControl-02875"); |
| |
| VkPipelineCache pipeline_cache; |
| VkPipelineCacheCreateInfo cache_create_info = vku::InitStructHelper(); |
| cache_create_info.initialDataSize = 0; |
| cache_create_info.flags = VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineCacheCreateInfo-pipelineCreationCacheControl-02892"); |
| vk::CreatePipelineCache(device(), &cache_create_info, nullptr, &pipeline_cache); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, PipelineCreationCacheFeaturesMaintenance8) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_8_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineCache pipeline_cache; |
| VkPipelineCacheCreateInfo cache_create_info = vku::InitStructHelper(); |
| cache_create_info.initialDataSize = 0; |
| cache_create_info.flags = VK_PIPELINE_CACHE_CREATE_INTERNALLY_SYNCHRONIZED_MERGE_BIT_KHR; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineCacheCreateInfo-maintenance8-10200"); |
| vk::CreatePipelineCache(device(), &cache_create_info, nullptr, &pipeline_cache); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, PipelineCreationFlagsMix) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_8_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::pipelineCreationCacheControl); |
| AddRequiredFeature(vkt::Feature::maintenance8); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineCache pipeline_cache; |
| VkPipelineCacheCreateInfo cache_create_info = vku::InitStructHelper(); |
| cache_create_info.initialDataSize = 0; |
| cache_create_info.flags = |
| VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT | VK_PIPELINE_CACHE_CREATE_INTERNALLY_SYNCHRONIZED_MERGE_BIT_KHR; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineCacheCreateInfo-flags-10201"); |
| vk::CreatePipelineCache(device(), &cache_create_info, nullptr, &pipeline_cache); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, NumBlendAttachMismatch) { |
| // Create Pipeline where the number of blend attachments doesn't match the |
| // number of color attachments. In this case, we don't add any color |
| // blend attachments even though we have a color attachment. |
| |
| AddOptionalExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = vku::InitStructHelper(); |
| 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 = NULL; |
| |
| const auto set_MSAA = [&](CreatePipelineHelper &helper) { |
| helper.ms_ci_ = pipe_ms_state_ci; |
| helper.cb_ci_.attachmentCount = 0; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, set_MSAA, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-renderPass-07609"); |
| } |
| |
| TEST_F(NegativePipeline, ColorBlendInvalidLogicOp) { |
| TEST_DESCRIPTION("Attempt to use invalid VkPipelineColorBlendStateCreateInfo::logicOp value."); |
| |
| AddRequiredFeature(vkt::Feature::logicOp); |
| RETURN_IF_SKIP(Init()); // enables all supported features |
| InitRenderTarget(); |
| |
| const auto set_shading_enable = [](CreatePipelineHelper &helper) { |
| helper.cb_ci_.logicOpEnable = VK_TRUE; |
| helper.cb_ci_.logicOp = static_cast<VkLogicOp>(VK_LOGIC_OP_SET + 1); // invalid logicOp to be tested |
| }; |
| CreatePipelineHelper::OneshotTest(*this, set_shading_enable, kErrorBit, |
| "VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00607"); |
| } |
| |
| TEST_F(NegativePipeline, ColorBlendUnsupportedLogicOp) { |
| TEST_DESCRIPTION("Attempt enabling VkPipelineColorBlendStateCreateInfo::logicOpEnable when logicOp feature is disabled."); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const auto set_shading_enable = [](CreatePipelineHelper &helper) { helper.cb_ci_.logicOpEnable = VK_TRUE; }; |
| CreatePipelineHelper::OneshotTest(*this, set_shading_enable, kErrorBit, |
| "VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00606"); |
| } |
| |
| TEST_F(NegativePipeline, ColorBlendUnsupportedDualSourceBlend) { |
| TEST_DESCRIPTION("Attempt to use dual-source blending when dualSrcBlend feature is disabled."); |
| |
| VkPhysicalDeviceFeatures features{}; |
| RETURN_IF_SKIP(Init(&features)); |
| InitRenderTarget(); |
| |
| VkPipelineColorBlendAttachmentState cb_attachments = {}; |
| |
| const auto set_dsb_src_color_enable = [&](CreatePipelineHelper &helper) { helper.cb_attachments_ = cb_attachments; }; |
| |
| cb_attachments.blendEnable = VK_TRUE; |
| cb_attachments.srcColorBlendFactor = VK_BLEND_FACTOR_SRC1_COLOR; // bad! |
| cb_attachments.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; |
| cb_attachments.colorBlendOp = VK_BLEND_OP_ADD; |
| cb_attachments.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; |
| cb_attachments.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; |
| cb_attachments.alphaBlendOp = VK_BLEND_OP_ADD; |
| CreatePipelineHelper::OneshotTest(*this, set_dsb_src_color_enable, kErrorBit, |
| "VUID-VkPipelineColorBlendAttachmentState-srcColorBlendFactor-00608"); |
| |
| cb_attachments.blendEnable = VK_TRUE; |
| cb_attachments.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; |
| cb_attachments.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR; // bad |
| cb_attachments.colorBlendOp = VK_BLEND_OP_ADD; |
| cb_attachments.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; |
| cb_attachments.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; |
| cb_attachments.alphaBlendOp = VK_BLEND_OP_ADD; |
| CreatePipelineHelper::OneshotTest(*this, set_dsb_src_color_enable, kErrorBit, |
| "VUID-VkPipelineColorBlendAttachmentState-dstColorBlendFactor-00609"); |
| |
| cb_attachments.blendEnable = VK_TRUE; |
| cb_attachments.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; |
| cb_attachments.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; |
| cb_attachments.colorBlendOp = VK_BLEND_OP_ADD; |
| cb_attachments.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC1_ALPHA; // bad |
| cb_attachments.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; |
| cb_attachments.alphaBlendOp = VK_BLEND_OP_ADD; |
| CreatePipelineHelper::OneshotTest(*this, set_dsb_src_color_enable, kErrorBit, |
| "VUID-VkPipelineColorBlendAttachmentState-srcAlphaBlendFactor-00610"); |
| |
| cb_attachments.blendEnable = VK_TRUE; |
| cb_attachments.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR; |
| cb_attachments.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; |
| cb_attachments.colorBlendOp = VK_BLEND_OP_ADD; |
| cb_attachments.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; |
| cb_attachments.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA; // bad! |
| cb_attachments.alphaBlendOp = VK_BLEND_OP_ADD; |
| CreatePipelineHelper::OneshotTest(*this, set_dsb_src_color_enable, kErrorBit, |
| "VUID-VkPipelineColorBlendAttachmentState-dstAlphaBlendFactor-00611"); |
| } |
| |
| TEST_F(NegativePipeline, DuplicateStage) { |
| TEST_DESCRIPTION("Test that an error is produced for a pipeline containing multiple shaders for the same stage"); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const auto set_info = [&](CreatePipelineHelper &helper) { |
| helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), helper.vs_->GetStageCreateInfo(), |
| helper.fs_->GetStageCreateInfo()}; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-stage-06897"); |
| } |
| |
| TEST_F(NegativePipeline, DuplicateStageMaintenance5) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const auto vs_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kMinimalShaderGlsl); |
| const auto fs_spv = GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kMinimalShaderGlsl); |
| |
| VkShaderModuleCreateInfo module_create_info_vs = vku::InitStructHelper(); |
| module_create_info_vs.pCode = vs_spv.data(); |
| module_create_info_vs.codeSize = vs_spv.size() * sizeof(uint32_t); |
| |
| VkPipelineShaderStageCreateInfo stage_ci_vs = vku::InitStructHelper(&module_create_info_vs); |
| stage_ci_vs.stage = VK_SHADER_STAGE_VERTEX_BIT; |
| stage_ci_vs.module = VK_NULL_HANDLE; |
| stage_ci_vs.pName = "main"; |
| |
| VkShaderModuleCreateInfo module_create_info_fs = vku::InitStructHelper(); |
| module_create_info_fs.pCode = fs_spv.data(); |
| module_create_info_fs.codeSize = fs_spv.size() * sizeof(uint32_t); |
| |
| VkPipelineShaderStageCreateInfo stage_ci_fs = vku::InitStructHelper(&module_create_info_fs); |
| stage_ci_fs.stage = VK_SHADER_STAGE_FRAGMENT_BIT; |
| stage_ci_fs.module = VK_NULL_HANDLE; |
| stage_ci_fs.pName = "main"; |
| |
| std::array stages = {stage_ci_vs, stage_ci_vs, stage_ci_fs}; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.stageCount = size32(stages); |
| pipe.gp_ci_.pStages = stages.data(); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-stage-06897"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, DuplicateStageMaintenance5Vertex) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char shader[] = R"glsl( |
| #version 450 |
| layout(set = 0, binding = 0) buffer ssbo { uint x; }; |
| void main() { |
| x = 0; |
| } |
| )glsl"; |
| |
| const auto vs_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, shader); |
| |
| VkShaderModuleCreateInfo module_create_info_vs = vku::InitStructHelper(); |
| module_create_info_vs.pCode = vs_spv.data(); |
| module_create_info_vs.codeSize = vs_spv.size() * sizeof(uint32_t); |
| |
| VkPipelineShaderStageCreateInfo stage_ci_vs = vku::InitStructHelper(&module_create_info_vs); |
| stage_ci_vs.stage = VK_SHADER_STAGE_VERTEX_BIT; |
| stage_ci_vs.module = VK_NULL_HANDLE; |
| stage_ci_vs.pName = "main"; |
| |
| std::array stages = {stage_ci_vs, stage_ci_vs}; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.stageCount = size32(stages); |
| pipe.gp_ci_.pStages = stages.data(); |
| pipe.dsl_bindings_[0] = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-stage-06897"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, MissingEntrypoint) { |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| // Graphics |
| { |
| VkShaderObj fs(*m_device, kFragmentMinimalGlsl, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, nullptr, |
| "foo"); |
| const auto set_info = [&](CreatePipelineHelper &helper) { |
| helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkPipelineShaderStageCreateInfo-pName-00707"); |
| } |
| |
| // Compute |
| { |
| const auto set_info = [&](CreateComputePipelineHelper& helper) { |
| helper.cs_ = VkShaderObj(*m_device, kMinimalShaderGlsl, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, |
| SPV_SOURCE_GLSL, nullptr, "foo"); |
| }; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkPipelineShaderStageCreateInfo-pName-00707"); |
| } |
| |
| // Multiple pipeline, middle has missing entrypoint |
| { |
| CreateComputePipelineHelper pipe_0(*this); // valid |
| pipe_0.LateBindPipelineInfo(); |
| CreateComputePipelineHelper pipe_1(*this); // invalid |
| pipe_1.cs_ = VkShaderObj(*m_device, kMinimalShaderGlsl, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, |
| nullptr, "foo"); |
| pipe_1.LateBindPipelineInfo(); |
| |
| VkComputePipelineCreateInfo create_infos[3] = {pipe_0.cp_ci_, pipe_1.cp_ci_, pipe_0.cp_ci_}; |
| VkPipeline pipelines[3]; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pName-00707"); |
| vk::CreateComputePipelines(device(), VK_NULL_HANDLE, 3, create_infos, nullptr, pipelines); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativePipeline, MissingEntrypoint2) { |
| RETURN_IF_SKIP(Init()); |
| |
| const char *shader_source = R"( |
| OpCapability Shader |
| OpMemoryModel Logical GLSL450 |
| OpEntryPoint GLCompute %foo "foo" |
| OpEntryPoint GLCompute %not_main "not_main" |
| OpEntryPoint GLCompute %not_main "still_no_main" |
| OpEntryPoint Vertex %not_this "not_this" |
| OpExecutionMode %foo LocalSize 1 1 1 |
| OpExecutionMode %not_main LocalSize 1 1 1 |
| %void = OpTypeVoid |
| %4 = OpTypeFunction %void |
| %foo = OpFunction %void None %4 |
| %l0 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| %not_main = OpFunction %void None %4 |
| %l1 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| %not_this = OpFunction %void None %4 |
| %l2 = OpLabel |
| OpReturn |
| OpFunctionEnd |
| )"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = |
| VkShaderObj(*m_device, shader_source, VK_SHADER_STAGE_COMPUTE_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_ASM, nullptr, "main"); |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pName-00707"); |
| pipe.CreateComputePipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, MissingEntrypointInline) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| std::vector<uint32_t> shader = GLSLToSPV(VK_SHADER_STAGE_FRAGMENT_BIT, kMinimalShaderGlsl); |
| |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| module_create_info.pCode = shader.data(); |
| module_create_info.codeSize = shader.size() * sizeof(uint32_t); |
| |
| VkPipelineShaderStageCreateInfo stage_ci = vku::InitStructHelper(&module_create_info); |
| stage_ci.stage = VK_SHADER_STAGE_FRAGMENT_BIT; |
| stage_ci.module = VK_NULL_HANDLE; |
| stage_ci.pName = "foo"; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), stage_ci}; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pName-00707"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, MissingEntrypointInlineWrongStage) { |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| // Messed up and should be FRAGMENT |
| const auto shader = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kMinimalShaderGlsl); |
| |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| module_create_info.pCode = shader.data(); |
| module_create_info.codeSize = shader.size() * sizeof(uint32_t); |
| |
| VkPipelineShaderStageCreateInfo stage_ci = vku::InitStructHelper(&module_create_info); |
| stage_ci.stage = VK_SHADER_STAGE_FRAGMENT_BIT; |
| stage_ci.module = VK_NULL_HANDLE; |
| stage_ci.pName = "name"; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), stage_ci}; |
| // VUID-VkPipelineShaderStageCreateInfo-pName-00707 |
| m_errorMonitor->SetDesiredError( |
| "Seems like you accidently created your SPIR-V with VK_SHADER_STAGE_VERTEX_BIT so the entry point is not matching up"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, DepthStencilRequired) { |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-09028"); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| RenderPassSingleSubpass rp(*this); |
| rp.AddAttachmentDescription(VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); |
| rp.AddAttachmentDescription(VK_FORMAT_D16_UNORM, 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(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.renderPass = rp; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, NullStagepName) { |
| TEST_DESCRIPTION("Test that an error is produced for a stage with a null pName pointer"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| VkShaderObj vs(*m_device, kVertexMinimalGlsl, VK_SHADER_STAGE_VERTEX_BIT); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo()}; |
| pipe.shader_stages_[0].pName = nullptr; |
| pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {}); |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pName-parameter"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, NullStagepNameCompute) { |
| TEST_DESCRIPTION("Test that an error is produced for a stage with a null pName pointer"); |
| RETURN_IF_SKIP(Init()); |
| VkShaderObj cs(*m_device, kMinimalShaderGlsl, VK_SHADER_STAGE_COMPUTE_BIT); |
| |
| vkt::PipelineLayout layout(*m_device, {}); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cp_ci_.stage = cs.GetStageCreateInfo(); |
| pipe.cp_ci_.stage.pName = nullptr; |
| pipe.cp_ci_.layout = layout; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pName-parameter"); |
| pipe.CreateComputePipeline(false); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, NullStagepNameMaintenance5) { |
| TEST_DESCRIPTION("Test that an error is produced for a stage with a null pName pointer"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| std::vector<uint32_t> shader = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kMinimalShaderGlsl); |
| |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| module_create_info.pCode = shader.data(); |
| module_create_info.codeSize = shader.size() * sizeof(uint32_t); |
| |
| VkPipelineShaderStageCreateInfo stage_ci = vku::InitStructHelper(&module_create_info); |
| stage_ci.stage = VK_SHADER_STAGE_VERTEX_BIT; |
| stage_ci.module = VK_NULL_HANDLE; |
| stage_ci.pName = nullptr; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.stageCount = 1; |
| pipe.gp_ci_.pStages = &stage_ci; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pName-parameter"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, NullStagepNameMaintenance5Compute) { |
| TEST_DESCRIPTION("Test that an error is produced for a stage with a null pName pointer"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| |
| std::vector<uint32_t> shader = GLSLToSPV(VK_SHADER_STAGE_COMPUTE_BIT, kMinimalShaderGlsl); |
| |
| VkShaderModuleCreateInfo module_create_info = vku::InitStructHelper(); |
| module_create_info.pCode = shader.data(); |
| module_create_info.codeSize = shader.size() * sizeof(uint32_t); |
| |
| VkPipelineShaderStageCreateInfo stage_ci = vku::InitStructHelper(&module_create_info); |
| stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT; |
| stage_ci.module = VK_NULL_HANDLE; |
| stage_ci.pName = nullptr; |
| |
| vkt::PipelineLayout layout(*m_device, {}); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cp_ci_.stage = stage_ci; |
| pipe.cp_ci_.layout = layout; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineShaderStageCreateInfo-pName-parameter"); |
| pipe.CreateComputePipeline(false); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, AMDMixedAttachmentSamplesValidateGraphicsPipeline) { |
| TEST_DESCRIPTION("Verify an error message for an incorrect graphics pipeline rasterization sample count."); |
| |
| AddRequiredExtensions(VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| // Set a mismatched sample count |
| VkPipelineMultisampleStateCreateInfo ms_state_ci = vku::InitStructHelper(); |
| ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT; |
| |
| const auto set_info = [&](CreatePipelineHelper &helper) { helper.ms_ci_ = ms_state_ci; }; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-subpass-01505"); |
| } |
| |
| TEST_F(NegativePipeline, FramebufferMixedSamplesNV) { |
| TEST_DESCRIPTION("Verify VK_NV_framebuffer_mixed_samples."); |
| AddRequiredExtensions(VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::sampleRateShading); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| struct TestCase { |
| VkSampleCountFlagBits color_samples; |
| VkSampleCountFlagBits depth_samples; |
| VkSampleCountFlagBits raster_samples; |
| VkBool32 depth_test; |
| VkBool32 sample_shading; |
| uint32_t table_count; |
| bool positiveTest; |
| std::string vuid; |
| }; |
| |
| std::vector<TestCase> test_cases = { |
| {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_FALSE, 1, true, |
| "VUID-VkGraphicsPipelineCreateInfo-multisampledRenderToSingleSampled-06853"}, |
| {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT, VK_FALSE, VK_FALSE, 4, false, |
| "VUID-VkPipelineCoverageModulationStateCreateInfoNV-coverageModulationTableEnable-01405"}, |
| {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT, VK_FALSE, VK_FALSE, 2, true, |
| "VUID-VkPipelineCoverageModulationStateCreateInfoNV-coverageModulationTableEnable-01405"}, |
| {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_TRUE, VK_FALSE, 1, false, |
| "VUID-VkGraphicsPipelineCreateInfo-subpass-01411"}, |
| {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_8_BIT, VK_TRUE, VK_FALSE, 1, true, |
| "VUID-VkGraphicsPipelineCreateInfo-subpass-01411"}, |
| {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_1_BIT, VK_FALSE, VK_FALSE, 1, false, |
| "VUID-VkGraphicsPipelineCreateInfo-subpass-01412"}, |
| {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_FALSE, 1, true, |
| "VUID-VkGraphicsPipelineCreateInfo-subpass-01412"}, |
| {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_TRUE, 1, false, |
| "VUID-VkPipelineMultisampleStateCreateInfo-rasterizationSamples-01415"}, |
| {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_FALSE, 1, true, |
| "VUID-VkPipelineMultisampleStateCreateInfo-rasterizationSamples-01415"}, |
| {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_FALSE, VK_FALSE, 1, true, |
| "VUID-VkGraphicsPipelineCreateInfo-multisampledRenderToSingleSampled-06853"}}; |
| |
| for (const auto &test_case : test_cases) { |
| RenderPassSingleSubpass rp(*this); |
| rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, test_case.color_samples, VK_IMAGE_LAYOUT_PREINITIALIZED, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); |
| rp.AddAttachmentDescription(VK_FORMAT_D24_UNORM_S8_UINT, test_case.depth_samples, VK_IMAGE_LAYOUT_PREINITIALIZED, |
| 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(); |
| |
| VkPipelineDepthStencilStateCreateInfo ds = vku::InitStructHelper(); |
| VkPipelineCoverageModulationStateCreateInfoNV cmi = vku::InitStructHelper(); |
| |
| // Create a dummy modulation table that can be used for the positive |
| // coverageModulationTableCount test. |
| std::vector<float> cm_table{}; |
| |
| const auto break_samples = [&cmi, &rp, &ds, &cm_table, &test_case](CreatePipelineHelper &helper) { |
| cm_table.resize(test_case.table_count); |
| |
| cmi.flags = 0; |
| cmi.coverageModulationTableEnable = (test_case.table_count > 1); |
| cmi.coverageModulationTableCount = test_case.table_count; |
| cmi.pCoverageModulationTable = cm_table.data(); |
| |
| ds.depthTestEnable = test_case.depth_test; |
| |
| helper.ms_ci_.pNext = &cmi; |
| helper.ms_ci_.rasterizationSamples = test_case.raster_samples; |
| helper.ms_ci_.sampleShadingEnable = test_case.sample_shading; |
| |
| helper.gp_ci_.renderPass = rp; |
| helper.gp_ci_.pDepthStencilState = &ds; |
| }; |
| |
| if (!test_case.positiveTest) { |
| CreatePipelineHelper::OneshotTest(*this, break_samples, kErrorBit, test_case.vuid); |
| } else { |
| CreatePipelineHelper::OneshotTest(*this, break_samples, kErrorBit); |
| } |
| } |
| } |
| |
| TEST_F(NegativePipeline, FramebufferMixedSamples) { |
| TEST_DESCRIPTION("Verify that the expected VUIds are hits when VK_NV_framebuffer_mixed_samples is disabled."); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const VkFormat ds_format = FindSupportedDepthStencilFormat(Gpu()); |
| |
| struct TestCase { |
| VkSampleCountFlagBits color_samples; |
| VkSampleCountFlagBits depth_samples; |
| VkSampleCountFlagBits raster_samples; |
| bool positiveTest; |
| }; |
| |
| std::vector<TestCase> test_cases = { |
| {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, |
| false}, // Fails vk::CreateRenderPass and vk::CreateGraphicsPipeline |
| {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, false}, // Fails vk::CreateGraphicsPipeline |
| {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, true} // Pass |
| }; |
| |
| for (const auto &test_case : test_cases) { |
| RenderPassSingleSubpass rp(*this); |
| rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, test_case.color_samples, VK_IMAGE_LAYOUT_PREINITIALIZED, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); |
| rp.AddAttachmentDescription(ds_format, test_case.depth_samples, VK_IMAGE_LAYOUT_PREINITIALIZED, |
| 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); |
| |
| if (test_case.color_samples != test_case.depth_samples) { |
| m_errorMonitor->SetDesiredError("VUID-VkSubpassDescription-pDepthStencilAttachment-01418"); |
| } |
| rp.CreateRenderPass(); |
| |
| if (test_case.color_samples != test_case.depth_samples) { |
| m_errorMonitor->VerifyFound(); |
| continue; |
| } |
| |
| VkPipelineDepthStencilStateCreateInfo ds = vku::InitStructHelper(); |
| |
| const auto break_samples = [&rp, &ds, &test_case](CreatePipelineHelper &helper) { |
| helper.ms_ci_.rasterizationSamples = test_case.raster_samples; |
| |
| helper.gp_ci_.renderPass = rp; |
| helper.gp_ci_.pDepthStencilState = &ds; |
| }; |
| |
| if (!test_case.positiveTest) { |
| CreatePipelineHelper::OneshotTest(*this, break_samples, kErrorBit, |
| "VUID-VkGraphicsPipelineCreateInfo-multisampledRenderToSingleSampled-06853"); |
| } else { |
| CreatePipelineHelper::OneshotTest(*this, break_samples, kErrorBit); |
| } |
| } |
| } |
| |
| TEST_F(NegativePipeline, FramebufferMixedSamplesCoverageReduction) { |
| TEST_DESCRIPTION("Verify VK_NV_coverage_reduction_mode."); |
| |
| AddRequiredExtensions(VK_NV_COVERAGE_REDUCTION_MODE_EXTENSION_NAME); |
| AddOptionalExtensions(VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME); |
| AddOptionalExtensions(VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| if (!IsExtensionsEnabled(VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME) && |
| !IsExtensionsEnabled(VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME)) { |
| GTEST_SKIP() << "Extensions not supported"; |
| } |
| InitRenderTarget(); |
| |
| struct TestCase { |
| VkSampleCountFlagBits raster_samples; |
| VkSampleCountFlagBits color_samples; |
| VkSampleCountFlagBits depth_samples; |
| VkCoverageReductionModeNV coverage_reduction_mode; |
| bool positiveTest; |
| std::string vuid; |
| }; |
| |
| std::vector<TestCase> test_cases; |
| |
| uint32_t combination_count = 0; |
| std::vector<VkFramebufferMixedSamplesCombinationNV> combinations; |
| |
| vk::GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(Gpu(), &combination_count, nullptr); |
| if (combination_count < 1) { |
| GTEST_SKIP() << "No mixed sample combinations are supported"; |
| } |
| combinations.resize(combination_count); |
| // TODO this fill can be removed once https://github.com/KhronosGroup/Vulkan-ValidationLayers/pull/4138 merges |
| std::fill(combinations.begin(), combinations.end(), vku::InitStruct<VkFramebufferMixedSamplesCombinationNV>()); |
| vk::GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV(Gpu(), &combination_count, &combinations[0]); |
| |
| // Pick the first supported combination for a positive test. |
| test_cases.push_back({combinations[0].rasterizationSamples, static_cast<VkSampleCountFlagBits>(combinations[0].colorSamples), |
| static_cast<VkSampleCountFlagBits>(combinations[0].depthStencilSamples), |
| combinations[0].coverageReductionMode, true, |
| "VUID-VkGraphicsPipelineCreateInfo-coverageReductionMode-02722"}); |
| |
| VkSampleCountFlags fb_sample_counts = m_device->Physical().limits_.framebufferDepthSampleCounts; |
| int max_sample_count = VK_SAMPLE_COUNT_64_BIT; |
| while (max_sample_count > VK_SAMPLE_COUNT_1_BIT) { |
| if (fb_sample_counts & max_sample_count) { |
| break; |
| } |
| max_sample_count /= 2; |
| } |
| // Look for a valid combination that is not in the supported list for a negative test. |
| bool neg_comb_found = false; |
| for (int mode = VK_COVERAGE_REDUCTION_MODE_TRUNCATE_NV; mode >= 0 && !neg_comb_found; mode--) { |
| for (int rs = max_sample_count; rs >= VK_SAMPLE_COUNT_1_BIT && !neg_comb_found; rs /= 2) { |
| for (int ds = rs; ds >= 0 && !neg_comb_found; ds -= rs) { |
| for (int cs = rs / 2; cs > 0 && !neg_comb_found; cs /= 2) { |
| bool combination_found = false; |
| for (const auto &combination : combinations) { |
| if (mode == combination.coverageReductionMode && rs == combination.rasterizationSamples && |
| (ds & combination.depthStencilSamples || ds == 0) && (cs & combination.colorSamples || cs == 0)) { |
| combination_found = true; |
| break; |
| } |
| } |
| |
| if (!combination_found) { |
| neg_comb_found = true; |
| test_cases.push_back({static_cast<VkSampleCountFlagBits>(rs), static_cast<VkSampleCountFlagBits>(cs), |
| static_cast<VkSampleCountFlagBits>(ds), static_cast<VkCoverageReductionModeNV>(mode), |
| false, "VUID-VkGraphicsPipelineCreateInfo-coverageReductionMode-02722"}); |
| } |
| } |
| } |
| } |
| } |
| |
| for (const auto &test_case : test_cases) { |
| RenderPassSingleSubpass rp(*this); |
| rp.AddAttachmentDescription(VK_FORMAT_R8G8B8A8_UNORM, test_case.color_samples, VK_IMAGE_LAYOUT_UNDEFINED, |
| VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); |
| rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}); |
| rp.AddColorAttachment(0); |
| if (test_case.depth_samples) { |
| rp.AddAttachmentDescription(VK_FORMAT_D24_UNORM_S8_UINT, test_case.depth_samples, VK_IMAGE_LAYOUT_UNDEFINED, |
| VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); |
| rp.AddAttachmentReference({1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}); |
| rp.AddDepthStencilAttachment(1); |
| } |
| rp.CreateRenderPass(); |
| |
| VkPipelineDepthStencilStateCreateInfo dss = vku::InitStructHelper(); |
| VkPipelineCoverageReductionStateCreateInfoNV crs = vku::InitStructHelper(); |
| |
| const auto break_samples = [&rp, &dss, &crs, &test_case](CreatePipelineHelper &helper) { |
| crs.flags = 0; |
| crs.coverageReductionMode = test_case.coverage_reduction_mode; |
| |
| helper.ms_ci_.pNext = &crs; |
| helper.ms_ci_.rasterizationSamples = test_case.raster_samples; |
| helper.gp_ci_.renderPass = rp; |
| helper.gp_ci_.pDepthStencilState = (test_case.depth_samples) ? &dss : nullptr; |
| }; |
| |
| if (!test_case.positiveTest) { |
| CreatePipelineHelper::OneshotTest(*this, break_samples, kErrorBit, test_case.vuid); |
| } else { |
| CreatePipelineHelper::OneshotTest(*this, break_samples, kErrorBit); |
| } |
| } |
| } |
| |
| TEST_F(NegativePipeline, FragmentCoverageToColorNV) { |
| TEST_DESCRIPTION("Verify VK_NV_fragment_coverage_to_color."); |
| |
| AddRequiredExtensions(VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| struct TestCase { |
| VkFormat format; |
| VkBool32 enabled; |
| uint32_t location; |
| bool positive; |
| }; |
| |
| const std::array<TestCase, 9> test_cases = {{ |
| {VK_FORMAT_R8G8B8A8_UNORM, VK_FALSE, 0, true}, |
| {VK_FORMAT_R8_UINT, VK_TRUE, 1, true}, |
| {VK_FORMAT_R16_UINT, VK_TRUE, 1, true}, |
| {VK_FORMAT_R16_SINT, VK_TRUE, 1, true}, |
| {VK_FORMAT_R32_UINT, VK_TRUE, 1, true}, |
| {VK_FORMAT_R32_SINT, VK_TRUE, 1, true}, |
| {VK_FORMAT_R32_SINT, VK_TRUE, 2, false}, |
| {VK_FORMAT_R8_SINT, VK_TRUE, 3, false}, |
| {VK_FORMAT_R8G8B8A8_UNORM, VK_TRUE, 1, false}, |
| }}; |
| |
| for (const auto &test_case : test_cases) { |
| std::array<VkAttachmentDescription, 2> att = {{{}, {}}}; |
| att[0].format = VK_FORMAT_R8G8B8A8_UNORM; |
| att[0].samples = VK_SAMPLE_COUNT_1_BIT; |
| att[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| att[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; |
| att[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; |
| att[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| |
| att[1].format = VK_FORMAT_R8G8B8A8_UNORM; |
| att[1].samples = VK_SAMPLE_COUNT_1_BIT; |
| att[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| att[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; |
| att[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; |
| att[1].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| |
| if (test_case.location < att.size()) { |
| att[test_case.location].format = test_case.format; |
| } |
| |
| const std::array<VkAttachmentReference, 3> cr = {{{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, |
| {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}, |
| {VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}}}; |
| |
| VkSubpassDescription sp = {}; |
| sp.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; |
| sp.colorAttachmentCount = cr.size(); |
| sp.pColorAttachments = cr.data(); |
| |
| VkRenderPassCreateInfo rpi = vku::InitStructHelper(); |
| rpi.attachmentCount = att.size(); |
| rpi.pAttachments = att.data(); |
| rpi.subpassCount = 1; |
| rpi.pSubpasses = &sp; |
| |
| const std::array<VkPipelineColorBlendAttachmentState, 3> cba = {{{}, {}, {}}}; |
| |
| VkPipelineColorBlendStateCreateInfo cbi = vku::InitStructHelper(); |
| cbi.attachmentCount = cba.size(); |
| cbi.pAttachments = cba.data(); |
| |
| vkt::RenderPass rp(*m_device, rpi); |
| ASSERT_TRUE(rp.initialized()); |
| |
| VkPipelineCoverageToColorStateCreateInfoNV cci = vku::InitStructHelper(); |
| |
| const auto break_samples = [&cci, &cbi, &rp, &test_case](CreatePipelineHelper &helper) { |
| cci.coverageToColorEnable = test_case.enabled; |
| cci.coverageToColorLocation = test_case.location; |
| |
| helper.ms_ci_.pNext = &cci; |
| helper.gp_ci_.renderPass = rp; |
| helper.gp_ci_.pColorBlendState = &cbi; |
| }; |
| |
| if (!test_case.positive) { |
| CreatePipelineHelper::OneshotTest(*this, break_samples, kErrorBit, |
| "VUID-VkPipelineCoverageToColorStateCreateInfoNV-coverageToColorEnable-01404"); |
| } else { |
| CreatePipelineHelper::OneshotTest(*this, break_samples, kErrorBit); |
| } |
| } |
| } |
| |
| TEST_F(NegativePipeline, ViewportSwizzleNV) { |
| AddRequiredExtensions(VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::multiViewport); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineViewportSwizzleStateCreateInfoNV vp_swizzle_state = vku::InitStructHelper(); |
| |
| // Test invalid VkViewportSwizzleNV |
| { |
| const VkViewportSwizzleNV invalid_swizzles = { |
| static_cast<VkViewportCoordinateSwizzleNV>(-1), |
| static_cast<VkViewportCoordinateSwizzleNV>(-1), |
| static_cast<VkViewportCoordinateSwizzleNV>(-1), |
| static_cast<VkViewportCoordinateSwizzleNV>(-1), |
| }; |
| |
| vp_swizzle_state.viewportCount = 1; |
| vp_swizzle_state.pViewportSwizzles = &invalid_swizzles; |
| |
| const std::vector<std::string> expected_vuids = { |
| "VUID-VkViewportSwizzleNV-x-parameter", "VUID-VkViewportSwizzleNV-y-parameter", "VUID-VkViewportSwizzleNV-z-parameter", |
| "VUID-VkViewportSwizzleNV-w-parameter"}; |
| |
| auto break_swizzles = [&vp_swizzle_state](CreatePipelineHelper &helper) { helper.vp_state_ci_.pNext = &vp_swizzle_state; }; |
| |
| CreatePipelineHelper::OneshotTest(*this, break_swizzles, kErrorBit, expected_vuids); |
| } |
| |
| // Test case where VkPipelineViewportSwizzleStateCreateInfoNV::viewportCount is LESS THAN viewportCount set in |
| // VkPipelineViewportStateCreateInfo |
| { |
| const VkViewportSwizzleNV 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}; |
| |
| vp_swizzle_state.viewportCount = 1; |
| vp_swizzle_state.pViewportSwizzles = &swizzle; |
| |
| std::array<VkViewport, 2> viewports = {}; |
| std::array<VkRect2D, 2> scissors = {}; |
| |
| viewports.fill({0, 0, 16, 16, 0, 1}); |
| scissors.fill({{0, 0}, {16, 16}}); |
| |
| auto break_vp_count = [&vp_swizzle_state, &viewports, &scissors](CreatePipelineHelper &helper) { |
| helper.vp_state_ci_.viewportCount = size32(viewports); |
| helper.vp_state_ci_.pViewports = viewports.data(); |
| helper.vp_state_ci_.scissorCount = size32(scissors); |
| helper.vp_state_ci_.pScissors = scissors.data(); |
| helper.vp_state_ci_.pNext = &vp_swizzle_state; |
| ASSERT_TRUE(vp_swizzle_state.viewportCount < helper.vp_state_ci_.viewportCount); |
| }; |
| |
| CreatePipelineHelper::OneshotTest(*this, break_vp_count, kErrorBit, |
| "VUID-VkPipelineViewportSwizzleStateCreateInfoNV-viewportCount-01215"); |
| } |
| } |
| |
| TEST_F(NegativePipeline, CreationFeedbackCount) { |
| TEST_DESCRIPTION("Test graphics pipeline feedback stage count check."); |
| |
| AddRequiredExtensions(VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| if (IsPlatformMockICD()) { |
| GTEST_SKIP() << "Driver data writeback check not supported by MockICD"; |
| } |
| |
| VkPipelineCreationFeedbackCreateInfo feedback_info = vku::InitStructHelper(); |
| VkPipelineCreationFeedback feedbacks[3] = {}; |
| // Set flags to known value that the driver has to overwrite |
| feedbacks[0].flags = VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM; |
| |
| feedback_info.pPipelineCreationFeedback = &feedbacks[0]; |
| feedback_info.pipelineStageCreationFeedbackCount = 2; |
| feedback_info.pPipelineStageCreationFeedbacks = &feedbacks[1]; |
| |
| auto set_feedback = [&feedback_info](CreatePipelineHelper &helper) { helper.gp_ci_.pNext = &feedback_info; }; |
| |
| CreatePipelineHelper::OneshotTest(*this, set_feedback, kErrorBit); |
| |
| if (feedback_info.pPipelineCreationFeedback->flags == VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM) { |
| m_errorMonitor->SetError("ValidationLayers did not return GraphicsPipelineFeedback driver data properly."); |
| } |
| |
| feedback_info.pipelineStageCreationFeedbackCount = 1; |
| CreatePipelineHelper::OneshotTest(*this, set_feedback, kErrorBit, |
| "VUID-VkGraphicsPipelineCreateInfo-pipelineStageCreationFeedbackCount-06594"); |
| } |
| |
| TEST_F(NegativePipeline, CreationFeedbackCountCompute) { |
| TEST_DESCRIPTION("Test compute pipeline feedback stage count check."); |
| |
| AddRequiredExtensions(VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineCreationFeedbackCreateInfo feedback_info = vku::InitStructHelper(); |
| VkPipelineCreationFeedback feedbacks[3] = {}; |
| feedback_info.pPipelineCreationFeedback = &feedbacks[0]; |
| feedback_info.pipelineStageCreationFeedbackCount = 1; |
| feedback_info.pPipelineStageCreationFeedbacks = &feedbacks[1]; |
| |
| const auto set_info = [&](CreateComputePipelineHelper &helper) { helper.cp_ci_.pNext = &feedback_info; }; |
| |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit); |
| |
| feedback_info.pipelineStageCreationFeedbackCount = 2; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, |
| "VUID-VkComputePipelineCreateInfo-pipelineStageCreationFeedbackCount-06566"); |
| } |
| |
| TEST_F(NegativePipeline, LineRasterization) { |
| TEST_DESCRIPTION("Test VK_EXT_line_rasterization state against feature enables."); |
| |
| AddRequiredExtensions(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| { |
| constexpr std::array vuids = {"VUID-VkGraphicsPipelineCreateInfo-lineRasterizationMode-02766", |
| "VUID-VkPipelineRasterizationLineStateCreateInfo-lineRasterizationMode-02769"}; |
| CreatePipelineHelper::OneshotTest( |
| *this, |
| [&](CreatePipelineHelper &helper) { |
| helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM; |
| helper.ms_ci_.alphaToCoverageEnable = VK_TRUE; |
| }, |
| kErrorBit, vuids); |
| } |
| { |
| constexpr std::array vuids = {"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767", |
| "VUID-VkPipelineRasterizationLineStateCreateInfo-lineRasterizationMode-02769", |
| "VUID-VkPipelineRasterizationLineStateCreateInfo-stippledLineEnable-02772"}; |
| CreatePipelineHelper::OneshotTest( |
| *this, |
| [&](CreatePipelineHelper &helper) { |
| helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM; |
| helper.line_state_ci_.stippledLineEnable = VK_TRUE; |
| }, |
| kErrorBit, vuids); |
| } |
| { |
| constexpr std::array vuids = {"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767", |
| "VUID-VkPipelineRasterizationLineStateCreateInfo-lineRasterizationMode-02768", |
| "VUID-VkPipelineRasterizationLineStateCreateInfo-stippledLineEnable-02771"}; |
| CreatePipelineHelper::OneshotTest( |
| *this, |
| [&](CreatePipelineHelper &helper) { |
| helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR; |
| helper.line_state_ci_.stippledLineEnable = VK_TRUE; |
| }, |
| kErrorBit, vuids); |
| } |
| { |
| constexpr std::array vuids = {"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767", |
| "VUID-VkPipelineRasterizationLineStateCreateInfo-lineRasterizationMode-02770", |
| "VUID-VkPipelineRasterizationLineStateCreateInfo-stippledLineEnable-02773"}; |
| CreatePipelineHelper::OneshotTest( |
| *this, |
| [&](CreatePipelineHelper &helper) { |
| helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH; |
| helper.line_state_ci_.stippledLineEnable = VK_TRUE; |
| }, |
| kErrorBit, vuids); |
| } |
| { |
| constexpr std::array vuids = {"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767", |
| "VUID-VkPipelineRasterizationLineStateCreateInfo-stippledLineEnable-02774"}; |
| CreatePipelineHelper::OneshotTest( |
| *this, |
| [&](CreatePipelineHelper &helper) { |
| helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT; |
| helper.line_state_ci_.stippledLineEnable = VK_TRUE; |
| }, |
| kErrorBit, vuids); |
| } |
| |
| m_command_buffer.Begin(); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdSetLineStipple-lineStippleFactor-02776"); |
| vk::CmdSetLineStippleEXT(m_command_buffer, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| vk::CmdSetLineStippleEXT(m_command_buffer, 1, 1); |
| } |
| |
| TEST_F(NegativePipeline, NotCompatibleForSet) { |
| TEST_DESCRIPTION("Check that validation path catches pipeline layout inconsistencies for bind vs. dispatch"); |
| RETURN_IF_SKIP(Init()); |
| |
| if (m_device->QueuesWithComputeCapability().empty()) { |
| GTEST_SKIP() << "compute queue not supported"; |
| } |
| |
| vkt::Buffer storage_buffer(*m_device, 4, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); |
| vkt::Buffer uniform_buffer(*m_device, 20, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); |
| |
| std::vector<VkDescriptorSetLayoutBinding> binding_defs = { |
| {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, |
| {1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, |
| }; |
| const vkt::DescriptorSetLayout pipeline_dsl(*m_device, binding_defs); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&pipeline_dsl}); |
| |
| // We now will use a slightly different Layout definition for the descriptors we acutally bind with (but that would still be |
| // correct for the shader |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}, |
| {1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}}); |
| const vkt::PipelineLayout binding_pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| descriptor_set.WriteDescriptorBufferInfo(0, storage_buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); |
| descriptor_set.WriteDescriptorBufferInfo(1, uniform_buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| const char *csSource = R"glsl( |
| #version 450 |
| layout(set = 0, binding = 0) buffer StorageBuffer { uint index; } u_index; |
| layout(set = 0, binding = 1) uniform UniformStruct { ivec4 dummy; int val; } ubo; |
| |
| void main() { |
| u_index.index = ubo.val; |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, binding_pipeline_layout, 0, 1, &descriptor_set.set_, |
| 0, nullptr); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-08600"); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativePipeline, NotCompatibleForSetIndependent) { |
| TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/9870"); |
| AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| vkt::Buffer uniform_buffer(*m_device, 16, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| descriptor_set.WriteDescriptorBufferInfo(0, uniform_buffer, 0, VK_WHOLE_SIZE); |
| descriptor_set.UpdateDescriptorSets(); |
| |
| const vkt::PipelineLayout pipeline_layout_1(*m_device, {&descriptor_set.layout_}, {}, |
| VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT); |
| const vkt::PipelineLayout pipeline_layout_2(*m_device, {&descriptor_set.layout_}); |
| |
| const char *csSource = R"glsl( |
| #version 450 |
| layout(set = 0, binding = 0) uniform UniformStruct { uint dummy; } ubo; |
| void main() { |
| uint x = ubo.dummy; // make descriptor set statically used |
| } |
| )glsl"; |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipeline_layout_1; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout_2, 0, 1, &descriptor_set.set_, 0, |
| nullptr); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-08600"); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativePipeline, DescriptorSetNotBound) { |
| RETURN_IF_SKIP(Init()); |
| |
| const char *cs_source = R"glsl( |
| #version 450 |
| layout(set = 0, binding = 0) buffer SSBO { uint x; }; |
| void main() { |
| x = 0; |
| } |
| )glsl"; |
| |
| OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_}); |
| |
| CreateComputePipelineHelper pipe(*this); |
| pipe.cs_ = VkShaderObj(*m_device, cs_source, VK_SHADER_STAGE_COMPUTE_BIT); |
| pipe.cp_ci_.layout = pipeline_layout; |
| pipe.CreateComputePipeline(); |
| |
| m_command_buffer.Begin(); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipe); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDispatch-None-08600"); |
| vk::CmdDispatch(m_command_buffer, 1, 1, 1); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativePipeline, MaxPerStageResources) { |
| TEST_DESCRIPTION("Check case where pipeline is created that exceeds maxPerStageResources"); |
| |
| RETURN_IF_SKIP(InitFramework()); |
| PFN_vkSetPhysicalDeviceLimitsEXT fpvkSetPhysicalDeviceLimitsEXT = nullptr; |
| PFN_vkGetOriginalPhysicalDeviceLimitsEXT fpvkGetOriginalPhysicalDeviceLimitsEXT = nullptr; |
| if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceLimitsEXT, fpvkGetOriginalPhysicalDeviceLimitsEXT)) { |
| GTEST_SKIP() << "Failed to load device profile layer."; |
| } |
| |
| // Spec requires a minimum of 128 so know this is setting it lower than that |
| const uint32_t maxPerStageResources = 4; |
| VkPhysicalDeviceProperties props; |
| fpvkGetOriginalPhysicalDeviceLimitsEXT(Gpu(), &props.limits); |
| props.limits.maxPerStageResources = maxPerStageResources; |
| fpvkSetPhysicalDeviceLimitsEXT(Gpu(), &props.limits); |
| RETURN_IF_SKIP(InitState()); |
| // Adds the one color attachment |
| InitRenderTarget(); |
| |
| // A case where it shouldn't error because no single stage is over limit |
| std::vector<VkDescriptorSetLayoutBinding> layout_bindings_normal = { |
| {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, maxPerStageResources, VK_SHADER_STAGE_VERTEX_BIT, nullptr}, |
| {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}}; |
| |
| // vertex test |
| std::vector<VkDescriptorSetLayoutBinding> layout_bindings_vert = { |
| {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, maxPerStageResources, VK_SHADER_STAGE_VERTEX_BIT, nullptr}, |
| {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}; |
| |
| // fragment only has it at the limit because color attachment should push it over |
| std::vector<VkDescriptorSetLayoutBinding> layout_bindings_frag = { |
| {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, maxPerStageResources, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}}; |
| |
| // compute test |
| std::vector<VkDescriptorSetLayoutBinding> layout_bindings_comp = { |
| {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, maxPerStageResources, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, |
| {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}}; |
| |
| // Have case where it pushes limit from two setLayouts instead of two setLayoutBindings |
| std::vector<VkDescriptorSetLayoutBinding> layout_binding_combined0 = { |
| {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, maxPerStageResources, VK_SHADER_STAGE_VERTEX_BIT, nullptr}}; |
| std::vector<VkDescriptorSetLayoutBinding> layout_binding_combined1 = { |
| {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, nullptr}}; |
| |
| const vkt::DescriptorSetLayout ds_layout_normal(*m_device, layout_bindings_normal); |
| const vkt::DescriptorSetLayout ds_layout_vert(*m_device, layout_bindings_vert); |
| const vkt::DescriptorSetLayout ds_layout_frag(*m_device, layout_bindings_frag); |
| const vkt::DescriptorSetLayout ds_layout_comp(*m_device, layout_bindings_comp); |
| const vkt::DescriptorSetLayout ds_layout_combined0(*m_device, layout_binding_combined0); |
| const vkt::DescriptorSetLayout ds_layout_combined1(*m_device, layout_binding_combined1); |
| |
| CreateComputePipelineHelper compute_pipe(*this); |
| compute_pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {&ds_layout_comp}); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-layout-01687"); |
| compute_pipe.CreateComputePipeline(); |
| m_errorMonitor->VerifyFound(); |
| |
| { |
| CreatePipelineHelper graphics_pipe(*this); |
| graphics_pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {&ds_layout_normal}); |
| graphics_pipe.CreateGraphicsPipeline(); |
| } |
| |
| { |
| CreatePipelineHelper graphics_pipe(*this); |
| graphics_pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {&ds_layout_vert}); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-01688"); |
| graphics_pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| { |
| CreatePipelineHelper graphics_pipe(*this); |
| graphics_pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {&ds_layout_frag}); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-01688"); |
| graphics_pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| { |
| CreatePipelineHelper graphics_pipe(*this); |
| graphics_pipe.pipeline_layout_ = vkt::PipelineLayout(*m_device, {&ds_layout_combined0, &ds_layout_combined1}); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-layout-01688"); |
| graphics_pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativePipeline, PipelineExecutablePropertiesFeature) { |
| TEST_DESCRIPTION("Try making calls without pipelineExecutableInfo."); |
| |
| AddRequiredExtensions(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| // MockICD will return 0 for the executable count |
| if (IsPlatformMockICD()) { |
| GTEST_SKIP() << "Test not supported by MockICD"; |
| } |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.CreateGraphicsPipeline(); |
| |
| uint32_t count; |
| VkPipelineExecutableInfoKHR pipeline_exe_info = vku::InitStructHelper(); |
| pipeline_exe_info.pipeline = pipe; |
| pipeline_exe_info.executableIndex = 0; |
| |
| VkPipelineInfoKHR pipeline_info = vku::InitStructHelper(); |
| pipeline_info.pipeline = pipe; |
| |
| m_errorMonitor->SetDesiredError("VUID-vkGetPipelineExecutableInternalRepresentationsKHR-pipelineExecutableInfo-03276"); |
| m_errorMonitor->SetDesiredError("VUID-vkGetPipelineExecutableInternalRepresentationsKHR-pipeline-03278"); |
| vk::GetPipelineExecutableInternalRepresentationsKHR(device(), &pipeline_exe_info, &count, nullptr); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkGetPipelineExecutableStatisticsKHR-pipelineExecutableInfo-03272"); |
| m_errorMonitor->SetDesiredError("VUID-vkGetPipelineExecutableStatisticsKHR-pipeline-03274"); |
| vk::GetPipelineExecutableStatisticsKHR(device(), &pipeline_exe_info, &count, nullptr); |
| m_errorMonitor->VerifyFound(); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkGetPipelineExecutablePropertiesKHR-pipelineExecutableInfo-03270"); |
| vk::GetPipelineExecutablePropertiesKHR(device(), &pipeline_info, &count, nullptr); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, SampledInvalidImageViews) { |
| TEST_DESCRIPTION("Test if an VkImageView is sampled at draw/dispatch that the format has valid format features enabled"); |
| AddRequiredExtensions(VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| PFN_vkSetPhysicalDeviceFormatPropertiesEXT fpvkSetPhysicalDeviceFormatPropertiesEXT = nullptr; |
| PFN_vkGetOriginalPhysicalDeviceFormatPropertiesEXT fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT = nullptr; |
| if (!LoadDeviceProfileLayer(fpvkSetPhysicalDeviceFormatPropertiesEXT, fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT)) { |
| GTEST_SKIP() << "Failed to load device profile layer."; |
| } |
| |
| const VkFormat sampled_format = VK_FORMAT_R8G8B8A8_UNORM; |
| |
| // Remove format features want to test if missing |
| VkFormatProperties formatProps; |
| fpvkGetOriginalPhysicalDeviceFormatPropertiesEXT(Gpu(), sampled_format, &formatProps); |
| formatProps.optimalTilingFeatures = (formatProps.optimalTilingFeatures & ~VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT); |
| fpvkSetPhysicalDeviceFormatPropertiesEXT(Gpu(), sampled_format, formatProps); |
| |
| vkt::Image image(*m_device, 128, 128, sampled_format, VK_IMAGE_USAGE_SAMPLED_BIT); |
| vkt::ImageView imageView = image.CreateView(); |
| |
| // maps to VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER |
| const char *fs_source_combined = R"glsl( |
| #version 450 |
| layout (set=0, binding=0) uniform sampler2D samplerColor; |
| layout(location=0) out vec4 color; |
| void main() { |
| color = texture(samplerColor, gl_FragCoord.xy); |
| color += texture(samplerColor, gl_FragCoord.wz); |
| } |
| )glsl"; |
| VkShaderObj fs_combined(*m_device, fs_source_combined, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| // maps to VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE and VK_DESCRIPTOR_TYPE_SAMPLER |
| const char *fs_source_seperate = R"glsl( |
| #version 450 |
| layout (set=0, binding=0) uniform texture2D textureColor; |
| layout (set=0, binding=1) uniform sampler samplers; |
| layout(location=0) out vec4 color; |
| // test can be detected from function |
| vec4 foo(texture2D _texture, sampler _sampler) { |
| return texture(sampler2D(_texture, _sampler), gl_FragCoord.xy); |
| } |
| void main() { |
| color = foo(textureColor, samplers); |
| } |
| )glsl"; |
| VkShaderObj fs_seperate(*m_device, fs_source_seperate, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| // maps to an unused image sampler that should not trigger validation as it is never sampled |
| const char *fs_source_unused = R"glsl( |
| #version 450 |
| layout (set=0, binding=0) uniform sampler2D samplerColor; |
| layout(location=0) out vec4 color; |
| void main() { |
| color = vec4(gl_FragCoord.xyz, 1.0); |
| } |
| )glsl"; |
| VkShaderObj fs_unused(*m_device, fs_source_unused, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| // maps to VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER but makes sure it walks function tree to find sampling |
| const char *fs_source_function = R"glsl( |
| #version 450 |
| layout (set=0, binding=0) uniform sampler2D samplerColor; |
| layout(location=0) out vec4 color; |
| vec4 foo() { return texture(samplerColor, gl_FragCoord.xy); } |
| vec4 bar(float x) { return (x > 0.5) ? foo() : vec4(1.0,1.0,1.0,1.0); } |
| void main() { |
| color = bar(gl_FragCoord.x); |
| } |
| )glsl"; |
| VkShaderObj fs_function(*m_device, fs_source_function, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| CreatePipelineHelper pipeline_combined(*this); |
| CreatePipelineHelper pipeline_seperate(*this); |
| CreatePipelineHelper pipeline_unused(*this); |
| CreatePipelineHelper pipeline_function(*this); |
| |
| // 4 different pipelines for 4 different shaders |
| // 3 are invalid and 1 (pipeline_unused) is valid |
| pipeline_combined.shader_stages_[1] = fs_combined.GetStageCreateInfo(); |
| pipeline_seperate.shader_stages_[1] = fs_seperate.GetStageCreateInfo(); |
| pipeline_unused.shader_stages_[1] = fs_unused.GetStageCreateInfo(); |
| pipeline_function.shader_stages_[1] = fs_function.GetStageCreateInfo(); |
| |
| OneOffDescriptorSet combined_descriptor_set( |
| m_device, {{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}}); |
| OneOffDescriptorSet seperate_descriptor_set(m_device, |
| {{0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}, |
| {1, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}}); |
| const vkt::PipelineLayout combined_pipeline_layout(*m_device, {&combined_descriptor_set.layout_}); |
| const vkt::PipelineLayout seperate_pipeline_layout(*m_device, {&seperate_descriptor_set.layout_}); |
| |
| pipeline_combined.gp_ci_.layout = combined_pipeline_layout; |
| pipeline_seperate.gp_ci_.layout = seperate_pipeline_layout; |
| pipeline_unused.gp_ci_.layout = combined_pipeline_layout; |
| pipeline_function.gp_ci_.layout = combined_pipeline_layout; |
| |
| pipeline_combined.CreateGraphicsPipeline(); |
| pipeline_seperate.CreateGraphicsPipeline(); |
| pipeline_unused.CreateGraphicsPipeline(); |
| pipeline_function.CreateGraphicsPipeline(); |
| |
| VkSamplerReductionModeCreateInfo reduction_mode_ci = vku::InitStructHelper(); |
| reduction_mode_ci.reductionMode = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; |
| |
| VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo(&reduction_mode_ci); |
| sampler_ci.minFilter = VK_FILTER_LINEAR; // turned off feature bit for test |
| sampler_ci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; |
| sampler_ci.compareEnable = VK_FALSE; |
| vkt::Sampler sampler_filter(*m_device, sampler_ci); |
| |
| sampler_ci.minFilter = VK_FILTER_NEAREST; |
| sampler_ci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; // turned off feature bit for test |
| vkt::Sampler sampler_mipmap(*m_device, sampler_ci); |
| |
| combined_descriptor_set.WriteDescriptorImageInfo(0, imageView, sampler_filter); |
| combined_descriptor_set.UpdateDescriptorSets(); |
| |
| seperate_descriptor_set.WriteDescriptorImageInfo(0, imageView, VK_NULL_HANDLE, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); |
| seperate_descriptor_set.WriteDescriptorImageInfo(1, VK_NULL_HANDLE, sampler_filter, VK_DESCRIPTOR_TYPE_SAMPLER, |
| VK_IMAGE_LAYOUT_UNDEFINED); |
| seperate_descriptor_set.UpdateDescriptorSets(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRenderPass(m_renderPassBeginInfo); |
| |
| // Unused is a valid version of the combined pipeline/descriptors |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_unused); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, combined_pipeline_layout, 0, 1, |
| &combined_descriptor_set.set_, 0, nullptr); |
| vk::CmdDraw(m_command_buffer, 1, 0, 0, 0); |
| |
| // Test magFilter |
| { |
| // Same descriptor set as combined test |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_function); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-magFilter-04553"); |
| vk::CmdDraw(m_command_buffer, 1, 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // Draw with invalid combined image sampler |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_combined); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-magFilter-04553"); |
| vk::CmdDraw(m_command_buffer, 1, 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // Same error, but not with seperate descriptors |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_seperate); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, seperate_pipeline_layout, 0, 1, |
| &seperate_descriptor_set.set_, 0, nullptr); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-magFilter-04553"); |
| vk::CmdDraw(m_command_buffer, 1, 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // Same test but for mipmap, so need to update descriptors |
| { |
| combined_descriptor_set.Clear(); |
| combined_descriptor_set.WriteDescriptorImageInfo(0, imageView, sampler_mipmap); |
| combined_descriptor_set.UpdateDescriptorSets(); |
| |
| seperate_descriptor_set.Clear(); |
| seperate_descriptor_set.WriteDescriptorImageInfo(1, VK_NULL_HANDLE, sampler_mipmap, VK_DESCRIPTOR_TYPE_SAMPLER, |
| VK_IMAGE_LAYOUT_UNDEFINED); |
| seperate_descriptor_set.UpdateDescriptorSets(); |
| |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, combined_pipeline_layout, 0, 1, |
| &combined_descriptor_set.set_, 0, nullptr); |
| |
| // Same descriptor set as combined test |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_function); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-mipmapMode-04770"); |
| vk::CmdDraw(m_command_buffer, 1, 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // Draw with invalid combined image sampler |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_combined); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-mipmapMode-04770"); |
| vk::CmdDraw(m_command_buffer, 1, 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| // Same error, but not with seperate descriptors |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_seperate); |
| vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, seperate_pipeline_layout, 0, 1, |
| &seperate_descriptor_set.set_, 0, nullptr); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-mipmapMode-04770"); |
| vk::CmdDraw(m_command_buffer, 1, 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativePipeline, ShaderDrawParametersNotEnabled10) { |
| TEST_DESCRIPTION("Validation using DrawParameters for Vulkan 1.0 without the shaderDrawParameters feature enabled."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_0); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| if (DeviceValidationVersion() > VK_API_VERSION_1_0) { |
| GTEST_SKIP() << "Test requires Vulkan exactly 1.0"; |
| } |
| |
| const char *vsSource = R"glsl( |
| #version 460 |
| void main(){ |
| gl_Position = vec4(float(gl_BaseVertex)); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08742"); |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, ShaderDrawParametersNotEnabled11) { |
| TEST_DESCRIPTION("Validation using DrawParameters for Vulkan 1.1 without the shaderDrawParameters feature enabled."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *vsSource = R"glsl( |
| #version 460 |
| void main(){ |
| gl_Position = vec4(float(gl_BaseVertex)); |
| } |
| )glsl"; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkShaderModuleCreateInfo-pCode-08740"); |
| VkShaderObj vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_1); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, CreateFlags) { |
| TEST_DESCRIPTION("Create a graphics pipeline with invalid VkPipelineCreateFlags."); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME); // add to remove many extra errors |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineCreateFlags flags; |
| const auto set_info = [&](CreatePipelineHelper &helper) { helper.gp_ci_.flags = flags; }; |
| |
| flags = VK_PIPELINE_CREATE_DISPATCH_BASE; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-flags-00764"); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-None-09497"); |
| flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, |
| "VUID-VkGraphicsPipelineCreateInfo-graphicsPipelineLibrary-06606"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-flags-03372"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-flags-03373"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-flags-03374"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-flags-03375"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-flags-03376"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-flags-03377"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-flags-03577"); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-None-09497"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-flags-04947"); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-None-09497"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-flags-07401"); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-None-09497"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-flags-07997"); |
| flags = 0x80000000; |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-None-09497"); |
| } |
| |
| TEST_F(NegativePipeline, CreateFlagsCompute) { |
| TEST_DESCRIPTION("Create a compute pipeline with invalid VkPipelineCreateFlags."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME); // add to remove many extra errors |
| RETURN_IF_SKIP(Init()); |
| |
| VkPipelineCreateFlags flags; |
| const auto set_info = [&](CreateComputePipelineHelper &helper) { helper.cp_ci_.flags = flags; }; |
| |
| flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR; |
| m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-None-09497"); |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-shaderEnqueue-09177"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_ANY_HIT_SHADERS_BIT_KHR; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-flags-03365"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_CLOSEST_HIT_SHADERS_BIT_KHR; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-flags-03366"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_MISS_SHADERS_BIT_KHR; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-flags-03367"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_NO_NULL_INTERSECTION_SHADERS_BIT_KHR; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-flags-03368"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_SKIP_TRIANGLES_BIT_KHR; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-flags-03369"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_SKIP_AABBS_BIT_KHR; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-flags-03370"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_SHADER_GROUP_HANDLE_CAPTURE_REPLAY_BIT_KHR; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-flags-03576"); |
| m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-None-09497"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_ALLOW_MOTION_BIT_NV; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-flags-04945"); |
| m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-None-09497"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_OPACITY_MICROMAP_BIT_EXT; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-flags-07367"); |
| m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-None-09497"); |
| flags = VK_PIPELINE_CREATE_RAY_TRACING_DISPLACEMENT_MICROMAP_BIT_NV; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-flags-07996"); |
| flags = VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-None-09497"); |
| flags = 0x80000000; |
| CreateComputePipelineHelper::OneshotTest(*this, set_info, kErrorBit, "VUID-VkComputePipelineCreateInfo-None-09497"); |
| } |
| |
| TEST_F(NegativePipeline, MergePipelineCachesInvalidDst) { |
| TEST_DESCRIPTION("Test mergeing pipeline caches with dst cache in src list"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.CreateGraphicsPipeline(); |
| |
| CreatePipelineHelper other_pipe(*this); |
| other_pipe.CreateGraphicsPipeline(); |
| |
| VkPipelineCache dstCache = pipe.pipeline_cache_; |
| VkPipelineCache srcCaches[2] = {other_pipe.pipeline_cache_, pipe.pipeline_cache_}; |
| |
| m_errorMonitor->SetDesiredError("VUID-vkMergePipelineCaches-dstCache-00770"); |
| vk::MergePipelineCaches(device(), dstCache, 2, srcCaches); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, CreateComputePipelineWithBadBasePointer) { |
| TEST_DESCRIPTION("Create Compute Pipeline with bad base pointer"); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| const char *csSource = R"glsl( |
| #version 450 |
| layout(local_size_x=2, local_size_y=4) in; |
| void main(){ |
| } |
| )glsl"; |
| |
| VkShaderObj cs(*m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT); |
| |
| std::vector<VkDescriptorSetLayoutBinding> bindings(0); |
| const vkt::DescriptorSetLayout pipeline_dsl(*m_device, bindings); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&pipeline_dsl}); |
| |
| VkComputePipelineCreateInfo compute_create_info = vku::InitStructHelper(); |
| compute_create_info.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT; |
| compute_create_info.stage = cs.GetStageCreateInfo(); |
| compute_create_info.layout = pipeline_layout; |
| |
| { |
| compute_create_info.basePipelineHandle = VK_NULL_HANDLE; |
| compute_create_info.basePipelineIndex = 1; |
| m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-flags-07985"); |
| VkPipeline pipeline; |
| vk::CreateComputePipelines(device(), VK_NULL_HANDLE, 1, &compute_create_info, nullptr, &pipeline); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativePipeline, CreateComputePipelineWithDerivatives) { |
| TEST_DESCRIPTION("Create Compute Pipeline with derivatives"); |
| |
| RETURN_IF_SKIP(Init()); |
| |
| const char *csSource = R"glsl( |
| #version 450 |
| layout(local_size_x=2, local_size_y=4) in; |
| void main(){ |
| } |
| )glsl"; |
| |
| VkShaderObj cs(*m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT); |
| |
| std::vector<VkDescriptorSetLayoutBinding> bindings(0); |
| const vkt::DescriptorSetLayout pipeline_dsl(*m_device, bindings); |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&pipeline_dsl}); |
| |
| VkComputePipelineCreateInfo compute_create_infos[2]; |
| compute_create_infos[0] = vku::InitStructHelper(); |
| compute_create_infos[0].stage = cs.GetStageCreateInfo(); |
| compute_create_infos[0].layout = pipeline_layout; |
| |
| compute_create_infos[1] = vku::InitStructHelper(); |
| compute_create_infos[1].stage = cs.GetStageCreateInfo(); |
| compute_create_infos[1].layout = pipeline_layout; |
| |
| { |
| // Create a base pipeline and a derivative in a single call, using 0 as the base. |
| // Base pipeline lacks the VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT flag |
| compute_create_infos[0].flags = 0; |
| compute_create_infos[0].basePipelineHandle = VK_NULL_HANDLE; |
| compute_create_infos[0].basePipelineIndex = -1; |
| compute_create_infos[1].flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT; |
| compute_create_infos[1].basePipelineHandle = VK_NULL_HANDLE; |
| compute_create_infos[1].basePipelineIndex = 0; |
| m_errorMonitor->SetDesiredError("VUID-vkCreateComputePipelines-flags-00696"); |
| |
| VkPipeline pipelines[2] = {VK_NULL_HANDLE, VK_NULL_HANDLE}; |
| vk::CreateComputePipelines(device(), VK_NULL_HANDLE, 2, compute_create_infos, nullptr, pipelines); |
| |
| m_errorMonitor->VerifyFound(); |
| for (auto pipeline : pipelines) { |
| vk::DestroyPipeline(device(), pipeline, nullptr); |
| } |
| } |
| |
| { |
| // Create a base pipeline and a derivative in a single call, using 1 as the base. |
| compute_create_infos[0].flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT; |
| compute_create_infos[0].basePipelineHandle = VK_NULL_HANDLE; |
| compute_create_infos[0].basePipelineIndex = 1; |
| compute_create_infos[1].flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT; |
| compute_create_infos[1].basePipelineHandle = VK_NULL_HANDLE; |
| compute_create_infos[1].basePipelineIndex = -1; |
| m_errorMonitor->SetDesiredError("VUID-vkCreateComputePipelines-flags-00695"); |
| |
| VkPipeline pipelines[2] = {VK_NULL_HANDLE, VK_NULL_HANDLE}; |
| vk::CreateComputePipelines(device(), VK_NULL_HANDLE, 2, compute_create_infos, nullptr, pipelines); |
| |
| m_errorMonitor->VerifyFound(); |
| for (auto pipeline : pipelines) { |
| vk::DestroyPipeline(device(), pipeline, nullptr); |
| } |
| } |
| |
| { |
| // Specify both an index and a handle for base pipeline. |
| compute_create_infos[0].flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT; |
| compute_create_infos[0].basePipelineHandle = VK_NULL_HANDLE; |
| compute_create_infos[0].basePipelineIndex = -1; |
| |
| vkt::Pipeline test_pipeline(*m_device, compute_create_infos[0]); |
| if (test_pipeline.initialized()) { |
| compute_create_infos[1].flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT; |
| compute_create_infos[1].basePipelineHandle = test_pipeline; |
| compute_create_infos[1].basePipelineIndex = 0; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkComputePipelineCreateInfo-flags-07986"); |
| |
| VkPipeline pipelines[2] = {VK_NULL_HANDLE, VK_NULL_HANDLE}; |
| vk::CreateComputePipelines(device(), VK_NULL_HANDLE, 2, compute_create_infos, nullptr, pipelines); |
| |
| m_errorMonitor->VerifyFound(); |
| |
| for (auto pipeline : pipelines) { |
| vk::DestroyPipeline(device(), pipeline, nullptr); |
| } |
| } |
| } |
| } |
| |
| TEST_F(NegativePipeline, GraphicsPipelineWithBadBasePointer) { |
| TEST_DESCRIPTION("Create Graphics Pipeline with bad base pointer"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| CreatePipelineHelper base_pipe(*this); |
| base_pipe.CreateGraphicsPipeline(); |
| |
| { |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT; |
| pipe.gp_ci_.basePipelineHandle = VK_NULL_HANDLE; |
| pipe.gp_ci_.basePipelineIndex = 2; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-flags-07985"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| { |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT; |
| pipe.gp_ci_.basePipelineHandle = base_pipe; |
| pipe.gp_ci_.basePipelineIndex = 2; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-flags-07986"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativePipeline, DiscardRectangle) { |
| TEST_DESCRIPTION("Create a graphics pipeline invalid VkPipelineDiscardRectangleStateCreateInfoEXT"); |
| |
| AddRequiredExtensions(VK_EXT_DISCARD_RECTANGLES_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPhysicalDeviceDiscardRectanglePropertiesEXT discard_rectangle_properties = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(discard_rectangle_properties); |
| |
| uint32_t count = discard_rectangle_properties.maxDiscardRectangles + 1; |
| std::vector<VkRect2D> discard_rectangles(count); |
| |
| VkPipelineDiscardRectangleStateCreateInfoEXT discard_rectangle_state = |
| vku::InitStructHelper(); |
| discard_rectangle_state.discardRectangleCount = count; |
| discard_rectangle_state.pDiscardRectangles = discard_rectangles.data(); |
| |
| CreatePipelineHelper pipe(*this, &discard_rectangle_state); |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineDiscardRectangleStateCreateInfoEXT-discardRectangleCount-00582"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, ColorWriteCreateInfoEXT) { |
| TEST_DESCRIPTION("Test VkPipelineColorWriteCreateInfoEXT in color blend state pNext"); |
| |
| AddRequiredExtensions(VK_EXT_COLOR_WRITE_ENABLE_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(); |
| |
| VkBool32 enabled = VK_FALSE; |
| color_write.attachmentCount = 1; |
| color_write.pColorWriteEnables = &enabled; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineColorWriteCreateInfoEXT-pAttachments-04801"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, ColorWriteCreateInfoEXTMaxAttachments) { |
| TEST_DESCRIPTION("Test VkPipelineColorWriteCreateInfoEXT in color blend state pNext with too many attachments"); |
| |
| AddRequiredExtensions(VK_EXT_COLOR_WRITE_ENABLE_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| uint32_t max_color_attachments = m_device->Physical().limits_.maxColorAttachments + 1; |
| |
| std::vector<VkBool32> enables(max_color_attachments, VK_TRUE); |
| VkPipelineColorWriteCreateInfoEXT color_write = vku::InitStructHelper(); |
| color_write.attachmentCount = max_color_attachments; |
| color_write.pColorWriteEnables = enables.data(); |
| |
| std::vector<VkPipelineColorBlendAttachmentState> color_blends(max_color_attachments); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.cb_ci_.pNext = &color_write; |
| pipe.cb_ci_.attachmentCount = max_color_attachments; |
| pipe.cb_ci_.pAttachments = color_blends.data(); |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineColorWriteCreateInfoEXT-attachmentCount-06655"); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-07609"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, VariableSampleLocations) { |
| TEST_DESCRIPTION("Validate using VkPhysicalDeviceSampleLocationsPropertiesEXT"); |
| |
| AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| VkPhysicalDeviceSampleLocationsPropertiesEXT sample_locations = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(sample_locations); |
| |
| if (sample_locations.variableSampleLocations) { |
| GTEST_SKIP() << "VkPhysicalDeviceSampleLocationsPropertiesEXT::variableSampleLocations is supported, skipping."; |
| } |
| |
| VkAttachmentReference attach = {}; |
| attach.layout = VK_IMAGE_LAYOUT_GENERAL; |
| |
| VkSubpassDescription subpass = {}; |
| subpass.pColorAttachments = &attach; |
| subpass.colorAttachmentCount = 1; |
| |
| VkAttachmentDescription attach_desc = {}; |
| attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM; |
| attach_desc.samples = VK_SAMPLE_COUNT_1_BIT; |
| attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; |
| attach_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL; |
| |
| VkSubpassDescription subpasses[2] = {subpass, subpass}; |
| VkSubpassDependency subpass_dependency = {0, |
| 1, |
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, |
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| VK_DEPENDENCY_BY_REGION_BIT}; |
| |
| VkRenderPassCreateInfo rpci = vku::InitStructHelper(); |
| rpci.subpassCount = 2; |
| rpci.pSubpasses = subpasses; |
| rpci.attachmentCount = 1; |
| rpci.pAttachments = &attach_desc; |
| rpci.dependencyCount = 1; |
| rpci.pDependencies = &subpass_dependency; |
| vkt::RenderPass render_pass(*m_device, rpci); |
| |
| vkt::Image image(*m_device, 32, 32, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); |
| vkt::ImageView image_view = image.CreateView(); |
| |
| vkt::Framebuffer framebuffer(*m_device, render_pass, 1, &image_view.handle()); |
| |
| VkMultisamplePropertiesEXT multisample_prop = vku::InitStructHelper(); |
| vk::GetPhysicalDeviceMultisamplePropertiesEXT(Gpu(), VK_SAMPLE_COUNT_1_BIT, &multisample_prop); |
| const uint32_t valid_count = |
| multisample_prop.maxSampleLocationGridSize.width * multisample_prop.maxSampleLocationGridSize.height; |
| |
| if (valid_count == 0) { |
| GTEST_SKIP() << "multisample properties are not supported"; |
| } |
| |
| 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_locations_state = |
| vku::InitStructHelper(); |
| sample_locations_state.sampleLocationsEnable = VK_TRUE; |
| sample_locations_state.sampleLocationsInfo = sample_locations_info; |
| |
| VkPipelineMultisampleStateCreateInfo multi_sample_state = vku::InitStructHelper(&sample_locations_state); |
| multi_sample_state.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; |
| multi_sample_state.sampleShadingEnable = VK_FALSE; |
| multi_sample_state.minSampleShading = 1.0; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.pMultisampleState = &multi_sample_state; |
| pipe.gp_ci_.renderPass = render_pass; |
| pipe.CreateGraphicsPipeline(); |
| |
| VkClearValue clear_value; |
| clear_value.color.float32[0] = 0.25f; |
| clear_value.color.float32[1] = 0.25f; |
| clear_value.color.float32[2] = 0.25f; |
| clear_value.color.float32[3] = 0.0f; |
| |
| VkAttachmentSampleLocationsEXT attachment_sample_locations; |
| attachment_sample_locations.attachmentIndex = 0; |
| attachment_sample_locations.sampleLocationsInfo = sample_locations_info; |
| VkSubpassSampleLocationsEXT subpass_sample_locations; |
| subpass_sample_locations.subpassIndex = 0; |
| subpass_sample_locations.sampleLocationsInfo = sample_locations_info; |
| |
| VkRenderPassSampleLocationsBeginInfoEXT render_pass_sample_locations = vku::InitStructHelper(); |
| render_pass_sample_locations.attachmentInitialSampleLocationsCount = 1; |
| render_pass_sample_locations.pAttachmentInitialSampleLocations = &attachment_sample_locations; |
| render_pass_sample_locations.postSubpassSampleLocationsCount = 1; |
| render_pass_sample_locations.pPostSubpassSampleLocations = &subpass_sample_locations; |
| |
| sample_location[0].x = |
| 0.0f; // Invalid, VkRenderPassSampleLocationsBeginInfoEXT wont match VkPipelineSampleLocationsStateCreateInfoEXT |
| |
| VkRenderPassBeginInfo begin_info = vku::InitStructHelper(&render_pass_sample_locations); |
| begin_info.renderPass = render_pass; |
| begin_info.framebuffer = framebuffer; |
| begin_info.renderArea.extent = {32, 32}; |
| begin_info.renderArea.offset = {0, 0}; |
| begin_info.clearValueCount = 1; |
| begin_info.pClearValues = &clear_value; |
| |
| m_command_buffer.Begin(); |
| vk::CmdBeginRenderPass(m_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE); |
| |
| m_errorMonitor->SetDesiredError("VUID-vkCmdBindPipeline-variableSampleLocations-01525"); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.NextSubpass(); |
| sample_location[0].x = 0.5f; |
| m_errorMonitor->SetDesiredError("VUID-vkCmdBindPipeline-variableSampleLocations-01525"); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.EndRenderPass(); |
| |
| begin_info.pNext = nullptr; // Invalid, missing VkRenderPassSampleLocationsBeginInfoEXT |
| vk::CmdBeginRenderPass(m_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdBindPipeline-variableSampleLocations-01525"); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.NextSubpass(); |
| m_command_buffer.EndRenderPass(); |
| |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativePipeline, RasterizationConservativeStateCreateInfo) { |
| TEST_DESCRIPTION("Test PipelineRasterizationConservativeStateCreateInfo."); |
| |
| AddRequiredExtensions(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservative_rasterization_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(conservative_rasterization_props); |
| |
| VkPipelineRasterizationConservativeStateCreateInfoEXT conservative_state = |
| vku::InitStructHelper(); |
| conservative_state.extraPrimitiveOverestimationSize = -1.0f; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.rs_state_ci_.pNext = &conservative_state; |
| |
| m_errorMonitor->SetDesiredError( |
| "VUID-VkPipelineRasterizationConservativeStateCreateInfoEXT-extraPrimitiveOverestimationSize-01769"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| |
| conservative_state.extraPrimitiveOverestimationSize = |
| conservative_rasterization_props.maxExtraPrimitiveOverestimationSize + 0.1f; |
| m_errorMonitor->SetDesiredError( |
| "VUID-VkPipelineRasterizationConservativeStateCreateInfoEXT-extraPrimitiveOverestimationSize-01769"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, NullRenderPass) { |
| TEST_DESCRIPTION("Test for a creating a pipeline with a null renderpass but VK_KHR_dynamic_rendering is not enabled"); |
| RETURN_IF_SKIP(Init()); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.renderPass = VK_NULL_HANDLE; |
| pipe.cb_ci_.attachmentCount = 0; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-dynamicRendering-06576"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, RasterizationOrderAttachmentAccessWithoutFeature) { |
| TEST_DESCRIPTION("Test for a creating a pipeline with VK_ARM_rasterization_order_attachment_access enabled"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| VkPipelineDepthStencilStateCreateInfo ds_ci = vku::InitStructHelper(); |
| VkPipelineColorBlendAttachmentState cb_as = {}; |
| VkPipelineColorBlendStateCreateInfo cb_ci = vku::InitStructHelper(); |
| cb_ci.attachmentCount = 1; |
| cb_ci.pAttachments = &cb_as; |
| |
| VkAttachmentDescription attachments[2] = {}; |
| attachments[0].flags = 0; |
| attachments[0].format = VK_FORMAT_B8G8R8A8_UNORM; |
| attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; |
| attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; |
| attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; |
| attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; |
| attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; |
| attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| |
| attachments[1].flags = 0; |
| attachments[1].format = FindSupportedDepthStencilFormat(this->Gpu()); |
| attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; |
| attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; |
| attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; |
| attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; |
| attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; |
| attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| |
| VkAttachmentReference cAttachRef = {}; |
| cAttachRef.attachment = 0; |
| cAttachRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| |
| VkAttachmentReference dsAttachRef = {}; |
| dsAttachRef.attachment = 1; |
| dsAttachRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| |
| VkSubpassDescription subpass = {}; |
| subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; |
| subpass.colorAttachmentCount = 1; |
| subpass.pColorAttachments = &cAttachRef; |
| subpass.pDepthStencilAttachment = &dsAttachRef; |
| subpass.flags = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT | |
| VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT | |
| VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT; |
| |
| VkRenderPassCreateInfo rpci = vku::InitStructHelper(); |
| rpci.attachmentCount = 2; |
| rpci.pAttachments = attachments; |
| rpci.subpassCount = 1; |
| rpci.pSubpasses = &subpass; |
| |
| vkt::RenderPass render_pass(*m_device, rpci); |
| |
| auto set_info = [&](CreatePipelineHelper &helper) { |
| helper.gp_ci_.pDepthStencilState = &ds_ci; |
| helper.gp_ci_.pColorBlendState = &cb_ci; |
| helper.gp_ci_.renderPass = render_pass; |
| }; |
| |
| // Color attachment |
| cb_ci.flags = VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT; |
| ds_ci.flags = 0; |
| |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, |
| "VUID-VkPipelineColorBlendStateCreateInfo-rasterizationOrderColorAttachmentAccess-06465"); |
| |
| // Depth attachment |
| cb_ci.flags = 0; |
| ds_ci.flags = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT; |
| |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, |
| "VUID-VkPipelineDepthStencilStateCreateInfo-rasterizationOrderDepthAttachmentAccess-06463"); |
| |
| // Stencil attachment |
| cb_ci.flags = 0; |
| ds_ci.flags = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT; |
| |
| CreatePipelineHelper::OneshotTest(*this, set_info, kErrorBit, |
| "VUID-VkPipelineDepthStencilStateCreateInfo-rasterizationOrderStencilAttachmentAccess-06464"); |
| } |
| |
| TEST_F(NegativePipeline, RasterizationOrderAttachmentAccessNoSubpassFlags) { |
| TEST_DESCRIPTION("Test for a creating a pipeline with VK_ARM_rasterization_order_attachment_access enabled"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()); |
| |
| VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM rasterization_order_features = vku::InitStructHelper(); |
| GetPhysicalDeviceFeatures2(rasterization_order_features); |
| |
| if (!rasterization_order_features.rasterizationOrderColorAttachmentAccess && |
| !rasterization_order_features.rasterizationOrderDepthAttachmentAccess && |
| !rasterization_order_features.rasterizationOrderStencilAttachmentAccess) { |
| GTEST_SKIP() << "Test requires (unsupported) rasterizationOrder*AttachmentAccess"; |
| } |
| |
| RETURN_IF_SKIP(InitState(nullptr, &rasterization_order_features)); |
| |
| VkPipelineDepthStencilStateCreateInfo ds_ci = vku::InitStructHelper(); |
| VkPipelineColorBlendAttachmentState cb_as = {}; |
| VkPipelineColorBlendStateCreateInfo cb_ci = vku::InitStructHelper(); |
| cb_ci.attachmentCount = 1; |
| cb_ci.pAttachments = &cb_as; |
| VkRenderPass render_pass_handle = VK_NULL_HANDLE; |
| |
| auto create_render_pass = [&](VkPipelineDepthStencilStateCreateFlags subpass_flags, vkt::RenderPass &render_pass) { |
| VkAttachmentDescription attachments[2] = {}; |
| attachments[0].flags = 0; |
| attachments[0].format = VK_FORMAT_B8G8R8A8_UNORM; |
| attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; |
| attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; |
| attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; |
| attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; |
| attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; |
| attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| |
| attachments[1].flags = 0; |
| attachments[1].format = FindSupportedDepthStencilFormat(this->Gpu()); |
| attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; |
| attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; |
| attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; |
| attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; |
| attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; |
| attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| |
| VkAttachmentReference cAttachRef = {}; |
| cAttachRef.attachment = 0; |
| cAttachRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| |
| VkAttachmentReference dsAttachRef = {}; |
| dsAttachRef.attachment = 1; |
| dsAttachRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| |
| VkSubpassDescription subpass = {}; |
| subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; |
| subpass.colorAttachmentCount = 1; |
| subpass.pColorAttachments = &cAttachRef; |
| subpass.pDepthStencilAttachment = &dsAttachRef; |
| subpass.flags = subpass_flags; |
| |
| VkRenderPassCreateInfo rpci = vku::InitStructHelper(); |
| rpci.attachmentCount = 2; |
| rpci.pAttachments = attachments; |
| rpci.subpassCount = 1; |
| rpci.pSubpasses = &subpass; |
| |
| render_pass.Init(*this->m_device, rpci); |
| }; |
| |
| auto set_flgas_pipeline_createinfo = [&](CreatePipelineHelper &helper) { |
| helper.gp_ci_.pDepthStencilState = &ds_ci; |
| helper.gp_ci_.pColorBlendState = &cb_ci; |
| helper.gp_ci_.renderPass = render_pass_handle; |
| }; |
| |
| vkt::RenderPass render_pass_no_flags; |
| create_render_pass(0, render_pass_no_flags); |
| render_pass_handle = render_pass_no_flags; |
| |
| // Color attachment |
| if (rasterization_order_features.rasterizationOrderColorAttachmentAccess) { |
| cb_ci.flags = VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_EXT; |
| ds_ci.flags = 0; |
| |
| CreatePipelineHelper::OneshotTest(*this, set_flgas_pipeline_createinfo, kErrorBit, |
| "VUID-VkGraphicsPipelineCreateInfo-renderPass-09527"); |
| } |
| |
| // Depth attachment |
| if (rasterization_order_features.rasterizationOrderDepthAttachmentAccess) { |
| cb_ci.flags = 0; |
| ds_ci.flags = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT; |
| |
| CreatePipelineHelper::OneshotTest(*this, set_flgas_pipeline_createinfo, kErrorBit, |
| "VUID-VkGraphicsPipelineCreateInfo-renderPass-09528"); |
| } |
| |
| // Stencil attachment |
| if (rasterization_order_features.rasterizationOrderStencilAttachmentAccess) { |
| cb_ci.flags = 0; |
| ds_ci.flags = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_EXT; |
| |
| CreatePipelineHelper::OneshotTest(*this, set_flgas_pipeline_createinfo, kErrorBit, |
| "VUID-VkGraphicsPipelineCreateInfo-renderPass-09529"); |
| } |
| |
| if (rasterization_order_features.rasterizationOrderDepthAttachmentAccess) { |
| const char *fsSource = R"glsl( |
| #version 450 |
| layout(early_fragment_tests) in; |
| layout(location = 0) out vec4 uFragColor; |
| void main() { |
| uFragColor = vec4(0,1,0,1); |
| } |
| )glsl"; |
| |
| VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| auto set_stages_pipeline_createinfo = [&](CreatePipelineHelper &helper) { |
| helper.gp_ci_.pDepthStencilState = &ds_ci; |
| helper.gp_ci_.pColorBlendState = &cb_ci; |
| helper.gp_ci_.renderPass = render_pass_handle; |
| helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| }; |
| |
| cb_ci.flags = 0; |
| ds_ci.flags = VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_EXT; |
| vkt::RenderPass render_pass; |
| create_render_pass(VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM, render_pass); |
| render_pass_handle = render_pass; |
| CreatePipelineHelper::OneshotTest(*this, set_stages_pipeline_createinfo, kErrorBit, |
| "VUID-VkGraphicsPipelineCreateInfo-flags-06591"); |
| } |
| } |
| |
| TEST_F(NegativePipeline, MismatchedRenderPassAndPipelineAttachments) { |
| TEST_DESCRIPTION("Test creating a pipeline with no attachments with a render pass with attachments."); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-07609"); |
| |
| const char *vsSource = R"glsl( |
| #version 450 |
| |
| void main() { |
| } |
| )glsl"; |
| |
| const char *fsSource = R"glsl( |
| #version 450 |
| |
| void main() { |
| } |
| )glsl"; |
| |
| VkShaderObj vs(*m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT); |
| VkShaderObj fs(*m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| const vkt::DescriptorSetLayout descriptor_set_layout( |
| *m_device, {1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}); |
| |
| const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set_layout}); |
| CreatePipelineHelper pipe(*this); |
| pipe.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| pipe.gp_ci_.layout = pipeline_layout; |
| pipe.cb_ci_ = vku::InitStructHelper(); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, IncompatibleScissorCountAndViewportCount) { |
| TEST_DESCRIPTION("Validate creating a pipeline with incompatible scissor and viewport count, without dynamic states."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredFeature(vkt::Feature::multiViewport); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkViewport viewports[2] = {{0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}}; |
| |
| auto set_viewport_state_createinfo = [&](CreatePipelineHelper &helper) { |
| helper.vp_state_ci_.viewportCount = 2; |
| helper.vp_state_ci_.pViewports = viewports; |
| }; |
| |
| CreatePipelineHelper::OneshotTest(*this, set_viewport_state_createinfo, kErrorBit, |
| "VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"); |
| } |
| |
| TEST_F(NegativePipeline, ShaderTileImage) { |
| TEST_DESCRIPTION("Validate creating graphics pipeline with shader tile image extension."); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_3); |
| AddRequiredExtensions(VK_EXT_SHADER_TILE_IMAGE_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| RETURN_IF_SKIP(InitFramework()); |
| |
| VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamic_rendering_features = vku::InitStructHelper(); |
| VkPhysicalDeviceShaderTileImageFeaturesEXT shader_tile_image_features = vku::InitStructHelper(); |
| dynamic_rendering_features.pNext = &shader_tile_image_features; |
| auto features2 = GetPhysicalDeviceFeatures2(dynamic_rendering_features); |
| if (!dynamic_rendering_features.dynamicRendering) { |
| GTEST_SKIP() << "Test requires (unsupported) dynamicRendering"; |
| } |
| |
| // None of the shader tile image read features supported skip the test. |
| if (!shader_tile_image_features.shaderTileImageColorReadAccess && !shader_tile_image_features.shaderTileImageDepthReadAccess && |
| !shader_tile_image_features.shaderTileImageStencilReadAccess) { |
| GTEST_SKIP() << "Test requires (unsupported) shader tile image extension."; |
| } |
| |
| RETURN_IF_SKIP(InitState(nullptr, &features2)); |
| |
| VkFormat depth_format = VK_FORMAT_D32_SFLOAT_S8_UINT; |
| VkFormat color_format = VK_FORMAT_B8G8R8A8_UNORM; |
| VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper(); |
| pipeline_rendering_info.colorAttachmentCount = 1; |
| pipeline_rendering_info.pColorAttachmentFormats = &color_format; |
| pipeline_rendering_info.depthAttachmentFormat = depth_format; |
| pipeline_rendering_info.stencilAttachmentFormat = depth_format; |
| |
| VkPipelineDepthStencilStateCreateInfo ds_ci = vku::InitStructHelper(); |
| |
| if (shader_tile_image_features.shaderTileImageDepthReadAccess) { |
| auto fs = VkShaderObj::CreateFromASM(this, kShaderTileImageDepthReadSpv, VK_SHADER_STAGE_FRAGMENT_BIT); |
| auto pipeline_createinfo = [&](CreatePipelineHelper &helper) { |
| ds_ci.depthWriteEnable = true; |
| |
| helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| helper.gp_ci_.pDepthStencilState = &ds_ci; |
| helper.gp_ci_.renderPass = VK_NULL_HANDLE; |
| helper.gp_ci_.pNext = &pipeline_rendering_info; |
| }; |
| |
| CreatePipelineHelper::OneshotTest(*this, pipeline_createinfo, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-pStages-08711"); |
| } |
| |
| if (shader_tile_image_features.shaderTileImageStencilReadAccess) { |
| auto fs = VkShaderObj::CreateFromASM(this, kShaderTileImageStencilReadSpv, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| VkStencilOpState stencil_state = {}; |
| stencil_state.failOp = VK_STENCIL_OP_KEEP; |
| stencil_state.depthFailOp = VK_STENCIL_OP_KEEP; |
| stencil_state.passOp = VK_STENCIL_OP_REPLACE; |
| stencil_state.compareOp = VK_COMPARE_OP_LESS; |
| stencil_state.compareMask = 0xff; |
| stencil_state.writeMask = 0xff; |
| stencil_state.reference = 0xf; |
| |
| ds_ci = {}; |
| ds_ci.front = stencil_state; |
| ds_ci.back = stencil_state; |
| |
| auto pipeline_createinfo = [&](CreatePipelineHelper &helper) { |
| helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| helper.gp_ci_.pDepthStencilState = &ds_ci; |
| helper.gp_ci_.renderPass = VK_NULL_HANDLE; |
| helper.gp_ci_.pNext = &pipeline_rendering_info; |
| }; |
| |
| CreatePipelineHelper::OneshotTest(*this, pipeline_createinfo, kErrorBit, "VUID-VkGraphicsPipelineCreateInfo-pStages-08712"); |
| } |
| |
| if (shader_tile_image_features.shaderTileImageColorReadAccess) { |
| auto fs = VkShaderObj::CreateFromASM(this, kShaderTileImageColorReadSpv, VK_SHADER_STAGE_FRAGMENT_BIT); |
| |
| RenderPassSingleSubpass rp(*this); |
| rp.AddAttachmentDescription(VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_LAYOUT_UNDEFINED); |
| rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_GENERAL}); |
| rp.AddColorAttachment(0); |
| rp.CreateRenderPass(); |
| |
| // Check if the colorAttachmentRead capability enable, renderpass should be null |
| auto pipeline_createinfo = [&](CreatePipelineHelper &helper) { |
| helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| helper.gp_ci_.renderPass = rp; |
| }; |
| |
| CreatePipelineHelper::OneshotTest(*this, pipeline_createinfo, kErrorBit, |
| "VUID-VkGraphicsPipelineCreateInfo-renderPass-08710"); |
| |
| // sampleShading enable and minSampleShading not equal to 1.0 |
| VkPipelineMultisampleStateCreateInfo ms_ci = vku::InitStructHelper(); |
| ms_ci.sampleShadingEnable = VK_TRUE; |
| ms_ci.minSampleShading = 0; |
| ms_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; |
| |
| pipeline_rendering_info.depthAttachmentFormat = VK_FORMAT_UNDEFINED; |
| pipeline_rendering_info.stencilAttachmentFormat = VK_FORMAT_UNDEFINED; |
| |
| auto pipeline_createinfo_with_ms = [&](CreatePipelineHelper &helper) { |
| helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()}; |
| helper.gp_ci_.pMultisampleState = &ms_ci; |
| helper.gp_ci_.renderPass = VK_NULL_HANDLE; |
| helper.gp_ci_.pNext = &pipeline_rendering_info; |
| }; |
| |
| CreatePipelineHelper::OneshotTest(*this, pipeline_createinfo_with_ms, kErrorBit, |
| "VUID-RuntimeSpirv-minSampleShading-08732"); |
| } |
| } |
| |
| TEST_F(NegativePipeline, PipelineSubpassOutOfBounds) { |
| TEST_DESCRIPTION("Create pipeline with subpass index larger than number of subpasses in render pass"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.subpass = 4u; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-06046"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, PipelineRenderingInfoInvalidFormats) { |
| TEST_DESCRIPTION("Create pipeline with invalid pipeline rendering formats"); |
| |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| RETURN_IF_SKIP(Init()); |
| |
| VkPipelineRenderingCreateInfo pipeline_rendering_ci = vku::InitStructHelper(); |
| pipeline_rendering_ci.depthAttachmentFormat = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK; |
| |
| CreatePipelineHelper pipe(*this, &pipeline_rendering_ci); |
| pipe.gp_ci_.renderPass = VK_NULL_HANDLE; |
| pipe.cb_ci_.attachmentCount = 0u; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-06583"); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-06587"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| |
| pipeline_rendering_ci.depthAttachmentFormat = VK_FORMAT_UNDEFINED; |
| pipeline_rendering_ci.stencilAttachmentFormat = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-06584"); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-06588"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, RasterStateWithDepthBiasRepresentationInfo) { |
| TEST_DESCRIPTION( |
| "VkDepthBiasRepresentationInfoEXT in VkPipelineRasterizationStateCreateInfo pNext chain, but with " |
| "VkPhysicalDeviceDepthBiasControlFeaturesEXT features disabled"); |
| |
| AddRequiredExtensions(VK_EXT_DEPTH_BIAS_CONTROL_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::depthBiasControl); |
| |
| // Make sure validation of VkDepthBiasRepresentationInfoEXT in VkPipelineRasterizationStateCreateInfo does not rely on |
| // depthBiasClamp being enabled |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const auto create_pipe_with_depth_bias_representation = [this](VkDepthBiasRepresentationInfoEXT &depth_bias_representation) { |
| CreatePipelineHelper pipe(*this); |
| pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BIAS); |
| VkPipelineRasterizationStateCreateInfo raster_state = vku::InitStructHelper(&depth_bias_representation); |
| raster_state.lineWidth = 1.0f; |
| pipe.rs_state_ci_ = raster_state; |
| pipe.CreateGraphicsPipeline(); |
| }; |
| |
| 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; |
| m_errorMonitor->SetDesiredError("VUID-VkDepthBiasRepresentationInfoEXT-leastRepresentableValueForceUnormRepresentation-08947"); |
| m_errorMonitor->SetDesiredError("VUID-VkDepthBiasRepresentationInfoEXT-depthBiasExact-08949"); |
| create_pipe_with_depth_bias_representation(depth_bias_representation); |
| m_errorMonitor->VerifyFound(); |
| |
| depth_bias_representation.depthBiasExact = VK_FALSE; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkDepthBiasRepresentationInfoEXT-floatRepresentation-08948"); |
| depth_bias_representation.depthBiasRepresentation = VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT; |
| create_pipe_with_depth_bias_representation(depth_bias_representation); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, InvalidPipelineDepthBias) { |
| TEST_DESCRIPTION("Create pipeline with invalid depth bias"); |
| |
| RETURN_IF_SKIP(InitFramework()); |
| VkPhysicalDeviceFeatures features = {}; |
| RETURN_IF_SKIP(InitState(&features)); |
| InitRenderTarget(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.rs_state_ci_.depthBiasEnable = VK_TRUE; |
| pipe.rs_state_ci_.depthBiasClamp = 0.5f; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00754"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, MismatchedRasterizationSamples) { |
| TEST_DESCRIPTION("Draw when render pass rasterization samples do not match pipeline rasterization samples"); |
| |
| AddRequiredExtensions(VK_EXT_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| 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 = {128u, 128u, 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 format_props; |
| VkResult res = GetImageFormatProps(Gpu(), image_ci, format_props); |
| if (res != VK_SUCCESS || (format_props.sampleCounts & VK_SAMPLE_COUNT_2_BIT) == 0) { |
| GTEST_SKIP() << "Required format not supported"; |
| } |
| |
| vkt::Image image(*m_device, image_ci, vkt::set_layout); |
| |
| vkt::ImageView image_view = image.CreateView(); |
| |
| VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper(); |
| color_attachment.imageView = image_view; |
| color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| color_attachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; |
| color_attachment.resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| |
| VkMultisampledRenderToSingleSampledInfoEXT rtss = vku::InitStructHelper(); |
| rtss.multisampledRenderToSingleSampledEnable = VK_TRUE; |
| rtss.rasterizationSamples = VK_SAMPLE_COUNT_2_BIT; |
| |
| VkRenderingInfo rendering_info = vku::InitStructHelper(&rtss); |
| rendering_info.renderArea = {{0, 0}, {1, 1}}; |
| rendering_info.layerCount = 1u; |
| rendering_info.colorAttachmentCount = 1u; |
| rendering_info.pColorAttachments = &color_attachment; |
| |
| VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper(); |
| pipeline_rendering_info.colorAttachmentCount = 1; |
| pipeline_rendering_info.pColorAttachmentFormats = &image_ci.format; |
| |
| CreatePipelineHelper pipe(*this, &pipeline_rendering_info); |
| pipe.gp_ci_.renderPass = VK_NULL_HANDLE; |
| pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRendering(rendering_info); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-pNext-07935"); |
| vk::CmdDraw(m_command_buffer, 4u, 1u, 0u, 0u); |
| m_errorMonitor->VerifyFound(); |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativePipeline, PipelineMissingFeatures) { |
| TEST_DESCRIPTION("Enabled depth bounds when the features is disabled"); |
| |
| RETURN_IF_SKIP(InitFramework()); |
| VkPhysicalDeviceFeatures features = {}; |
| RETURN_IF_SKIP(InitState(&features)); |
| |
| const VkFormat ds_format = FindSupportedDepthStencilFormat(m_device->Physical()); |
| RenderPassSingleSubpass rp(*this); |
| rp.AddAttachmentDescription(ds_format, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); |
| rp.AddAttachmentReference({0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}); |
| rp.AddDepthStencilAttachment(0); |
| rp.CreateRenderPass(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.ds_ci_ = vku::InitStructHelper(); |
| pipe.ds_ci_.depthBoundsTestEnable = VK_TRUE; |
| pipe.gp_ci_.renderPass = rp; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineDepthStencilStateCreateInfo-depthBoundsTestEnable-00598"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| |
| pipe.ds_ci_.depthBoundsTestEnable = VK_FALSE; |
| pipe.ms_ci_.alphaToOneEnable = VK_TRUE; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineMultisampleStateCreateInfo-alphaToOneEnable-00785"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| |
| pipe.ms_ci_.alphaToOneEnable = VK_FALSE; |
| pipe.rs_state_ci_.depthClampEnable = VK_TRUE; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineRasterizationStateCreateInfo-depthClampEnable-00782"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, MissingPipelineFormat) { |
| TEST_DESCRIPTION("Render with required pipeline formats VK_FORMAT_UNDEFINED"); |
| |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredExtensions(VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| AddRequiredFeature(vkt::Feature::dynamicRenderingUnusedAttachments); |
| RETURN_IF_SKIP(Init()); |
| |
| VkFormat undefined = VK_FORMAT_UNDEFINED; |
| VkFormat color_format = VK_FORMAT_R8G8B8A8_UNORM; |
| VkFormat ds_format = FindSupportedDepthStencilFormat(Gpu()); |
| |
| vkt::Image color_image(*m_device, 32, 32, color_format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); |
| vkt::ImageView color_image_view = color_image.CreateView(); |
| |
| vkt::Image ds_image(*m_device, 32, 32, ds_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); |
| vkt::ImageView ds_image_view = ds_image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); |
| |
| VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper(); |
| pipeline_rendering_info.colorAttachmentCount = 1u; |
| pipeline_rendering_info.pColorAttachmentFormats = &undefined; |
| pipeline_rendering_info.depthAttachmentFormat = ds_format; |
| pipeline_rendering_info.stencilAttachmentFormat = ds_format; |
| |
| VkClearValue color_clear_value; |
| color_clear_value.color.float32[0] = 0.0f; |
| color_clear_value.color.float32[1] = 0.0f; |
| color_clear_value.color.float32[2] = 0.0f; |
| color_clear_value.color.float32[3] = 0.0f; |
| |
| VkClearValue ds_clear_value; |
| ds_clear_value.depthStencil = {1.0f, 0u}; |
| |
| VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper(); |
| color_attachment.imageView = color_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_clear_value; |
| |
| VkRenderingAttachmentInfo ds_attachment = vku::InitStructHelper(); |
| ds_attachment.imageView = ds_image_view; |
| ds_attachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| ds_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; |
| ds_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; |
| ds_attachment.clearValue = ds_clear_value; |
| |
| VkRenderingInfo rendering_info = vku::InitStructHelper(); |
| rendering_info.renderArea = {{0, 0}, {32u, 32u}}; |
| rendering_info.layerCount = 1u; |
| rendering_info.colorAttachmentCount = 1u; |
| rendering_info.pColorAttachments = &color_attachment; |
| rendering_info.pDepthAttachment = &ds_attachment; |
| rendering_info.pStencilAttachment = &ds_attachment; |
| |
| VkPipelineColorBlendAttachmentState color_blend_attachment_state = DefaultColorBlendAttachmentState(); |
| color_blend_attachment_state.colorWriteMask = |
| VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; |
| |
| VkPipelineDepthStencilStateCreateInfo ds_state = vku::InitStructHelper(); |
| ds_state.depthTestEnable = VK_TRUE; |
| ds_state.depthWriteEnable = VK_TRUE; |
| ds_state.stencilTestEnable = VK_TRUE; |
| |
| VkPipelineColorBlendStateCreateInfo color_blend_state = vku::InitStructHelper(); |
| color_blend_state.attachmentCount = 1u; |
| color_blend_state.pAttachments = &color_blend_attachment_state; |
| |
| CreatePipelineHelper color_pipe(*this, &pipeline_rendering_info); |
| color_pipe.ds_ci_ = ds_state; |
| color_pipe.cb_ci_ = color_blend_state; |
| color_pipe.CreateGraphicsPipeline(); |
| |
| pipeline_rendering_info.pColorAttachmentFormats = &color_format; |
| pipeline_rendering_info.depthAttachmentFormat = undefined; |
| |
| CreatePipelineHelper depth_pipe(*this, &pipeline_rendering_info); |
| depth_pipe.ds_ci_ = ds_state; |
| depth_pipe.CreateGraphicsPipeline(); |
| |
| pipeline_rendering_info.depthAttachmentFormat = ds_format; |
| pipeline_rendering_info.stencilAttachmentFormat = undefined; |
| |
| CreatePipelineHelper stencil_pipe(*this, &pipeline_rendering_info); |
| stencil_pipe.ds_ci_ = ds_state; |
| stencil_pipe.CreateGraphicsPipeline(); |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRendering(rendering_info); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, color_pipe); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-pColorAttachments-08963"); |
| vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, depth_pipe); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-pDepthAttachment-08964"); |
| vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u); |
| m_errorMonitor->VerifyFound(); |
| |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, stencil_pipe); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-pStencilAttachment-08965"); |
| vk::CmdDraw(m_command_buffer, 3u, 1u, 0u, 0u); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativePipeline, MissingPipelineViewportState) { |
| TEST_DESCRIPTION("Create pipeline with dynamic state discard enable, but no viewport state"); |
| |
| 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(); |
| |
| { |
| CreatePipelineHelper pipe(*this); |
| pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT); |
| pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE); |
| pipe.gp_ci_.pViewportState = nullptr; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-09024"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| { |
| CreatePipelineHelper pipe(*this); |
| pipe.AddDynamicState(VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT); |
| pipe.AddDynamicState(VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE); |
| pipe.gp_ci_.pViewportState = nullptr; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-09024"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| { |
| CreatePipelineHelper pipe(*this); |
| pipe.AddDynamicState(VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT); |
| pipe.gp_ci_.pViewportState = nullptr; |
| |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-09024"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| } |
| |
| TEST_F(NegativePipeline, PipelineRenderingInfoInvalidFormatWithoutFragmentState) { |
| TEST_DESCRIPTION("Create pipeline with invalid pipeline rendering formats"); |
| |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| RETURN_IF_SKIP(Init()); |
| |
| VkPipelineRenderingCreateInfo pipeline_rendering_ci = vku::InitStructHelper(); |
| pipeline_rendering_ci.stencilAttachmentFormat = VK_FORMAT_D16_UNORM; |
| |
| VkPipelineDepthStencilStateCreateInfo ds = vku::InitStructHelper(); |
| |
| CreatePipelineHelper pipe(*this, &pipeline_rendering_ci); |
| pipe.gp_ci_.renderPass = VK_NULL_HANDLE; |
| pipe.gp_ci_.pColorBlendState = nullptr; |
| pipe.cb_ci_.attachmentCount = 0u; |
| pipe.ds_ci_ = ds; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-renderPass-06588"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, IndirectBindablePipelineWithoutFeature) { |
| TEST_DESCRIPTION( |
| "Create pipeline with VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV without enabling required deviceGeneratedCommands " |
| "feature"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); |
| AddRequiredExtensions(VK_NV_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.flags = VK_PIPELINE_CREATE_INDIRECT_BINDABLE_BIT_NV; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-flags-02877"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, GeometryShaderConservativeRasterization) { |
| TEST_DESCRIPTION("Use geometry shader with invalid conservative rasterization mode"); |
| |
| AddRequiredExtensions(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::geometryShader); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| const char *gsSource = R"glsl( |
| #version 450 |
| layout (triangles) in; |
| layout (points) out; |
| layout (max_vertices = 1) out; |
| void main() { |
| gl_Position = vec4(1.0f); |
| EmitVertex(); |
| } |
| )glsl"; |
| |
| VkShaderObj gs(*m_device, gsSource, VK_SHADER_STAGE_GEOMETRY_BIT); |
| |
| VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservative_rasterization_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(conservative_rasterization_props); |
| if (conservative_rasterization_props.conservativePointAndLineRasterization) { |
| GTEST_SKIP() << "Test requires conservativePointAndLineRasterization to be VK_FALSE"; |
| } |
| |
| VkPipelineRasterizationConservativeStateCreateInfoEXT conservative_state = vku::InitStructHelper(); |
| conservative_state.conservativeRasterizationMode = VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.rs_state_ci_.pNext = &conservative_state; |
| pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), gs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()}; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-conservativePointAndLineRasterization-08892"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, VertexPointOutputConservativeRasterization) { |
| TEST_DESCRIPTION("Use vertex shader with invalid conservative rasterization mode"); |
| |
| AddRequiredExtensions(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::geometryShader); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservative_rasterization_props = vku::InitStructHelper(); |
| GetPhysicalDeviceProperties2(conservative_rasterization_props); |
| if (conservative_rasterization_props.conservativePointAndLineRasterization) { |
| GTEST_SKIP() << "Test requires conservativePointAndLineRasterization to be VK_FALSE"; |
| } |
| |
| VkPipelineRasterizationConservativeStateCreateInfoEXT conservative_state = vku::InitStructHelper(); |
| conservative_state.conservativeRasterizationMode = VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.rs_state_ci_.pNext = &conservative_state; |
| pipe.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-conservativePointAndLineRasterization-08892"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, PipelineCreationFlags2CacheControl) { |
| TEST_DESCRIPTION("Test VK_EXT_pipeline_creation_cache_control with VkPipelineCreateFlags2"); |
| |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_EXT_PIPELINE_CREATION_CACHE_CONTROL_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineCreateFlags2CreateInfo flags2 = vku::InitStructHelper(); |
| |
| const auto set_graphics_flags = [&](CreatePipelineHelper &helper) { |
| helper.gp_ci_.pNext = &flags2; |
| flags2.flags = VK_PIPELINE_CREATE_2_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, set_graphics_flags, kErrorBit, |
| "VUID-VkGraphicsPipelineCreateInfo-pipelineCreationCacheControl-02878"); |
| |
| const auto set_compute_flags = [&](CreateComputePipelineHelper &helper) { |
| helper.cp_ci_.pNext = &flags2; |
| flags2.flags = VK_PIPELINE_CREATE_2_EARLY_RETURN_ON_FAILURE_BIT; |
| }; |
| CreateComputePipelineHelper::OneshotTest(*this, set_compute_flags, kErrorBit, |
| "VUID-VkComputePipelineCreateInfo-pipelineCreationCacheControl-02875"); |
| } |
| |
| TEST_F(NegativePipeline, PipelineCreationFlags2Library) { |
| TEST_DESCRIPTION("Test VK_PIPELINE_CREATE_LIBRARY_BIT_KHR with VkPipelineCreateFlags2"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::maintenance5); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineCreateFlags2CreateInfo flags2 = vku::InitStructHelper(); |
| flags2.flags = VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR; |
| |
| CreatePipelineHelper pipe(*this, &flags2); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-graphicsPipelineLibrary-06606"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, PipelineCreationFlags2LibraryLinkTime) { |
| TEST_DESCRIPTION("Test VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT with VkPipelineCreateFlags2"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineCreateFlags2CreateInfo flags2 = vku::InitStructHelper(); |
| flags2.flags = VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR; |
| |
| CreatePipelineHelper vertex_input_lib(*this); |
| vertex_input_lib.InitVertexInputLibInfo(&flags2); |
| vertex_input_lib.CreateGraphicsPipeline(false); |
| |
| VkPipeline libraries[1] = { |
| vertex_input_lib, |
| }; |
| |
| flags2.flags = VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR | VK_PIPELINE_CREATE_2_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT; |
| VkPipelineLibraryCreateInfoKHR link_info = vku::InitStructHelper(&flags2); |
| link_info.libraryCount = size32(libraries); |
| link_info.pLibraries = libraries; |
| |
| const auto vs_spv = GLSLToSPV(VK_SHADER_STAGE_VERTEX_BIT, kVertexMinimalGlsl); |
| vkt::GraphicsPipelineLibraryStage vs_stage(vs_spv, VK_SHADER_STAGE_VERTEX_BIT); |
| |
| CreatePipelineHelper pre_raster_lib(*this); |
| pre_raster_lib.InitPreRasterLibInfo(&vs_stage.stage_ci); |
| pre_raster_lib.gpl_info->pNext = &link_info; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-flags-06610"); |
| pre_raster_lib.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, ViewportStateScissorOverflow) { |
| TEST_DESCRIPTION("Validate sum of offset and width of viewport state scissor"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; |
| VkRect2D scissor_x = {{vvl::kI32Max / 2, 0}, {vvl::kI32Max / 2 + 64, 64}}; |
| VkRect2D scissor_y = {{0, vvl::kI32Max / 2}, {64, vvl::kI32Max / 2 + 64}}; |
| |
| const auto break_vp_x = [&](CreatePipelineHelper &helper) { |
| helper.vp_state_ci_.viewportCount = 1; |
| helper.vp_state_ci_.pViewports = &viewport; |
| helper.vp_state_ci_.scissorCount = 1; |
| helper.vp_state_ci_.pScissors = &scissor_x; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, break_vp_x, kErrorBit, |
| std::vector<std::string>({"VUID-VkPipelineViewportStateCreateInfo-offset-02822"})); |
| |
| const auto break_vp_y = [&](CreatePipelineHelper &helper) { |
| helper.vp_state_ci_.viewportCount = 1; |
| helper.vp_state_ci_.pViewports = &viewport; |
| helper.vp_state_ci_.scissorCount = 1; |
| helper.vp_state_ci_.pScissors = &scissor_y; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, break_vp_y, kErrorBit, |
| std::vector<std::string>({"VUID-VkPipelineViewportStateCreateInfo-offset-02823"})); |
| } |
| |
| TEST_F(NegativePipeline, ViewportStateScissorNegative) { |
| TEST_DESCRIPTION("Validate offset of viewport state scissor"); |
| |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f}; |
| VkRect2D scissor_x = {{-64, 0}, {256, 256}}; |
| VkRect2D scissor_y = {{0, -64}, {256, 256}}; |
| |
| const auto break_vp_x = [&](CreatePipelineHelper &helper) { |
| helper.vp_state_ci_.viewportCount = 1; |
| helper.vp_state_ci_.pViewports = &viewport; |
| helper.vp_state_ci_.scissorCount = 1; |
| helper.vp_state_ci_.pScissors = &scissor_x; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, break_vp_x, kErrorBit, "VUID-VkPipelineViewportStateCreateInfo-x-02821"); |
| |
| const auto break_vp_y = [&](CreatePipelineHelper &helper) { |
| helper.vp_state_ci_.viewportCount = 1; |
| helper.vp_state_ci_.pViewports = &viewport; |
| helper.vp_state_ci_.scissorCount = 1; |
| helper.vp_state_ci_.pScissors = &scissor_y; |
| }; |
| CreatePipelineHelper::OneshotTest(*this, break_vp_y, kErrorBit, "VUID-VkPipelineViewportStateCreateInfo-x-02821"); |
| } |
| |
| TEST_F(NegativePipeline, PipelineCreateFlags2) { |
| TEST_DESCRIPTION("Test using VkPipelineCreateFlags2CreateInfo"); |
| SetTargetApiVersion(VK_API_VERSION_1_1); |
| AddRequiredExtensions(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineCreateFlags2CreateInfo flags2 = vku::InitStructHelper(); |
| flags2.flags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR; |
| |
| CreatePipelineHelper pipe(*this, &flags2); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-graphicsPipelineLibrary-06606"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, RasterizationStateFlag) { |
| TEST_DESCRIPTION("Enabled depth bounds when the features is disabled"); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.rs_state_ci_.flags = 1; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineRasterizationStateCreateInfo-flags-zerobitmask"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, GetPipelinePropertiesEXT) { |
| AddRequiredExtensions(VK_EXT_PIPELINE_PROPERTIES_EXTENSION_NAME); |
| RETURN_IF_SKIP(Init()); // missing feature |
| InitRenderTarget(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.CreateGraphicsPipeline(); |
| |
| VkPipelineInfoEXT pipeline_info = vku::InitStructHelper(); |
| pipeline_info.pipeline = pipe; |
| |
| m_errorMonitor->SetDesiredError("VUID-vkGetPipelinePropertiesEXT-None-06766"); |
| m_errorMonitor->SetDesiredError("VUID-vkGetPipelinePropertiesEXT-pPipelineProperties-06739"); |
| vk::GetPipelinePropertiesEXT(device(), &pipeline_info, nullptr); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| // stype-check off |
| TEST_F(NegativePipeline, PipelinePropertiesIdentifierEXT) { |
| AddRequiredExtensions(VK_EXT_PIPELINE_PROPERTIES_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::pipelinePropertiesIdentifier); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.CreateGraphicsPipeline(); |
| |
| VkPipelineInfoEXT pipeline_info = vku::InitStructHelper(); |
| pipeline_info.pipeline = pipe; |
| VkPipelinePropertiesIdentifierEXT pipeline_props = vku::InitStructHelper(&pipeline_info); |
| |
| m_errorMonitor->SetDesiredError("VUID-VkPipelinePropertiesIdentifierEXT-pNext-pNext"); |
| vk::GetPipelinePropertiesEXT(device(), &pipeline_info, (VkBaseOutStructure *)&pipeline_props); |
| m_errorMonitor->VerifyFound(); |
| |
| pipeline_props.pNext = nullptr; |
| pipeline_props.sType = VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelinePropertiesIdentifierEXT-sType-sType"); |
| vk::GetPipelinePropertiesEXT(device(), &pipeline_info, (VkBaseOutStructure *)&pipeline_props); |
| m_errorMonitor->VerifyFound(); |
| } |
| // stype-check on |
| |
| TEST_F(NegativePipeline, NoRasterizationState) { |
| TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8051"); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.gp_ci_.pRasterizationState = nullptr; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pRasterizationState-06601"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, NoRasterizationStateDynamicRendering) { |
| TEST_DESCRIPTION("https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/8051"); |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| RETURN_IF_SKIP(Init()); |
| |
| VkFormat color_formats = VK_FORMAT_UNDEFINED; |
| VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper(); |
| pipeline_rendering_info.colorAttachmentCount = 1; |
| pipeline_rendering_info.pColorAttachmentFormats = &color_formats; |
| |
| CreatePipelineHelper pipe(*this, &pipeline_rendering_info); |
| pipe.gp_ci_.pRasterizationState = nullptr; |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pRasterizationState-06601"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, DepthClampControlMinMax) { |
| AddRequiredExtensions(VK_EXT_DEPTH_CLAMP_CONTROL_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::depthClampControl); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkDepthClampRangeEXT clamp_range = {0.5f, 0.4f}; |
| VkPipelineViewportDepthClampControlCreateInfoEXT clamp_control = vku::InitStructHelper(); |
| clamp_control.depthClampMode = VK_DEPTH_CLAMP_MODE_USER_DEFINED_RANGE_EXT; |
| clamp_control.pDepthClampRange = &clamp_range; |
| CreatePipelineHelper pipe(*this); |
| pipe.vp_state_ci_.pNext = &clamp_control; |
| m_errorMonitor->SetDesiredError("VUID-VkDepthClampRangeEXT-pDepthClampRange-00999"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, DepthClampControlUnrestricted) { |
| AddRequiredExtensions(VK_EXT_DEPTH_CLAMP_CONTROL_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::depthClampControl); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkDepthClampRangeEXT clamp_range = {-0.5f, 1.5f}; |
| VkPipelineViewportDepthClampControlCreateInfoEXT clamp_control = vku::InitStructHelper(); |
| clamp_control.depthClampMode = VK_DEPTH_CLAMP_MODE_USER_DEFINED_RANGE_EXT; |
| clamp_control.pDepthClampRange = &clamp_range; |
| CreatePipelineHelper pipe(*this); |
| pipe.vp_state_ci_.pNext = &clamp_control; |
| m_errorMonitor->SetDesiredError("VUID-VkDepthClampRangeEXT-pDepthClampRange-09648"); |
| m_errorMonitor->SetDesiredError("VUID-VkDepthClampRangeEXT-pDepthClampRange-09649"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, DepthClampControlUserDefined) { |
| AddRequiredExtensions(VK_EXT_DEPTH_CLAMP_CONTROL_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::depthClampControl); |
| RETURN_IF_SKIP(Init()); |
| InitRenderTarget(); |
| |
| VkPipelineViewportDepthClampControlCreateInfoEXT clamp_control = vku::InitStructHelper(); |
| clamp_control.depthClampMode = VK_DEPTH_CLAMP_MODE_USER_DEFINED_RANGE_EXT; |
| clamp_control.pDepthClampRange = nullptr; |
| CreatePipelineHelper pipe(*this); |
| pipe.vp_state_ci_.pNext = &clamp_control; |
| m_errorMonitor->SetDesiredError("VUID-VkPipelineViewportDepthClampControlCreateInfoEXT-pDepthClampRange-09646"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |
| |
| TEST_F(NegativePipeline, 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> test_cases = { |
| {2, |
| viewports, |
| 1, |
| scissors, |
| {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", |
| "VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134"}}, |
| {2, |
| viewports, |
| 1, |
| scissors, |
| {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", |
| "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"}}, |
| {1, nullptr, 1, scissors, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04130"}}, |
| {1, viewports, 1, nullptr, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04131"}}, |
| {1, |
| nullptr, |
| 1, |
| nullptr, |
| {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04130", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04131"}}, |
| {2, |
| nullptr, |
| 3, |
| nullptr, |
| {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", |
| "VUID-VkPipelineViewportStateCreateInfo-scissorCount-04134", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04130", |
| "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-04131"}}, |
| {2, |
| nullptr, |
| 2, |
| nullptr, |
| {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217", |
| "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); |
| } |
| } |
| |
| TEST_F(NegativePipeline, SampleLocationsDynamicRendering) { |
| SetTargetApiVersion(VK_API_VERSION_1_2); |
| AddRequiredExtensions(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME); |
| AddRequiredExtensions(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::dynamicRendering); |
| 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 VkFormat depth_format = FindSupportedDepthStencilFormat(Gpu()); |
| auto image_ci = vkt::Image::ImageCreateInfo2D(128, 128, 1, 1, depth_format, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); |
| vkt::Image depth_image(*m_device, image_ci, vkt::set_layout); |
| |
| VkFormat color_format = VK_FORMAT_R8G8B8A8_UNORM; |
| vkt::Image color_image(*m_device, 128, 128, color_format, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); |
| |
| vkt::ImageView color_view = color_image.CreateView(); |
| vkt::ImageView depth_view = depth_image.CreateView(VK_IMAGE_ASPECT_DEPTH_BIT); |
| |
| 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; |
| |
| VkPipelineRenderingCreateInfo pipeline_rendering_info = vku::InitStructHelper(); |
| pipeline_rendering_info.colorAttachmentCount = 1; |
| pipeline_rendering_info.pColorAttachmentFormats = &color_format; |
| pipeline_rendering_info.depthAttachmentFormat = depth_format; |
| |
| CreatePipelineHelper pipe(*this, &pipeline_rendering_info); |
| pipe.ms_ci_ = pipe_ms_state_ci; |
| pipe.gp_ci_.pDepthStencilState = &pipe_ds_state_ci; |
| pipe.CreateGraphicsPipeline(); |
| |
| VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper(); |
| color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; |
| color_attachment.imageView = color_view; |
| VkRenderingAttachmentInfo depth_attachment = vku::InitStructHelper(); |
| depth_attachment.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; |
| depth_attachment.imageView = depth_view; |
| |
| VkRenderingInfo begin_rendering_info = vku::InitStructHelper(); |
| begin_rendering_info.colorAttachmentCount = 1; |
| begin_rendering_info.pColorAttachments = &color_attachment; |
| begin_rendering_info.pDepthAttachment = &depth_attachment; |
| begin_rendering_info.layerCount = 1; |
| begin_rendering_info.renderArea = {{0, 0}, {1, 1}}; |
| |
| m_command_buffer.Begin(); |
| m_command_buffer.BeginRendering(begin_rendering_info); |
| vkt::Buffer vbo(*m_device, sizeof(float) * 3, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); |
| vk::CmdBindVertexBuffers(m_command_buffer, 1, 1, &vbo.handle(), &kZeroDeviceSize); |
| vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); |
| m_errorMonitor->SetDesiredError("VUID-vkCmdDraw-sampleLocationsEnable-02689"); |
| vk::CmdDraw(m_command_buffer, 1, 0, 0, 0); |
| m_errorMonitor->VerifyFound(); |
| |
| m_command_buffer.EndRendering(); |
| m_command_buffer.End(); |
| } |
| |
| TEST_F(NegativePipeline, DepthBounds) { |
| AddRequiredExtensions(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); |
| AddRequiredFeature(vkt::Feature::depthBounds); |
| AddRequiredFeature(vkt::Feature::extendedDynamicState); |
| RETURN_IF_SKIP(Init()); |
| |
| 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.minDepthBounds = 0.6f; |
| ds_ci.maxDepthBounds = 0.4f; |
| |
| CreatePipelineHelper pipe(*this); |
| pipe.ds_ci_ = ds_ci; |
| pipe.AddDynamicState(VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE); |
| m_errorMonitor->SetDesiredError("VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-10913"); |
| pipe.CreateGraphicsPipeline(); |
| m_errorMonitor->VerifyFound(); |
| } |