1 /*
2  * Copyright (c) 2015-2019 The Khronos Group Inc.
3  * Copyright (c) 2015-2019 Valve Corporation
4  * Copyright (c) 2015-2019 LunarG, Inc.
5  * Copyright (c) 2015-2019 Google, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Author: Chia-I Wu <olvaffe@gmail.com>
14  * Author: Chris Forbes <chrisf@ijw.co.nz>
15  * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
16  * Author: Mark Lobodzinski <mark@lunarg.com>
17  * Author: Mike Stroyan <mike@LunarG.com>
18  * Author: Tobin Ehlis <tobine@google.com>
19  * Author: Tony Barbour <tony@LunarG.com>
20  * Author: Cody Northrop <cnorthrop@google.com>
21  * Author: Dave Houlton <daveh@lunarg.com>
22  * Author: Jeremy Kniager <jeremyk@lunarg.com>
23  * Author: Shannon McPherson <shannon@lunarg.com>
24  * Author: John Zulauf <jzulauf@lunarg.com>
25  */
26 
27 #include "cast_utils.h"
28 #include "layer_validation_tests.h"
29 
TEST_F(VkLayerTest,PSOPolygonModeInvalid)30 TEST_F(VkLayerTest, PSOPolygonModeInvalid) {
31     TEST_DESCRIPTION("Attempt to use invalid polygon fill modes.");
32     VkPhysicalDeviceFeatures device_features = {};
33     device_features.fillModeNonSolid = VK_FALSE;
34     // The sacrificial device object
35     ASSERT_NO_FATAL_FAILURE(Init(&device_features));
36     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
37 
38     VkPipelineRasterizationStateCreateInfo rs_ci = {};
39     rs_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
40     rs_ci.pNext = nullptr;
41     rs_ci.lineWidth = 1.0f;
42     rs_ci.rasterizerDiscardEnable = VK_TRUE;
43 
44     auto set_polygonMode = [&](CreatePipelineHelper &helper) { helper.rs_state_ci_ = rs_ci; };
45 
46     // Set polygonMode to POINT while the non-solid fill mode feature is disabled.
47     // Introduce failure by setting unsupported polygon mode
48     rs_ci.polygonMode = VK_POLYGON_MODE_POINT;
49     CreatePipelineHelper::OneshotTest(*this, set_polygonMode, VK_DEBUG_REPORT_ERROR_BIT_EXT,
50                                       "polygonMode cannot be VK_POLYGON_MODE_POINT or VK_POLYGON_MODE_LINE");
51 
52     // Set polygonMode to LINE while the non-solid fill mode feature is disabled.
53     // Introduce failure by setting unsupported polygon mode
54     rs_ci.polygonMode = VK_POLYGON_MODE_LINE;
55     CreatePipelineHelper::OneshotTest(*this, set_polygonMode, VK_DEBUG_REPORT_ERROR_BIT_EXT,
56                                       "polygonMode cannot be VK_POLYGON_MODE_POINT or VK_POLYGON_MODE_LINE");
57 
58     // Set polygonMode to FILL_RECTANGLE_NV while the extension is not enabled.
59     // Introduce failure by setting unsupported polygon mode
60     rs_ci.polygonMode = VK_POLYGON_MODE_FILL_RECTANGLE_NV;
61     CreatePipelineHelper::OneshotTest(*this, set_polygonMode, VK_DEBUG_REPORT_ERROR_BIT_EXT,
62                                       "VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01414");
63 }
64 
TEST_F(VkLayerTest,PipelineNotBound)65 TEST_F(VkLayerTest, PipelineNotBound) {
66     TEST_DESCRIPTION("Pass in an invalid pipeline object handle into a Vulkan API call.");
67 
68     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindPipeline-pipeline-parameter");
69 
70     ASSERT_NO_FATAL_FAILURE(Init());
71     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
72 
73     VkPipeline badPipeline = CastToHandle<VkPipeline, uintptr_t>(0xbaadb1be);
74 
75     m_commandBuffer->begin();
76     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, badPipeline);
77 
78     m_errorMonitor->VerifyFound();
79 }
80 
TEST_F(VkLayerTest,PipelineWrongBindPointGraphics)81 TEST_F(VkLayerTest, PipelineWrongBindPointGraphics) {
82     TEST_DESCRIPTION("Bind a compute pipeline in the graphics bind point");
83 
84     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindPipeline-pipelineBindPoint-00779");
85 
86     ASSERT_NO_FATAL_FAILURE(Init());
87     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
88 
89     CreateComputePipelineHelper pipe(*this);
90     pipe.InitInfo();
91     pipe.InitState();
92     pipe.CreateComputePipeline();
93 
94     m_commandBuffer->begin();
95     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
96 
97     m_errorMonitor->VerifyFound();
98 }
99 
TEST_F(VkLayerTest,PipelineWrongBindPointCompute)100 TEST_F(VkLayerTest, PipelineWrongBindPointCompute) {
101     TEST_DESCRIPTION("Bind a graphics pipeline in the compute bind point");
102 
103     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindPipeline-pipelineBindPoint-00780");
104 
105     ASSERT_NO_FATAL_FAILURE(Init());
106     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
107 
108     CreatePipelineHelper pipe(*this);
109     pipe.InitInfo();
110     pipe.InitState();
111     pipe.CreateGraphicsPipeline();
112 
113     m_commandBuffer->begin();
114     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipe.pipeline_);
115 
116     m_errorMonitor->VerifyFound();
117 }
118 
TEST_F(VkLayerTest,PipelineWrongBindPointRayTracing)119 TEST_F(VkLayerTest, PipelineWrongBindPointRayTracing) {
120     TEST_DESCRIPTION("Bind a graphics pipeline in the ray-tracing bind point");
121 
122     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
123         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
124     } else {
125         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
126         return;
127     }
128     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
129 
130     if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_RAY_TRACING_EXTENSION_NAME)) {
131         m_device_extension_names.push_back(VK_NV_RAY_TRACING_EXTENSION_NAME);
132         m_device_extension_names.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
133     } else {
134         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_NV_RAY_TRACING_EXTENSION_NAME);
135         return;
136     }
137     ASSERT_NO_FATAL_FAILURE(InitState());
138 
139     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindPipeline-pipelineBindPoint-02392");
140 
141     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
142 
143     if (!EnableDeviceProfileLayer()) {
144         printf("%s Failed to enable device profile layer.\n", kSkipPrefix);
145         return;
146     }
147 
148     CreatePipelineHelper pipe(*this);
149     pipe.InitInfo();
150     pipe.InitState();
151     pipe.CreateGraphicsPipeline();
152 
153     m_commandBuffer->begin();
154     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, pipe.pipeline_);
155 
156     m_errorMonitor->VerifyFound();
157 }
158 
TEST_F(VkLayerTest,CreatePipelineBadVertexAttributeFormat)159 TEST_F(VkLayerTest, CreatePipelineBadVertexAttributeFormat) {
160     TEST_DESCRIPTION("Test that pipeline validation catches invalid vertex attribute formats");
161 
162     ASSERT_NO_FATAL_FAILURE(Init());
163     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
164 
165     VkVertexInputBindingDescription input_binding;
166     memset(&input_binding, 0, sizeof(input_binding));
167 
168     VkVertexInputAttributeDescription input_attribs;
169     memset(&input_attribs, 0, sizeof(input_attribs));
170 
171     // Pick a really bad format for this purpose and make sure it should fail
172     input_attribs.format = VK_FORMAT_BC2_UNORM_BLOCK;
173     VkFormatProperties format_props = m_device->format_properties(input_attribs.format);
174     if ((format_props.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) != 0) {
175         printf("%s Format unsuitable for test; skipped.\n", kSkipPrefix);
176         return;
177     }
178 
179     input_attribs.location = 0;
180 
181     auto set_info = [&](CreatePipelineHelper &helper) {
182         helper.vi_ci_.pVertexBindingDescriptions = &input_binding;
183         helper.vi_ci_.vertexBindingDescriptionCount = 1;
184         helper.vi_ci_.pVertexAttributeDescriptions = &input_attribs;
185         helper.vi_ci_.vertexAttributeDescriptionCount = 1;
186     };
187     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
188                                       "VUID-VkVertexInputAttributeDescription-format-00623");
189 }
190 
TEST_F(VkLayerTest,DisabledIndependentBlend)191 TEST_F(VkLayerTest, DisabledIndependentBlend) {
192     TEST_DESCRIPTION(
193         "Generate INDEPENDENT_BLEND by disabling independent blend and then specifying different blend states for two "
194         "attachments");
195     VkPhysicalDeviceFeatures features = {};
196     features.independentBlend = VK_FALSE;
197     ASSERT_NO_FATAL_FAILURE(Init(&features));
198 
199     m_errorMonitor->SetDesiredFailureMsg(
200         VK_DEBUG_REPORT_ERROR_BIT_EXT,
201         "Invalid Pipeline CreateInfo: If independent blend feature not enabled, all elements of pAttachments must be identical");
202 
203     VkDescriptorSetObj descriptorSet(m_device);
204     descriptorSet.AppendDummy();
205     descriptorSet.CreateVKDescriptorSet(m_commandBuffer);
206 
207     VkPipelineObj pipeline(m_device);
208     // Create a renderPass with two color attachments
209     VkAttachmentReference attachments[2] = {};
210     attachments[0].layout = VK_IMAGE_LAYOUT_GENERAL;
211     attachments[1].attachment = 1;
212     attachments[1].layout = VK_IMAGE_LAYOUT_GENERAL;
213 
214     VkSubpassDescription subpass = {};
215     subpass.pColorAttachments = attachments;
216     subpass.colorAttachmentCount = 2;
217 
218     VkRenderPassCreateInfo rpci = {};
219     rpci.subpassCount = 1;
220     rpci.pSubpasses = &subpass;
221     rpci.attachmentCount = 2;
222 
223     VkAttachmentDescription attach_desc[2] = {};
224     attach_desc[0].format = VK_FORMAT_B8G8R8A8_UNORM;
225     attach_desc[0].samples = VK_SAMPLE_COUNT_1_BIT;
226     attach_desc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
227     attach_desc[0].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
228     attach_desc[1].format = VK_FORMAT_B8G8R8A8_UNORM;
229     attach_desc[1].samples = VK_SAMPLE_COUNT_1_BIT;
230     attach_desc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
231     attach_desc[1].finalLayout = VK_IMAGE_LAYOUT_GENERAL;
232 
233     rpci.pAttachments = attach_desc;
234     rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
235 
236     VkRenderPass renderpass;
237     vkCreateRenderPass(m_device->device(), &rpci, NULL, &renderpass);
238     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
239     pipeline.AddShader(&vs);
240 
241     VkPipelineColorBlendAttachmentState att_state1 = {}, att_state2 = {};
242     att_state1.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR;
243     att_state1.blendEnable = VK_TRUE;
244     att_state2.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR;
245     att_state2.blendEnable = VK_FALSE;
246     pipeline.AddColorAttachment(0, att_state1);
247     pipeline.AddColorAttachment(1, att_state2);
248     pipeline.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderpass);
249     m_errorMonitor->VerifyFound();
250     vkDestroyRenderPass(m_device->device(), renderpass, NULL);
251 }
252 
253 // Is the Pipeline compatible with the expectations of the Renderpass/subpasses?
TEST_F(VkLayerTest,PipelineRenderpassCompatibility)254 TEST_F(VkLayerTest, PipelineRenderpassCompatibility) {
255     TEST_DESCRIPTION(
256         "Create a graphics pipeline that is incompatible with the requirements of its contained Renderpass/subpasses.");
257     ASSERT_NO_FATAL_FAILURE(Init());
258     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
259 
260     VkPipelineColorBlendAttachmentState att_state1 = {};
261     att_state1.dstAlphaBlendFactor = VK_BLEND_FACTOR_CONSTANT_COLOR;
262     att_state1.blendEnable = VK_TRUE;
263 
264     auto set_info = [&](CreatePipelineHelper &helper) {
265         helper.cb_attachments_ = att_state1;
266         helper.gp_ci_.pColorBlendState = nullptr;
267     };
268     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
269                                       "VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00753");
270 }
271 
TEST_F(VkLayerTest,PointSizeFailure)272 TEST_F(VkLayerTest, PointSizeFailure) {
273     TEST_DESCRIPTION("Create a pipeline using TOPOLOGY_POINT_LIST but do not set PointSize in vertex shader.");
274 
275     ASSERT_NO_FATAL_FAILURE(Init());
276     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
277     ASSERT_NO_FATAL_FAILURE(InitViewport());
278 
279     // Create VS declaring PointSize but not writing to it
280     const char NoPointSizeVertShader[] =
281         "#version 450\n"
282         "vec2 vertices[3];\n"
283         "out gl_PerVertex\n"
284         "{\n"
285         "    vec4 gl_Position;\n"
286         "    float gl_PointSize;\n"
287         "};\n"
288         "void main() {\n"
289         "    vertices[0] = vec2(-1.0, -1.0);\n"
290         "    vertices[1] = vec2( 1.0, -1.0);\n"
291         "    vertices[2] = vec2( 0.0,  1.0);\n"
292         "    gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n"
293         "}\n";
294     VkShaderObj vs(m_device, NoPointSizeVertShader, VK_SHADER_STAGE_VERTEX_BIT, this);
295 
296     // Set Input Assembly to TOPOLOGY POINT LIST
297     auto set_info = [&](CreatePipelineHelper &helper) {
298         // Set Input Assembly to TOPOLOGY POINT LIST
299         helper.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
300 
301         helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
302     };
303     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "Pipeline topology is set to POINT_LIST");
304 }
305 
TEST_F(VkLayerTest,InvalidTopology)306 TEST_F(VkLayerTest, InvalidTopology) {
307     TEST_DESCRIPTION("InvalidTopology.");
308     VkPhysicalDeviceFeatures deviceFeatures = {};
309     deviceFeatures.geometryShader = VK_FALSE;
310     deviceFeatures.tessellationShader = VK_FALSE;
311 
312     ASSERT_NO_FATAL_FAILURE(Init(&deviceFeatures));
313     ASSERT_NO_FATAL_FAILURE(InitViewport());
314     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
315 
316     VkShaderObj vs(m_device, bindStateVertPointSizeShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
317 
318     VkPrimitiveTopology topology;
319 
320     auto set_info = [&](CreatePipelineHelper &helper) {
321         helper.ia_ci_.topology = topology;
322         helper.ia_ci_.primitiveRestartEnable = VK_TRUE;
323         helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
324     };
325 
326     topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
327     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
328                                       "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428");
329 
330     topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
331     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
332                                       "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428");
333 
334     topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
335     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
336                                       "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428");
337 
338     topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
339     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
340                                       std::vector<string>{"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428",
341                                                           "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429"});
342 
343     topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
344     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
345                                       std::vector<string>{"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428",
346                                                           "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429"});
347 
348     topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
349     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
350                                       std::vector<string>{"VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00428",
351                                                           "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00430",
352                                                           "VUID-VkGraphicsPipelineCreateInfo-topology-00737"});
353 
354     topology = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
355     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
356                                       "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429");
357 
358     topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
359     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
360                                       "VUID-VkPipelineInputAssemblyStateCreateInfo-topology-00429");
361 }
362 
TEST_F(VkLayerTest,PointSizeGeomShaderFailure)363 TEST_F(VkLayerTest, PointSizeGeomShaderFailure) {
364     TEST_DESCRIPTION(
365         "Create a pipeline using TOPOLOGY_POINT_LIST, set PointSize vertex shader, but not in the final geometry stage.");
366 
367     ASSERT_NO_FATAL_FAILURE(Init());
368 
369     if ((!m_device->phy().features().geometryShader) || (!m_device->phy().features().shaderTessellationAndGeometryPointSize)) {
370         printf("%s Device does not support the required geometry shader features; skipped.\n", kSkipPrefix);
371         return;
372     }
373     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
374     ASSERT_NO_FATAL_FAILURE(InitViewport());
375 
376     // Create VS declaring PointSize and writing to it
377     static char const *gsSource =
378         "#version 450\n"
379         "layout (points) in;\n"
380         "layout (points) out;\n"
381         "layout (max_vertices = 1) out;\n"
382         "void main() {\n"
383         "   gl_Position = vec4(1.0, 0.5, 0.5, 0.0);\n"
384         "   EmitVertex();\n"
385         "}\n";
386 
387     VkShaderObj vs(m_device, bindStateVertPointSizeShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
388     VkShaderObj gs(m_device, gsSource, VK_SHADER_STAGE_GEOMETRY_BIT, this);
389 
390     auto set_info = [&](CreatePipelineHelper &helper) {
391         helper.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
392         helper.shader_stages_ = {vs.GetStageCreateInfo(), gs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
393     };
394 
395     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "Pipeline topology is set to POINT_LIST");
396 }
397 
TEST_F(VkLayerTest,BuiltinBlockOrderMismatchVsGs)398 TEST_F(VkLayerTest, BuiltinBlockOrderMismatchVsGs) {
399     TEST_DESCRIPTION("Use different order of gl_Position and gl_PointSize in builtin block interface between VS and GS.");
400 
401     ASSERT_NO_FATAL_FAILURE(Init());
402 
403     if (!m_device->phy().features().geometryShader) {
404         printf("%s Device does not support geometry shaders; Skipped.\n", kSkipPrefix);
405         return;
406     }
407     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
408     ASSERT_NO_FATAL_FAILURE(InitViewport());
409 
410     // Compiled using the GLSL code below. GlslangValidator rearranges the members, but here they are kept in the order provided.
411     // #version 450
412     // layout (points) in;
413     // layout (points) out;
414     // layout (max_vertices = 1) out;
415     // in gl_PerVertex {
416     //     float gl_PointSize;
417     //     vec4 gl_Position;
418     // } gl_in[];
419     // void main() {
420     //     gl_Position = gl_in[0].gl_Position;
421     //     gl_PointSize = gl_in[0].gl_PointSize;
422     //     EmitVertex();
423     // }
424 
425     const std::string gsSource = R"(
426                OpCapability Geometry
427                OpCapability GeometryPointSize
428           %1 = OpExtInstImport "GLSL.std.450"
429                OpMemoryModel Logical GLSL450
430                OpEntryPoint Geometry %main "main" %_ %gl_in
431                OpExecutionMode %main InputPoints
432                OpExecutionMode %main Invocations 1
433                OpExecutionMode %main OutputPoints
434                OpExecutionMode %main OutputVertices 1
435                OpSource GLSL 450
436                OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
437                OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
438                OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
439                OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
440                OpDecorate %gl_PerVertex Block
441                OpMemberDecorate %gl_PerVertex_0 0 BuiltIn PointSize
442                OpMemberDecorate %gl_PerVertex_0 1 BuiltIn Position
443                OpDecorate %gl_PerVertex_0 Block
444        %void = OpTypeVoid
445           %3 = OpTypeFunction %void
446       %float = OpTypeFloat 32
447     %v4float = OpTypeVector %float 4
448        %uint = OpTypeInt 32 0
449      %uint_1 = OpConstant %uint 1
450 %_arr_float_uint_1 = OpTypeArray %float %uint_1
451 %gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
452 %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
453           %_ = OpVariable %_ptr_Output_gl_PerVertex Output
454         %int = OpTypeInt 32 1
455       %int_0 = OpConstant %int 0
456 %gl_PerVertex_0 = OpTypeStruct %float %v4float
457 %_arr_gl_PerVertex_0_uint_1 = OpTypeArray %gl_PerVertex_0 %uint_1
458 %_ptr_Input__arr_gl_PerVertex_0_uint_1 = OpTypePointer Input %_arr_gl_PerVertex_0_uint_1
459       %gl_in = OpVariable %_ptr_Input__arr_gl_PerVertex_0_uint_1 Input
460 %_ptr_Input_v4float = OpTypePointer Input %v4float
461 %_ptr_Output_v4float = OpTypePointer Output %v4float
462       %int_1 = OpConstant %int 1
463 %_ptr_Input_float = OpTypePointer Input %float
464 %_ptr_Output_float = OpTypePointer Output %float
465        %main = OpFunction %void None %3
466           %5 = OpLabel
467          %21 = OpAccessChain %_ptr_Input_v4float %gl_in %int_0 %int_1
468          %22 = OpLoad %v4float %21
469          %24 = OpAccessChain %_ptr_Output_v4float %_ %int_0
470                OpStore %24 %22
471          %27 = OpAccessChain %_ptr_Input_float %gl_in %int_0 %int_0
472          %28 = OpLoad %float %27
473          %30 = OpAccessChain %_ptr_Output_float %_ %int_1
474                OpStore %30 %28
475                OpEmitVertex
476                OpReturn
477                OpFunctionEnd
478         )";
479 
480     VkShaderObj vs(m_device, bindStateVertPointSizeShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
481     VkShaderObj gs(m_device, gsSource, VK_SHADER_STAGE_GEOMETRY_BIT, this);
482 
483     auto set_info = [&](CreatePipelineHelper &helper) {
484         helper.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
485         helper.shader_stages_ = {vs.GetStageCreateInfo(), gs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
486     };
487     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
488                                       "Builtin variable inside block doesn't match between");
489 }
490 
TEST_F(VkLayerTest,BuiltinBlockSizeMismatchVsGs)491 TEST_F(VkLayerTest, BuiltinBlockSizeMismatchVsGs) {
492     TEST_DESCRIPTION("Use different number of elements in builtin block interface between VS and GS.");
493 
494     ASSERT_NO_FATAL_FAILURE(Init());
495 
496     if (!m_device->phy().features().geometryShader) {
497         printf("%s Device does not support geometry shaders; Skipped.\n", kSkipPrefix);
498         return;
499     }
500 
501     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
502     ASSERT_NO_FATAL_FAILURE(InitViewport());
503 
504     static const char *gsSource =
505         "#version 450\n"
506         "layout (points) in;\n"
507         "layout (points) out;\n"
508         "layout (max_vertices = 1) out;\n"
509         "in gl_PerVertex\n"
510         "{\n"
511         "    vec4 gl_Position;\n"
512         "    float gl_PointSize;\n"
513         "    float gl_ClipDistance[];\n"
514         "} gl_in[];\n"
515         "void main()\n"
516         "{\n"
517         "    gl_Position = gl_in[0].gl_Position;\n"
518         "    gl_PointSize = gl_in[0].gl_PointSize;\n"
519         "    EmitVertex();\n"
520         "}\n";
521 
522     VkShaderObj vs(m_device, bindStateVertPointSizeShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
523     VkShaderObj gs(m_device, gsSource, VK_SHADER_STAGE_GEOMETRY_BIT, this);
524 
525     auto set_info = [&](CreatePipelineHelper &helper) {
526         helper.ia_ci_.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
527         helper.shader_stages_ = {vs.GetStageCreateInfo(), gs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
528     };
529     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
530                                       "Number of elements inside builtin block differ between stages");
531 }
532 
TEST_F(VkLayerTest,CreatePipelineLayoutExceedsSetLimit)533 TEST_F(VkLayerTest, CreatePipelineLayoutExceedsSetLimit) {
534     TEST_DESCRIPTION("Attempt to create a pipeline layout using more than the physical limit of SetLayouts.");
535 
536     ASSERT_NO_FATAL_FAILURE(Init());
537 
538     VkDescriptorSetLayoutBinding layout_binding = {};
539     layout_binding.binding = 0;
540     layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
541     layout_binding.descriptorCount = 1;
542     layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
543     layout_binding.pImmutableSamplers = NULL;
544 
545     VkDescriptorSetLayoutCreateInfo ds_layout_ci = {};
546     ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
547     ds_layout_ci.bindingCount = 1;
548     ds_layout_ci.pBindings = &layout_binding;
549     VkDescriptorSetLayout ds_layout = {};
550     VkResult err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
551     ASSERT_VK_SUCCESS(err);
552 
553     // Create an array of DSLs, one larger than the physical limit
554     const auto excess_layouts = 1 + m_device->phy().properties().limits.maxBoundDescriptorSets;
555     std::vector<VkDescriptorSetLayout> dsl_array(excess_layouts, ds_layout);
556 
557     VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
558     pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
559     pipeline_layout_ci.pNext = NULL;
560     pipeline_layout_ci.setLayoutCount = excess_layouts;
561     pipeline_layout_ci.pSetLayouts = dsl_array.data();
562 
563     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-setLayoutCount-00286");
564     VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
565     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
566     m_errorMonitor->VerifyFound();
567 
568     // Clean up
569     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
570 }
571 
TEST_F(VkLayerTest,CreatePipelineLayoutExcessPerStageDescriptors)572 TEST_F(VkLayerTest, CreatePipelineLayoutExcessPerStageDescriptors) {
573     TEST_DESCRIPTION("Attempt to create a pipeline layout where total descriptors exceed per-stage limits");
574 
575     ASSERT_NO_FATAL_FAILURE(Init());
576 
577     uint32_t max_uniform_buffers = m_device->phy().properties().limits.maxPerStageDescriptorUniformBuffers;
578     uint32_t max_storage_buffers = m_device->phy().properties().limits.maxPerStageDescriptorStorageBuffers;
579     uint32_t max_sampled_images = m_device->phy().properties().limits.maxPerStageDescriptorSampledImages;
580     uint32_t max_storage_images = m_device->phy().properties().limits.maxPerStageDescriptorStorageImages;
581     uint32_t max_samplers = m_device->phy().properties().limits.maxPerStageDescriptorSamplers;
582     uint32_t max_combined = std::min(max_samplers, max_sampled_images);
583     uint32_t max_input_attachments = m_device->phy().properties().limits.maxPerStageDescriptorInputAttachments;
584 
585     uint32_t sum_dyn_uniform_buffers = m_device->phy().properties().limits.maxDescriptorSetUniformBuffersDynamic;
586     uint32_t sum_uniform_buffers = m_device->phy().properties().limits.maxDescriptorSetUniformBuffers;
587     uint32_t sum_dyn_storage_buffers = m_device->phy().properties().limits.maxDescriptorSetStorageBuffersDynamic;
588     uint32_t sum_storage_buffers = m_device->phy().properties().limits.maxDescriptorSetStorageBuffers;
589     uint32_t sum_sampled_images = m_device->phy().properties().limits.maxDescriptorSetSampledImages;
590     uint32_t sum_storage_images = m_device->phy().properties().limits.maxDescriptorSetStorageImages;
591     uint32_t sum_samplers = m_device->phy().properties().limits.maxDescriptorSetSamplers;
592     uint32_t sum_input_attachments = m_device->phy().properties().limits.maxDescriptorSetInputAttachments;
593 
594     // Devices that report UINT32_MAX for any of these limits can't run this test
595     if (UINT32_MAX == std::max({max_uniform_buffers, max_storage_buffers, max_sampled_images, max_storage_images, max_samplers})) {
596         printf("%s Physical device limits report as 2^32-1. Skipping test.\n", kSkipPrefix);
597         return;
598     }
599 
600     VkDescriptorSetLayoutBinding dslb = {};
601     std::vector<VkDescriptorSetLayoutBinding> dslb_vec = {};
602     VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
603     VkDescriptorSetLayoutCreateInfo ds_layout_ci = {};
604     ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
605     ds_layout_ci.pNext = NULL;
606     VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
607     pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
608     pipeline_layout_ci.pNext = NULL;
609     pipeline_layout_ci.setLayoutCount = 1;
610     pipeline_layout_ci.pSetLayouts = &ds_layout;
611     VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
612 
613     // VU 0fe0023e - too many sampler type descriptors in fragment stage
614     dslb_vec.clear();
615     dslb.binding = 0;
616     dslb.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
617     dslb.descriptorCount = max_samplers;
618     dslb.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
619     dslb.pImmutableSamplers = NULL;
620     dslb_vec.push_back(dslb);
621     dslb.binding = 1;
622     dslb.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
623     dslb.descriptorCount = max_combined;
624     dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
625     dslb_vec.push_back(dslb);
626 
627     ds_layout_ci.bindingCount = dslb_vec.size();
628     ds_layout_ci.pBindings = dslb_vec.data();
629     VkResult err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
630     ASSERT_VK_SUCCESS(err);
631 
632     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00287");
633     if ((max_samplers + max_combined) > sum_samplers) {
634         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
635                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01677");  // expect all-stages sum too
636     }
637     if (max_combined > sum_sampled_images) {
638         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
639                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01682");  // expect all-stages sum too
640     }
641     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
642     m_errorMonitor->VerifyFound();
643     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
644     pipeline_layout = VK_NULL_HANDLE;
645     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
646 
647     // VU 0fe00240 - too many uniform buffer type descriptors in vertex stage
648     dslb_vec.clear();
649     dslb.binding = 0;
650     dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
651     dslb.descriptorCount = max_uniform_buffers + 1;
652     dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
653     dslb_vec.push_back(dslb);
654     dslb.binding = 1;
655     dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
656     dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
657     dslb_vec.push_back(dslb);
658 
659     ds_layout_ci.bindingCount = dslb_vec.size();
660     ds_layout_ci.pBindings = dslb_vec.data();
661     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
662     ASSERT_VK_SUCCESS(err);
663 
664     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00288");
665     if (dslb.descriptorCount > sum_uniform_buffers) {
666         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
667                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01678");  // expect all-stages sum too
668     }
669     if (dslb.descriptorCount > sum_dyn_uniform_buffers) {
670         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
671                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01679");  // expect all-stages sum too
672     }
673     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
674     m_errorMonitor->VerifyFound();
675     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
676     pipeline_layout = VK_NULL_HANDLE;
677     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
678 
679     // VU 0fe00242 - too many storage buffer type descriptors in compute stage
680     dslb_vec.clear();
681     dslb.binding = 0;
682     dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
683     dslb.descriptorCount = max_storage_buffers + 1;
684     dslb.stageFlags = VK_SHADER_STAGE_ALL;
685     dslb_vec.push_back(dslb);
686     dslb.binding = 1;
687     dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
688     dslb_vec.push_back(dslb);
689     dslb.binding = 2;
690     dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
691     dslb.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
692     dslb_vec.push_back(dslb);
693 
694     ds_layout_ci.bindingCount = dslb_vec.size();
695     ds_layout_ci.pBindings = dslb_vec.data();
696     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
697     ASSERT_VK_SUCCESS(err);
698 
699     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00289");
700     if (dslb.descriptorCount > sum_dyn_storage_buffers) {
701         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
702                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01681");  // expect all-stages sum too
703     }
704     if (dslb_vec[0].descriptorCount + dslb_vec[2].descriptorCount > sum_storage_buffers) {
705         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
706                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01680");  // expect all-stages sum too
707     }
708     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
709     m_errorMonitor->VerifyFound();
710     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
711     pipeline_layout = VK_NULL_HANDLE;
712     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
713 
714     // VU 0fe00244 - too many sampled image type descriptors in multiple stages
715     dslb_vec.clear();
716     dslb.binding = 0;
717     dslb.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
718     dslb.descriptorCount = max_sampled_images;
719     dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
720     dslb_vec.push_back(dslb);
721     dslb.binding = 1;
722     dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
723     dslb.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS;
724     dslb_vec.push_back(dslb);
725     dslb.binding = 2;
726     dslb.descriptorCount = max_combined;
727     dslb.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
728     dslb_vec.push_back(dslb);
729 
730     ds_layout_ci.bindingCount = dslb_vec.size();
731     ds_layout_ci.pBindings = dslb_vec.data();
732     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
733     ASSERT_VK_SUCCESS(err);
734 
735     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00290");
736     if (max_combined + 2 * max_sampled_images > sum_sampled_images) {
737         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
738                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01682");  // expect all-stages sum too
739     }
740     if (max_combined > sum_samplers) {
741         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
742                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01677");  // expect all-stages sum too
743     }
744     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
745     m_errorMonitor->VerifyFound();
746     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
747     pipeline_layout = VK_NULL_HANDLE;
748     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
749 
750     // VU 0fe00246 - too many storage image type descriptors in fragment stage
751     dslb_vec.clear();
752     dslb.binding = 0;
753     dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
754     dslb.descriptorCount = 1 + (max_storage_images / 2);
755     dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
756     dslb_vec.push_back(dslb);
757     dslb.binding = 1;
758     dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
759     dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
760     dslb_vec.push_back(dslb);
761 
762     ds_layout_ci.bindingCount = dslb_vec.size();
763     ds_layout_ci.pBindings = dslb_vec.data();
764     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
765     ASSERT_VK_SUCCESS(err);
766 
767     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00291");
768     if (2 * dslb.descriptorCount > sum_storage_images) {
769         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
770                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01683");  // expect all-stages sum too
771     }
772     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
773     m_errorMonitor->VerifyFound();
774     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
775     pipeline_layout = VK_NULL_HANDLE;
776     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
777 
778     // VU 0fe00d18 - too many input attachments in fragment stage
779     dslb_vec.clear();
780     dslb.binding = 0;
781     dslb.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
782     dslb.descriptorCount = 1 + max_input_attachments;
783     dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
784     dslb_vec.push_back(dslb);
785 
786     ds_layout_ci.bindingCount = dslb_vec.size();
787     ds_layout_ci.pBindings = dslb_vec.data();
788     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
789     ASSERT_VK_SUCCESS(err);
790 
791     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01676");
792     if (dslb.descriptorCount > sum_input_attachments) {
793         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
794                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01684");  // expect all-stages sum too
795     }
796     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
797     m_errorMonitor->VerifyFound();
798     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
799     pipeline_layout = VK_NULL_HANDLE;
800     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
801 }
802 
TEST_F(VkLayerTest,CreatePipelineLayoutExcessDescriptorsOverall)803 TEST_F(VkLayerTest, CreatePipelineLayoutExcessDescriptorsOverall) {
804     TEST_DESCRIPTION("Attempt to create a pipeline layout where total descriptors exceed limits");
805 
806     ASSERT_NO_FATAL_FAILURE(Init());
807 
808     uint32_t max_uniform_buffers = m_device->phy().properties().limits.maxPerStageDescriptorUniformBuffers;
809     uint32_t max_storage_buffers = m_device->phy().properties().limits.maxPerStageDescriptorStorageBuffers;
810     uint32_t max_sampled_images = m_device->phy().properties().limits.maxPerStageDescriptorSampledImages;
811     uint32_t max_storage_images = m_device->phy().properties().limits.maxPerStageDescriptorStorageImages;
812     uint32_t max_samplers = m_device->phy().properties().limits.maxPerStageDescriptorSamplers;
813     uint32_t max_input_attachments = m_device->phy().properties().limits.maxPerStageDescriptorInputAttachments;
814 
815     uint32_t sum_dyn_uniform_buffers = m_device->phy().properties().limits.maxDescriptorSetUniformBuffersDynamic;
816     uint32_t sum_uniform_buffers = m_device->phy().properties().limits.maxDescriptorSetUniformBuffers;
817     uint32_t sum_dyn_storage_buffers = m_device->phy().properties().limits.maxDescriptorSetStorageBuffersDynamic;
818     uint32_t sum_storage_buffers = m_device->phy().properties().limits.maxDescriptorSetStorageBuffers;
819     uint32_t sum_sampled_images = m_device->phy().properties().limits.maxDescriptorSetSampledImages;
820     uint32_t sum_storage_images = m_device->phy().properties().limits.maxDescriptorSetStorageImages;
821     uint32_t sum_samplers = m_device->phy().properties().limits.maxDescriptorSetSamplers;
822     uint32_t sum_input_attachments = m_device->phy().properties().limits.maxDescriptorSetInputAttachments;
823 
824     // Devices that report UINT32_MAX for any of these limits can't run this test
825     if (UINT32_MAX == std::max({sum_dyn_uniform_buffers, sum_uniform_buffers, sum_dyn_storage_buffers, sum_storage_buffers,
826                                 sum_sampled_images, sum_storage_images, sum_samplers, sum_input_attachments})) {
827         printf("%s Physical device limits report as 2^32-1. Skipping test.\n", kSkipPrefix);
828         return;
829     }
830 
831     VkDescriptorSetLayoutBinding dslb = {};
832     std::vector<VkDescriptorSetLayoutBinding> dslb_vec = {};
833     VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
834     VkDescriptorSetLayoutCreateInfo ds_layout_ci = {};
835     ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
836     ds_layout_ci.pNext = NULL;
837     VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
838     pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
839     pipeline_layout_ci.pNext = NULL;
840     pipeline_layout_ci.setLayoutCount = 1;
841     pipeline_layout_ci.pSetLayouts = &ds_layout;
842     VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
843 
844     // VU 0fe00d1a - too many sampler type descriptors overall
845     dslb_vec.clear();
846     dslb.binding = 0;
847     dslb.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
848     dslb.descriptorCount = sum_samplers / 2;
849     dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
850     dslb.pImmutableSamplers = NULL;
851     dslb_vec.push_back(dslb);
852     dslb.binding = 1;
853     dslb.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
854     dslb.descriptorCount = sum_samplers - dslb.descriptorCount + 1;
855     dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
856     dslb_vec.push_back(dslb);
857 
858     ds_layout_ci.bindingCount = dslb_vec.size();
859     ds_layout_ci.pBindings = dslb_vec.data();
860     VkResult err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
861     ASSERT_VK_SUCCESS(err);
862 
863     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01677");
864     if (dslb.descriptorCount > max_samplers) {
865         m_errorMonitor->SetDesiredFailureMsg(
866             VK_DEBUG_REPORT_ERROR_BIT_EXT,
867             "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00287");  // Expect max-per-stage samplers exceeds limits
868     }
869     if (dslb.descriptorCount > sum_sampled_images) {
870         m_errorMonitor->SetDesiredFailureMsg(
871             VK_DEBUG_REPORT_ERROR_BIT_EXT,
872             "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01682");  // Expect max overall sampled image count exceeds limits
873     }
874     if (dslb.descriptorCount > max_sampled_images) {
875         m_errorMonitor->SetDesiredFailureMsg(
876             VK_DEBUG_REPORT_ERROR_BIT_EXT,
877             "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00290");  // Expect max per-stage sampled image count exceeds limits
878     }
879     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
880     m_errorMonitor->VerifyFound();
881     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
882     pipeline_layout = VK_NULL_HANDLE;
883     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
884 
885     // VU 0fe00d1c - too many uniform buffer type descriptors overall
886     dslb_vec.clear();
887     dslb.binding = 0;
888     dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
889     dslb.descriptorCount = sum_uniform_buffers + 1;
890     dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
891     dslb.pImmutableSamplers = NULL;
892     dslb_vec.push_back(dslb);
893 
894     ds_layout_ci.bindingCount = dslb_vec.size();
895     ds_layout_ci.pBindings = dslb_vec.data();
896     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
897     ASSERT_VK_SUCCESS(err);
898 
899     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01678");
900     if (dslb.descriptorCount > max_uniform_buffers) {
901         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
902                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00288");  // expect max-per-stage too
903     }
904     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
905     m_errorMonitor->VerifyFound();
906     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
907     pipeline_layout = VK_NULL_HANDLE;
908     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
909 
910     // VU 0fe00d1e - too many dynamic uniform buffer type descriptors overall
911     dslb_vec.clear();
912     dslb.binding = 0;
913     dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
914     dslb.descriptorCount = sum_dyn_uniform_buffers + 1;
915     dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
916     dslb.pImmutableSamplers = NULL;
917     dslb_vec.push_back(dslb);
918 
919     ds_layout_ci.bindingCount = dslb_vec.size();
920     ds_layout_ci.pBindings = dslb_vec.data();
921     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
922     ASSERT_VK_SUCCESS(err);
923 
924     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01679");
925     if (dslb.descriptorCount > max_uniform_buffers) {
926         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
927                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00288");  // expect max-per-stage too
928     }
929     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
930     m_errorMonitor->VerifyFound();
931     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
932     pipeline_layout = VK_NULL_HANDLE;
933     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
934 
935     // VU 0fe00d20 - too many storage buffer type descriptors overall
936     dslb_vec.clear();
937     dslb.binding = 0;
938     dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
939     dslb.descriptorCount = sum_storage_buffers + 1;
940     dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
941     dslb.pImmutableSamplers = NULL;
942     dslb_vec.push_back(dslb);
943 
944     ds_layout_ci.bindingCount = dslb_vec.size();
945     ds_layout_ci.pBindings = dslb_vec.data();
946     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
947     ASSERT_VK_SUCCESS(err);
948 
949     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01680");
950     if (dslb.descriptorCount > max_storage_buffers) {
951         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
952                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00289");  // expect max-per-stage too
953     }
954     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
955     m_errorMonitor->VerifyFound();
956     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
957     pipeline_layout = VK_NULL_HANDLE;
958     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
959 
960     // VU 0fe00d22 - too many dynamic storage buffer type descriptors overall
961     dslb_vec.clear();
962     dslb.binding = 0;
963     dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
964     dslb.descriptorCount = sum_dyn_storage_buffers + 1;
965     dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
966     dslb.pImmutableSamplers = NULL;
967     dslb_vec.push_back(dslb);
968 
969     ds_layout_ci.bindingCount = dslb_vec.size();
970     ds_layout_ci.pBindings = dslb_vec.data();
971     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
972     ASSERT_VK_SUCCESS(err);
973 
974     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01681");
975     if (dslb.descriptorCount > max_storage_buffers) {
976         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
977                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00289");  // expect max-per-stage too
978     }
979     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
980     m_errorMonitor->VerifyFound();
981     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
982     pipeline_layout = VK_NULL_HANDLE;
983     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
984 
985     // VU 0fe00d24 - too many sampled image type descriptors overall
986     dslb_vec.clear();
987     dslb.binding = 0;
988     dslb.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
989     dslb.descriptorCount = max_samplers;
990     dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
991     dslb.pImmutableSamplers = NULL;
992     dslb_vec.push_back(dslb);
993     dslb.binding = 1;
994     dslb.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
995     // revisit: not robust to odd limits.
996     uint32_t remaining = (max_samplers > sum_sampled_images ? 0 : (sum_sampled_images - max_samplers) / 2);
997     dslb.descriptorCount = 1 + remaining;
998     dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
999     dslb_vec.push_back(dslb);
1000     dslb.binding = 2;
1001     dslb.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
1002     dslb.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
1003     dslb_vec.push_back(dslb);
1004 
1005     ds_layout_ci.bindingCount = dslb_vec.size();
1006     ds_layout_ci.pBindings = dslb_vec.data();
1007     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
1008     ASSERT_VK_SUCCESS(err);
1009 
1010     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01682");
1011     if (std::max(dslb_vec[0].descriptorCount, dslb_vec[1].descriptorCount) > max_sampled_images) {
1012         m_errorMonitor->SetDesiredFailureMsg(
1013             VK_DEBUG_REPORT_ERROR_BIT_EXT,
1014             "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00290");  // Expect max-per-stage sampled images to exceed limits
1015     }
1016     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
1017     m_errorMonitor->VerifyFound();
1018     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
1019     pipeline_layout = VK_NULL_HANDLE;
1020     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
1021 
1022     // VU 0fe00d26 - too many storage image type descriptors overall
1023     dslb_vec.clear();
1024     dslb.binding = 0;
1025     dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1026     dslb.descriptorCount = sum_storage_images / 2;
1027     dslb.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
1028     dslb.pImmutableSamplers = NULL;
1029     dslb_vec.push_back(dslb);
1030     dslb.binding = 1;
1031     dslb.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1032     dslb.descriptorCount = sum_storage_images - dslb.descriptorCount + 1;
1033     dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
1034     dslb_vec.push_back(dslb);
1035 
1036     ds_layout_ci.bindingCount = dslb_vec.size();
1037     ds_layout_ci.pBindings = dslb_vec.data();
1038     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
1039     ASSERT_VK_SUCCESS(err);
1040 
1041     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01683");
1042     if (dslb.descriptorCount > max_storage_images) {
1043         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
1044                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00291");  // expect max-per-stage too
1045     }
1046     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
1047     m_errorMonitor->VerifyFound();
1048     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
1049     pipeline_layout = VK_NULL_HANDLE;
1050     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
1051 
1052     // VU 0fe00d28 - too many input attachment type descriptors overall
1053     dslb_vec.clear();
1054     dslb.binding = 0;
1055     dslb.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
1056     dslb.descriptorCount = sum_input_attachments + 1;
1057     dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
1058     dslb.pImmutableSamplers = NULL;
1059     dslb_vec.push_back(dslb);
1060 
1061     ds_layout_ci.bindingCount = dslb_vec.size();
1062     ds_layout_ci.pBindings = dslb_vec.data();
1063     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
1064     ASSERT_VK_SUCCESS(err);
1065 
1066     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01684");
1067     if (dslb.descriptorCount > max_input_attachments) {
1068         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
1069                                              "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-01676");  // expect max-per-stage too
1070     }
1071     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
1072     m_errorMonitor->VerifyFound();
1073     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);  // Unnecessary but harmless if test passed
1074     pipeline_layout = VK_NULL_HANDLE;
1075     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
1076 }
1077 
TEST_F(VkLayerTest,InvalidCmdBufferPipelineDestroyed)1078 TEST_F(VkLayerTest, InvalidCmdBufferPipelineDestroyed) {
1079     TEST_DESCRIPTION("Attempt to draw with a command buffer that is invalid due to a pipeline dependency being destroyed.");
1080     ASSERT_NO_FATAL_FAILURE(Init());
1081     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1082 
1083     {
1084         // Use helper to create graphics pipeline
1085         CreatePipelineHelper helper(*this);
1086         helper.InitInfo();
1087         helper.InitState();
1088         helper.CreateGraphicsPipeline();
1089 
1090         // Bind helper pipeline to command buffer
1091         m_commandBuffer->begin();
1092         vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, helper.pipeline_);
1093         m_commandBuffer->end();
1094 
1095         // pipeline will be destroyed when helper goes out of scope
1096     }
1097 
1098     // Cause error by submitting command buffer that references destroyed pipeline
1099     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
1100                                          "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkPipeline");
1101     m_commandBuffer->QueueCommandBuffer(false);
1102     m_errorMonitor->VerifyFound();
1103 }
1104 
TEST_F(VkLayerTest,InvalidPipeline)1105 TEST_F(VkLayerTest, InvalidPipeline) {
1106     uint64_t fake_pipeline_handle = 0xbaad6001;
1107     VkPipeline bad_pipeline = reinterpret_cast<VkPipeline &>(fake_pipeline_handle);
1108 
1109     // Enable VK_KHR_draw_indirect_count for KHR variants
1110     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1111     if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME)) {
1112         m_device_extension_names.push_back(VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME);
1113     }
1114     ASSERT_NO_FATAL_FAILURE(InitState());
1115     bool has_khr_indirect = DeviceExtensionEnabled(VK_KHR_DRAW_INDIRECT_COUNT_EXTENSION_NAME);
1116     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1117 
1118     // Attempt to bind an invalid Pipeline to a valid Command Buffer
1119     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindPipeline-pipeline-parameter");
1120     m_commandBuffer->begin();
1121     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, bad_pipeline);
1122     m_errorMonitor->VerifyFound();
1123 
1124     // Try each of the 6 flavors of Draw()
1125     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);  // Draw*() calls must be submitted within a renderpass
1126 
1127     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDraw-None-02700");
1128     m_commandBuffer->Draw(1, 0, 0, 0);
1129     m_errorMonitor->VerifyFound();
1130 
1131     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndexed-None-02700");
1132     m_commandBuffer->DrawIndexed(1, 1, 0, 0, 0);
1133     m_errorMonitor->VerifyFound();
1134 
1135     VkBufferObj buffer;
1136     VkBufferCreateInfo ci = {};
1137     ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1138     ci.usage = VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
1139     ci.size = 1024;
1140     buffer.init(*m_device, ci);
1141     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndirect-None-02700");
1142     vkCmdDrawIndirect(m_commandBuffer->handle(), buffer.handle(), 0, 1, 0);
1143     m_errorMonitor->VerifyFound();
1144 
1145     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndexedIndirect-None-02700");
1146     vkCmdDrawIndexedIndirect(m_commandBuffer->handle(), buffer.handle(), 0, 1, 0);
1147     m_errorMonitor->VerifyFound();
1148 
1149     if (has_khr_indirect) {
1150         auto fpCmdDrawIndirectCountKHR =
1151             (PFN_vkCmdDrawIndirectCountKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdDrawIndirectCountKHR");
1152         ASSERT_NE(fpCmdDrawIndirectCountKHR, nullptr);
1153 
1154         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndirectCountKHR-None-02700");
1155         // stride must be a multiple of 4 and must be greater than or equal to sizeof(VkDrawIndirectCommand)
1156         fpCmdDrawIndirectCountKHR(m_commandBuffer->handle(), buffer.handle(), 0, buffer.handle(), 512, 1, 512);
1157         m_errorMonitor->VerifyFound();
1158 
1159         auto fpCmdDrawIndexedIndirectCountKHR =
1160             (PFN_vkCmdDrawIndexedIndirectCountKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdDrawIndexedIndirectCountKHR");
1161         ASSERT_NE(fpCmdDrawIndexedIndirectCountKHR, nullptr);
1162         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDrawIndexedIndirectCountKHR-None-02700");
1163         // stride must be a multiple of 4 and must be greater than or equal to sizeof(VkDrawIndexedIndirectCommand)
1164         fpCmdDrawIndexedIndirectCountKHR(m_commandBuffer->handle(), buffer.handle(), 0, buffer.handle(), 512, 1, 512);
1165         m_errorMonitor->VerifyFound();
1166     }
1167 
1168     // Also try the Dispatch variants
1169     vkCmdEndRenderPass(m_commandBuffer->handle());  // Compute submissions must be outside a renderpass
1170 
1171     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatch-None-02700");
1172     vkCmdDispatch(m_commandBuffer->handle(), 0, 0, 0);
1173     m_errorMonitor->VerifyFound();
1174 
1175     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchIndirect-None-02700");
1176     vkCmdDispatchIndirect(m_commandBuffer->handle(), buffer.handle(), 0);
1177     m_errorMonitor->VerifyFound();
1178 }
1179 
TEST_F(VkLayerTest,CmdDispatchExceedLimits)1180 TEST_F(VkLayerTest, CmdDispatchExceedLimits) {
1181     TEST_DESCRIPTION("Compute dispatch with dimensions that exceed device limits");
1182 
1183     // Enable KHX device group extensions, if available
1184     if (InstanceExtensionSupported(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME)) {
1185         m_instance_extension_names.push_back(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME);
1186     }
1187     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1188     bool khx_dg_ext_available = false;
1189     if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DEVICE_GROUP_EXTENSION_NAME)) {
1190         m_device_extension_names.push_back(VK_KHR_DEVICE_GROUP_EXTENSION_NAME);
1191         khx_dg_ext_available = true;
1192     }
1193     ASSERT_NO_FATAL_FAILURE(InitState());
1194 
1195     uint32_t x_count_limit = m_device->props.limits.maxComputeWorkGroupCount[0];
1196     uint32_t y_count_limit = m_device->props.limits.maxComputeWorkGroupCount[1];
1197     uint32_t z_count_limit = m_device->props.limits.maxComputeWorkGroupCount[2];
1198     if (std::max({x_count_limit, y_count_limit, z_count_limit}) == UINT32_MAX) {
1199         printf("%s device maxComputeWorkGroupCount limit reports UINT32_MAX, test not possible, skipping.\n", kSkipPrefix);
1200         return;
1201     }
1202 
1203     uint32_t x_size_limit = m_device->props.limits.maxComputeWorkGroupSize[0];
1204     uint32_t y_size_limit = m_device->props.limits.maxComputeWorkGroupSize[1];
1205     uint32_t z_size_limit = m_device->props.limits.maxComputeWorkGroupSize[2];
1206 
1207     std::string spv_source = R"(
1208         OpCapability Shader
1209         OpMemoryModel Logical GLSL450
1210         OpEntryPoint GLCompute %main "main"
1211         OpExecutionMode %main LocalSize )";
1212     spv_source.append(std::to_string(x_size_limit + 1) + " " + std::to_string(y_size_limit + 1) + " " +
1213                       std::to_string(z_size_limit + 1));
1214     spv_source.append(R"(
1215         %void = OpTypeVoid
1216            %3 = OpTypeFunction %void
1217         %main = OpFunction %void None %3
1218            %5 = OpLabel
1219                 OpReturn
1220                 OpFunctionEnd)");
1221 
1222     CreateComputePipelineHelper pipe(*this);
1223     pipe.InitInfo();
1224     pipe.cs_.reset(new VkShaderObj(m_device, spv_source, VK_SHADER_STAGE_COMPUTE_BIT, this));
1225     pipe.InitState();
1226 
1227     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "exceeds device limit maxComputeWorkGroupSize[0]");
1228     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "exceeds device limit maxComputeWorkGroupSize[1]");
1229     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "exceeds device limit maxComputeWorkGroupSize[2]");
1230     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "features-limits-maxComputeWorkGroupInvocations");
1231     pipe.CreateComputePipeline();
1232     m_errorMonitor->VerifyFound();
1233 
1234     // Create a minimal compute pipeline
1235     x_size_limit = (x_size_limit > 1024) ? 1024 : x_size_limit;
1236     y_size_limit = (y_size_limit > 1024) ? 1024 : y_size_limit;
1237     z_size_limit = (z_size_limit > 64) ? 64 : z_size_limit;
1238 
1239     uint32_t invocations_limit = m_device->props.limits.maxComputeWorkGroupInvocations;
1240     x_size_limit = (x_size_limit > invocations_limit) ? invocations_limit : x_size_limit;
1241     invocations_limit /= x_size_limit;
1242     y_size_limit = (y_size_limit > invocations_limit) ? invocations_limit : y_size_limit;
1243     invocations_limit /= y_size_limit;
1244     z_size_limit = (z_size_limit > invocations_limit) ? invocations_limit : z_size_limit;
1245 
1246     char cs_text[128] = "";
1247     sprintf(cs_text, "#version 450\nlayout(local_size_x = %d, local_size_y = %d, local_size_z = %d) in;\nvoid main() {}\n",
1248             x_size_limit, y_size_limit, z_size_limit);
1249 
1250     VkShaderObj cs_obj(m_device, cs_text, VK_SHADER_STAGE_COMPUTE_BIT, this);
1251     pipe.cs_.reset(new VkShaderObj(m_device, cs_text, VK_SHADER_STAGE_COMPUTE_BIT, this));
1252     pipe.CreateComputePipeline();
1253 
1254     // Bind pipeline to command buffer
1255     m_commandBuffer->begin();
1256     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipe.pipeline_);
1257 
1258     // Dispatch counts that exceed device limits
1259     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatch-groupCountX-00386");
1260     vkCmdDispatch(m_commandBuffer->handle(), x_count_limit + 1, y_count_limit, z_count_limit);
1261     m_errorMonitor->VerifyFound();
1262 
1263     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatch-groupCountY-00387");
1264     vkCmdDispatch(m_commandBuffer->handle(), x_count_limit, y_count_limit + 1, z_count_limit);
1265     m_errorMonitor->VerifyFound();
1266 
1267     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatch-groupCountZ-00388");
1268     vkCmdDispatch(m_commandBuffer->handle(), x_count_limit, y_count_limit, z_count_limit + 1);
1269     m_errorMonitor->VerifyFound();
1270 
1271     if (khx_dg_ext_available) {
1272         PFN_vkCmdDispatchBaseKHR fp_vkCmdDispatchBaseKHR =
1273             (PFN_vkCmdDispatchBaseKHR)vkGetInstanceProcAddr(instance(), "vkCmdDispatchBaseKHR");
1274 
1275         // Base equals or exceeds limit
1276         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-baseGroupX-00421");
1277         fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_count_limit, y_count_limit - 1, z_count_limit - 1, 0, 0, 0);
1278         m_errorMonitor->VerifyFound();
1279 
1280         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-baseGroupX-00422");
1281         fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_count_limit - 1, y_count_limit, z_count_limit - 1, 0, 0, 0);
1282         m_errorMonitor->VerifyFound();
1283 
1284         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-baseGroupZ-00423");
1285         fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_count_limit - 1, y_count_limit - 1, z_count_limit, 0, 0, 0);
1286         m_errorMonitor->VerifyFound();
1287 
1288         // (Base + count) exceeds limit
1289         uint32_t x_base = x_count_limit / 2;
1290         uint32_t y_base = y_count_limit / 2;
1291         uint32_t z_base = z_count_limit / 2;
1292         x_count_limit -= x_base;
1293         y_count_limit -= y_base;
1294         z_count_limit -= z_base;
1295 
1296         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-groupCountX-00424");
1297         fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_base, y_base, z_base, x_count_limit + 1, y_count_limit, z_count_limit);
1298         m_errorMonitor->VerifyFound();
1299 
1300         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-groupCountY-00425");
1301         fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_base, y_base, z_base, x_count_limit, y_count_limit + 1, z_count_limit);
1302         m_errorMonitor->VerifyFound();
1303 
1304         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDispatchBase-groupCountZ-00426");
1305         fp_vkCmdDispatchBaseKHR(m_commandBuffer->handle(), x_base, y_base, z_base, x_count_limit, y_count_limit, z_count_limit + 1);
1306         m_errorMonitor->VerifyFound();
1307     } else {
1308         printf("%s KHX_DEVICE_GROUP_* extensions not supported, skipping CmdDispatchBaseKHR() tests.\n", kSkipPrefix);
1309     }
1310 }
1311 
TEST_F(VkLayerTest,InvalidPipelineCreateState)1312 TEST_F(VkLayerTest, InvalidPipelineCreateState) {
1313     // Attempt to Create Gfx Pipeline w/o a VS
1314 
1315     ASSERT_NO_FATAL_FAILURE(Init());
1316     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1317     ASSERT_NO_FATAL_FAILURE(InitViewport());
1318 
1319     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
1320     VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
1321 
1322     VkPipelineShaderStageCreateInfo shaderStage = fs.GetStageCreateInfo();  // should be: vs.GetStageCreateInfo();
1323 
1324     auto set_info = [&](CreatePipelineHelper &helper) { helper.shader_stages_ = {shaderStage}; };
1325     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1326                                       "Invalid Pipeline CreateInfo State: Vertex Shader required");
1327 
1328     // Finally, check the string validation for the shader stage pName variable.  Correct the shader stage data, and bork the
1329     // string before calling again
1330     shaderStage = vs.GetStageCreateInfo();
1331     const uint8_t cont_char = 0xf8;
1332     char bad_string[] = {static_cast<char>(cont_char), static_cast<char>(cont_char), static_cast<char>(cont_char),
1333                          static_cast<char>(cont_char)};
1334     shaderStage.pName = bad_string;
1335 
1336     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1337                                       "contains invalid characters or is badly formed");
1338 }
1339 
TEST_F(VkLayerTest,InvalidPipelineSampleRateFeatureDisable)1340 TEST_F(VkLayerTest, InvalidPipelineSampleRateFeatureDisable) {
1341     // Enable sample shading in pipeline when the feature is disabled.
1342     // Disable sampleRateShading here
1343     VkPhysicalDeviceFeatures device_features = {};
1344     device_features.sampleRateShading = VK_FALSE;
1345 
1346     ASSERT_NO_FATAL_FAILURE(Init(&device_features));
1347     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1348 
1349     // Cause the error by enabling sample shading...
1350     auto set_shading_enable = [](CreatePipelineHelper &helper) { helper.pipe_ms_state_ci_.sampleShadingEnable = VK_TRUE; };
1351     CreatePipelineHelper::OneshotTest(*this, set_shading_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1352                                       "VUID-VkPipelineMultisampleStateCreateInfo-sampleShadingEnable-00784");
1353 }
1354 
TEST_F(VkLayerTest,InvalidPipelineSampleRateFeatureEnable)1355 TEST_F(VkLayerTest, InvalidPipelineSampleRateFeatureEnable) {
1356     // Enable sample shading in pipeline when the feature is disabled.
1357     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1358 
1359     // Require sampleRateShading here
1360     VkPhysicalDeviceFeatures device_features = {};
1361     ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features));
1362     if (device_features.sampleRateShading == VK_FALSE) {
1363         printf("%s SampleRateShading feature is disabled -- skipping related checks.\n", kSkipPrefix);
1364         return;
1365     }
1366 
1367     ASSERT_NO_FATAL_FAILURE(InitState(&device_features));
1368     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1369 
1370     auto range_test = [this](float value, bool positive_test) {
1371         auto info_override = [value](CreatePipelineHelper &helper) {
1372             helper.pipe_ms_state_ci_.sampleShadingEnable = VK_TRUE;
1373             helper.pipe_ms_state_ci_.minSampleShading = value;
1374         };
1375         CreatePipelineHelper::OneshotTest(*this, info_override, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1376                                           "VUID-VkPipelineMultisampleStateCreateInfo-minSampleShading-00786", positive_test);
1377     };
1378 
1379     range_test(NearestSmaller(0.0F), false);
1380     range_test(NearestGreater(1.0F), false);
1381     range_test(0.0F, /* positive_test= */ true);
1382     range_test(1.0F, /* positive_test= */ true);
1383 }
1384 
TEST_F(VkLayerTest,InvalidPipelineSamplePNext)1385 TEST_F(VkLayerTest, InvalidPipelineSamplePNext) {
1386     // Enable sample shading in pipeline when the feature is disabled.
1387     // Check for VK_KHR_get_physical_device_properties2
1388     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
1389         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1390     }
1391     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1392 
1393     // Set up the extension structs
1394     auto sampleLocations = chain_util::Init<VkPipelineSampleLocationsStateCreateInfoEXT>();
1395     sampleLocations.sampleLocationsInfo.sType = VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT;
1396     auto coverageToColor = chain_util::Init<VkPipelineCoverageToColorStateCreateInfoNV>();
1397     auto coverageModulation = chain_util::Init<VkPipelineCoverageModulationStateCreateInfoNV>();
1398     auto discriminatrix = [this](const char *name) { return DeviceExtensionSupported(gpu(), nullptr, name); };
1399     chain_util::ExtensionChain chain(discriminatrix, &m_device_extension_names);
1400     chain.Add(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME, sampleLocations);
1401     chain.Add(VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME, coverageToColor);
1402     chain.Add(VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME, coverageModulation);
1403     const void *extension_head = chain.Head();
1404 
1405     ASSERT_NO_FATAL_FAILURE(InitState());
1406     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1407 
1408     if (extension_head) {
1409         auto good_chain = [extension_head](CreatePipelineHelper &helper) { helper.pipe_ms_state_ci_.pNext = extension_head; };
1410         CreatePipelineHelper::OneshotTest(*this, good_chain, (VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT),
1411                                           "No error", true);
1412     } else {
1413         printf("%s Required extension not present -- skipping positive checks.\n", kSkipPrefix);
1414     }
1415 
1416     auto instance_ci = chain_util::Init<VkInstanceCreateInfo>();
1417     auto bad_chain = [&instance_ci](CreatePipelineHelper &helper) { helper.pipe_ms_state_ci_.pNext = &instance_ci; };
1418     CreatePipelineHelper::OneshotTest(*this, bad_chain, VK_DEBUG_REPORT_WARNING_BIT_EXT,
1419                                       "VUID-VkPipelineMultisampleStateCreateInfo-pNext-pNext");
1420 }
1421 
TEST_F(VkLayerTest,VertexAttributeDivisorExtension)1422 TEST_F(VkLayerTest, VertexAttributeDivisorExtension) {
1423     TEST_DESCRIPTION("Test VUIDs added with VK_EXT_vertex_attribute_divisor extension.");
1424 
1425     bool inst_ext = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1426     if (inst_ext) {
1427         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1428         ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1429     }
1430     if (inst_ext && DeviceExtensionSupported(gpu(), nullptr, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
1431         m_device_extension_names.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
1432     } else {
1433         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
1434         return;
1435     }
1436 
1437     VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vadf = {};
1438     vadf.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
1439     vadf.vertexAttributeInstanceRateDivisor = VK_TRUE;
1440     vadf.vertexAttributeInstanceRateZeroDivisor = VK_TRUE;
1441 
1442     VkPhysicalDeviceFeatures2 pd_features2 = {};
1443     pd_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
1444     pd_features2.pNext = &vadf;
1445 
1446     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &pd_features2));
1447     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1448 
1449     const VkPhysicalDeviceLimits &dev_limits = m_device->props.limits;
1450     VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT pdvad_props = {};
1451     pdvad_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
1452     VkPhysicalDeviceProperties2 pd_props2 = {};
1453     pd_props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1454     pd_props2.pNext = &pdvad_props;
1455     vkGetPhysicalDeviceProperties2(gpu(), &pd_props2);
1456 
1457     VkVertexInputBindingDivisorDescriptionEXT vibdd = {};
1458     VkPipelineVertexInputDivisorStateCreateInfoEXT pvids_ci = {};
1459     pvids_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
1460     pvids_ci.vertexBindingDivisorCount = 1;
1461     pvids_ci.pVertexBindingDivisors = &vibdd;
1462     VkVertexInputBindingDescription vibd = {};
1463     vibd.stride = 12;
1464     vibd.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
1465 
1466     if (pdvad_props.maxVertexAttribDivisor < pvids_ci.vertexBindingDivisorCount) {
1467         printf("%sThis device does not support %d vertexBindingDivisors, skipping tests\n", kSkipPrefix,
1468                pvids_ci.vertexBindingDivisorCount);
1469         return;
1470     }
1471 
1472     using std::vector;
1473     struct TestCase {
1474         uint32_t div_binding;
1475         uint32_t div_divisor;
1476         uint32_t desc_binding;
1477         VkVertexInputRate desc_rate;
1478         vector<std::string> vuids;
1479     };
1480 
1481     // clang-format off
1482     vector<TestCase> test_cases = {
1483         {   0,
1484             1,
1485             0,
1486             VK_VERTEX_INPUT_RATE_VERTEX,
1487             {"VUID-VkVertexInputBindingDivisorDescriptionEXT-inputRate-01871"}
1488         },
1489         {   dev_limits.maxVertexInputBindings + 1,
1490             1,
1491             0,
1492             VK_VERTEX_INPUT_RATE_INSTANCE,
1493             {"VUID-VkVertexInputBindingDivisorDescriptionEXT-binding-01869",
1494              "VUID-VkVertexInputBindingDivisorDescriptionEXT-inputRate-01871"}
1495         }
1496     };
1497 
1498     if (UINT32_MAX != pdvad_props.maxVertexAttribDivisor) {  // Can't test overflow if maxVAD is UINT32_MAX
1499         test_cases.push_back(
1500             {   0,
1501                 pdvad_props.maxVertexAttribDivisor + 1,
1502                 0,
1503                 VK_VERTEX_INPUT_RATE_INSTANCE,
1504                 {"VUID-VkVertexInputBindingDivisorDescriptionEXT-divisor-01870"}
1505             } );
1506     }
1507     // clang-format on
1508 
1509     for (const auto &test_case : test_cases) {
1510         const auto bad_divisor_state = [&test_case, &vibdd, &pvids_ci, &vibd](CreatePipelineHelper &helper) {
1511             vibdd.binding = test_case.div_binding;
1512             vibdd.divisor = test_case.div_divisor;
1513             vibd.binding = test_case.desc_binding;
1514             vibd.inputRate = test_case.desc_rate;
1515             helper.vi_ci_.pNext = &pvids_ci;
1516             helper.vi_ci_.vertexBindingDescriptionCount = 1;
1517             helper.vi_ci_.pVertexBindingDescriptions = &vibd;
1518         };
1519         CreatePipelineHelper::OneshotTest(*this, bad_divisor_state, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids);
1520     }
1521 }
1522 
TEST_F(VkLayerTest,VertexAttributeDivisorDisabled)1523 TEST_F(VkLayerTest, VertexAttributeDivisorDisabled) {
1524     TEST_DESCRIPTION("Test instance divisor feature disabled for VK_EXT_vertex_attribute_divisor extension.");
1525 
1526     bool inst_ext = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1527     if (inst_ext) {
1528         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1529         ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1530     }
1531     if (inst_ext && DeviceExtensionSupported(gpu(), nullptr, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
1532         m_device_extension_names.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
1533     } else {
1534         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
1535         return;
1536     }
1537 
1538     VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vadf = {};
1539     vadf.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
1540     vadf.vertexAttributeInstanceRateDivisor = VK_FALSE;
1541     vadf.vertexAttributeInstanceRateZeroDivisor = VK_FALSE;
1542     VkPhysicalDeviceFeatures2 pd_features2 = {};
1543     pd_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
1544     pd_features2.pNext = &vadf;
1545 
1546     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &pd_features2));
1547     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1548 
1549     VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT pdvad_props = {};
1550     pdvad_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
1551     VkPhysicalDeviceProperties2 pd_props2 = {};
1552     pd_props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1553     pd_props2.pNext = &pdvad_props;
1554     vkGetPhysicalDeviceProperties2(gpu(), &pd_props2);
1555 
1556     VkVertexInputBindingDivisorDescriptionEXT vibdd = {};
1557     vibdd.binding = 0;
1558     vibdd.divisor = 2;
1559     VkPipelineVertexInputDivisorStateCreateInfoEXT pvids_ci = {};
1560     pvids_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
1561     pvids_ci.vertexBindingDivisorCount = 1;
1562     pvids_ci.pVertexBindingDivisors = &vibdd;
1563     VkVertexInputBindingDescription vibd = {};
1564     vibd.binding = vibdd.binding;
1565     vibd.stride = 12;
1566     vibd.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
1567 
1568     if (pdvad_props.maxVertexAttribDivisor < pvids_ci.vertexBindingDivisorCount) {
1569         printf("%sThis device does not support %d vertexBindingDivisors, skipping tests\n", kSkipPrefix,
1570                pvids_ci.vertexBindingDivisorCount);
1571         return;
1572     }
1573 
1574     const auto instance_rate = [&pvids_ci, &vibd](CreatePipelineHelper &helper) {
1575         helper.vi_ci_.pNext = &pvids_ci;
1576         helper.vi_ci_.vertexBindingDescriptionCount = 1;
1577         helper.vi_ci_.pVertexBindingDescriptions = &vibd;
1578     };
1579     CreatePipelineHelper::OneshotTest(*this, instance_rate, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1580                                       "VUID-VkVertexInputBindingDivisorDescriptionEXT-vertexAttributeInstanceRateDivisor-02229");
1581 }
1582 
TEST_F(VkLayerTest,VertexAttributeDivisorInstanceRateZero)1583 TEST_F(VkLayerTest, VertexAttributeDivisorInstanceRateZero) {
1584     TEST_DESCRIPTION("Test instanceRateZero feature of VK_EXT_vertex_attribute_divisor extension.");
1585 
1586     bool inst_ext = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1587     if (inst_ext) {
1588         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1589         ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1590     }
1591     if (inst_ext && DeviceExtensionSupported(gpu(), nullptr, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
1592         m_device_extension_names.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
1593     } else {
1594         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
1595         return;
1596     }
1597 
1598     VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vadf = {};
1599     vadf.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
1600     vadf.vertexAttributeInstanceRateDivisor = VK_TRUE;
1601     vadf.vertexAttributeInstanceRateZeroDivisor = VK_FALSE;
1602     VkPhysicalDeviceFeatures2 pd_features2 = {};
1603     pd_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
1604     pd_features2.pNext = &vadf;
1605 
1606     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &pd_features2));
1607     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1608 
1609     VkVertexInputBindingDivisorDescriptionEXT vibdd = {};
1610     vibdd.binding = 0;
1611     vibdd.divisor = 0;
1612     VkPipelineVertexInputDivisorStateCreateInfoEXT pvids_ci = {};
1613     pvids_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
1614     pvids_ci.vertexBindingDivisorCount = 1;
1615     pvids_ci.pVertexBindingDivisors = &vibdd;
1616     VkVertexInputBindingDescription vibd = {};
1617     vibd.binding = vibdd.binding;
1618     vibd.stride = 12;
1619     vibd.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE;
1620 
1621     const auto instance_rate = [&pvids_ci, &vibd](CreatePipelineHelper &helper) {
1622         helper.vi_ci_.pNext = &pvids_ci;
1623         helper.vi_ci_.vertexBindingDescriptionCount = 1;
1624         helper.vi_ci_.pVertexBindingDescriptions = &vibd;
1625     };
1626     CreatePipelineHelper::OneshotTest(
1627         *this, instance_rate, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1628         "VUID-VkVertexInputBindingDivisorDescriptionEXT-vertexAttributeInstanceRateZeroDivisor-02228");
1629 }
1630 
1631 /*// TODO : This test should be good, but needs Tess support in compiler to run
1632 TEST_F(VkLayerTest, InvalidPatchControlPoints)
1633 {
1634     // Attempt to Create Gfx Pipeline w/o a VS
1635     VkResult        err;
1636 
1637     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
1638         "Invalid Pipeline CreateInfo State: VK_PRIMITIVE_TOPOLOGY_PATCH
1639 primitive ");
1640 
1641     ASSERT_NO_FATAL_FAILURE(Init());
1642     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1643 
1644     VkDescriptorPoolSize ds_type_count = {};
1645         ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1646         ds_type_count.descriptorCount = 1;
1647 
1648     VkDescriptorPoolCreateInfo ds_pool_ci = {};
1649         ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
1650         ds_pool_ci.pNext = NULL;
1651         ds_pool_ci.poolSizeCount = 1;
1652         ds_pool_ci.pPoolSizes = &ds_type_count;
1653 
1654     VkDescriptorPool ds_pool;
1655     err = vkCreateDescriptorPool(m_device->device(),
1656 VK_DESCRIPTOR_POOL_USAGE_NON_FREE, 1, &ds_pool_ci, NULL, &ds_pool);
1657     ASSERT_VK_SUCCESS(err);
1658 
1659     VkDescriptorSetLayoutBinding dsl_binding = {};
1660         dsl_binding.binding = 0;
1661         dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1662         dsl_binding.descriptorCount = 1;
1663         dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
1664         dsl_binding.pImmutableSamplers = NULL;
1665 
1666     VkDescriptorSetLayoutCreateInfo ds_layout_ci = {};
1667         ds_layout_ci.sType =
1668 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
1669         ds_layout_ci.pNext = NULL;
1670         ds_layout_ci.bindingCount = 1;
1671         ds_layout_ci.pBindings = &dsl_binding;
1672 
1673     VkDescriptorSetLayout ds_layout;
1674     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL,
1675 &ds_layout);
1676     ASSERT_VK_SUCCESS(err);
1677 
1678     VkDescriptorSet descriptorSet;
1679     err = vkAllocateDescriptorSets(m_device->device(), ds_pool,
1680 VK_DESCRIPTOR_SET_USAGE_NON_FREE, 1, &ds_layout, &descriptorSet);
1681     ASSERT_VK_SUCCESS(err);
1682 
1683     VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
1684         pipeline_layout_ci.sType =
1685 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
1686         pipeline_layout_ci.pNext = NULL;
1687         pipeline_layout_ci.setLayoutCount = 1;
1688         pipeline_layout_ci.pSetLayouts = &ds_layout;
1689 
1690     VkPipelineLayout pipeline_layout;
1691     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL,
1692 &pipeline_layout);
1693     ASSERT_VK_SUCCESS(err);
1694 
1695     VkPipelineShaderStageCreateInfo shaderStages[3];
1696     memset(&shaderStages, 0, 3 * sizeof(VkPipelineShaderStageCreateInfo));
1697 
1698     VkShaderObj vs(m_device,bindStateVertShaderText,VK_SHADER_STAGE_VERTEX_BIT,
1699 this);
1700     // Just using VS txt for Tess shaders as we don't care about functionality
1701     VkShaderObj
1702 tc(m_device,bindStateVertShaderText,VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1703 this);
1704     VkShaderObj
1705 te(m_device,bindStateVertShaderText,VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1706 this);
1707 
1708     shaderStages[0].sType  =
1709 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1710     shaderStages[0].stage  = VK_SHADER_STAGE_VERTEX_BIT;
1711     shaderStages[0].shader = vs.handle();
1712     shaderStages[1].sType  =
1713 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1714     shaderStages[1].stage  = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
1715     shaderStages[1].shader = tc.handle();
1716     shaderStages[2].sType  =
1717 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1718     shaderStages[2].stage  = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
1719     shaderStages[2].shader = te.handle();
1720 
1721     VkPipelineInputAssemblyStateCreateInfo iaCI = {};
1722         iaCI.sType =
1723 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1724         iaCI.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
1725 
1726     VkPipelineTessellationStateCreateInfo tsCI = {};
1727         tsCI.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
1728         tsCI.patchControlPoints = 0; // This will cause an error
1729 
1730     VkGraphicsPipelineCreateInfo gp_ci = {};
1731         gp_ci.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1732         gp_ci.pNext = NULL;
1733         gp_ci.stageCount = 3;
1734         gp_ci.pStages = shaderStages;
1735         gp_ci.pVertexInputState = NULL;
1736         gp_ci.pInputAssemblyState = &iaCI;
1737         gp_ci.pTessellationState = &tsCI;
1738         gp_ci.pViewportState = NULL;
1739         gp_ci.pRasterizationState = NULL;
1740         gp_ci.pMultisampleState = NULL;
1741         gp_ci.pDepthStencilState = NULL;
1742         gp_ci.pColorBlendState = NULL;
1743         gp_ci.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
1744         gp_ci.layout = pipeline_layout;
1745         gp_ci.renderPass = renderPass();
1746 
1747     VkPipelineCacheCreateInfo pc_ci = {};
1748         pc_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
1749         pc_ci.pNext = NULL;
1750         pc_ci.initialSize = 0;
1751         pc_ci.initialData = 0;
1752         pc_ci.maxSize = 0;
1753 
1754     VkPipeline pipeline;
1755     VkPipelineCache pipelineCache;
1756 
1757     err = vkCreatePipelineCache(m_device->device(), &pc_ci, NULL,
1758 &pipelineCache);
1759     ASSERT_VK_SUCCESS(err);
1760     err = vkCreateGraphicsPipelines(m_device->device(), pipelineCache, 1,
1761 &gp_ci, NULL, &pipeline);
1762 
1763     m_errorMonitor->VerifyFound();
1764 
1765     vkDestroyPipelineCache(m_device->device(), pipelineCache, NULL);
1766     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);
1767     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, NULL);
1768     vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL);
1769 }
1770 */
1771 
TEST_F(VkLayerTest,PSOViewportStateTests)1772 TEST_F(VkLayerTest, PSOViewportStateTests) {
1773     TEST_DESCRIPTION("Test VkPipelineViewportStateCreateInfo viewport and scissor count validation for non-multiViewport");
1774 
1775     VkPhysicalDeviceFeatures features{};
1776     ASSERT_NO_FATAL_FAILURE(Init(&features));
1777     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1778 
1779     const auto break_vp_state = [](CreatePipelineHelper &helper) {
1780         helper.rs_state_ci_.rasterizerDiscardEnable = VK_FALSE;
1781         helper.gp_ci_.pViewportState = nullptr;
1782     };
1783     CreatePipelineHelper::OneshotTest(*this, break_vp_state, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1784                                       "VUID-VkGraphicsPipelineCreateInfo-rasterizerDiscardEnable-00750");
1785 
1786     VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f};
1787     VkViewport viewports[] = {viewport, viewport};
1788     VkRect2D scissor = {{0, 0}, {64, 64}};
1789     VkRect2D scissors[] = {scissor, scissor};
1790 
1791     // test viewport and scissor arrays
1792     using std::vector;
1793     struct TestCase {
1794         uint32_t viewport_count;
1795         VkViewport *viewports;
1796         uint32_t scissor_count;
1797         VkRect2D *scissors;
1798 
1799         vector<std::string> vuids;
1800     };
1801 
1802     vector<TestCase> test_cases = {
1803         {0,
1804          viewports,
1805          1,
1806          scissors,
1807          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
1808           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1809         {2,
1810          viewports,
1811          1,
1812          scissors,
1813          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
1814           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1815         {1,
1816          viewports,
1817          0,
1818          scissors,
1819          {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
1820           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1821         {1,
1822          viewports,
1823          2,
1824          scissors,
1825          {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
1826           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1827         {0,
1828          viewports,
1829          0,
1830          scissors,
1831          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
1832           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}},
1833         {2,
1834          viewports,
1835          2,
1836          scissors,
1837          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
1838           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}},
1839         {0,
1840          viewports,
1841          2,
1842          scissors,
1843          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
1844           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1845         {2,
1846          viewports,
1847          0,
1848          scissors,
1849          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
1850           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1851         {1, nullptr, 1, scissors, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747"}},
1852         {1, viewports, 1, nullptr, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}},
1853         {1,
1854          nullptr,
1855          1,
1856          nullptr,
1857          {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}},
1858         {2,
1859          nullptr,
1860          3,
1861          nullptr,
1862          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
1863           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747",
1864           "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}},
1865         {0,
1866          nullptr,
1867          0,
1868          nullptr,
1869          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
1870           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}},
1871     };
1872 
1873     for (const auto &test_case : test_cases) {
1874         const auto break_vp = [&test_case](CreatePipelineHelper &helper) {
1875             helper.vp_state_ci_.viewportCount = test_case.viewport_count;
1876             helper.vp_state_ci_.pViewports = test_case.viewports;
1877             helper.vp_state_ci_.scissorCount = test_case.scissor_count;
1878             helper.vp_state_ci_.pScissors = test_case.scissors;
1879         };
1880         CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids);
1881     }
1882 
1883     vector<TestCase> dyn_test_cases = {
1884         {0,
1885          viewports,
1886          1,
1887          scissors,
1888          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
1889           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1890         {2,
1891          viewports,
1892          1,
1893          scissors,
1894          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
1895           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1896         {1,
1897          viewports,
1898          0,
1899          scissors,
1900          {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
1901           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1902         {1,
1903          viewports,
1904          2,
1905          scissors,
1906          {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
1907           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1908         {0,
1909          viewports,
1910          0,
1911          scissors,
1912          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
1913           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}},
1914         {2,
1915          viewports,
1916          2,
1917          scissors,
1918          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
1919           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}},
1920         {0,
1921          viewports,
1922          2,
1923          scissors,
1924          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
1925           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1926         {2,
1927          viewports,
1928          0,
1929          scissors,
1930          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
1931           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1932         {2,
1933          nullptr,
1934          3,
1935          nullptr,
1936          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216", "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217",
1937           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
1938         {0,
1939          nullptr,
1940          0,
1941          nullptr,
1942          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01216",
1943           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01217"}},
1944     };
1945 
1946     const VkDynamicState dyn_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
1947 
1948     for (const auto &test_case : dyn_test_cases) {
1949         const auto break_vp = [&](CreatePipelineHelper &helper) {
1950             VkPipelineDynamicStateCreateInfo dyn_state_ci = {};
1951             dyn_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1952             dyn_state_ci.dynamicStateCount = size(dyn_states);
1953             dyn_state_ci.pDynamicStates = dyn_states;
1954             helper.dyn_state_ci_ = dyn_state_ci;
1955 
1956             helper.vp_state_ci_.viewportCount = test_case.viewport_count;
1957             helper.vp_state_ci_.pViewports = test_case.viewports;
1958             helper.vp_state_ci_.scissorCount = test_case.scissor_count;
1959             helper.vp_state_ci_.pScissors = test_case.scissors;
1960         };
1961         CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids);
1962     }
1963 }
1964 
1965 // Set Extension dynamic states without enabling the required Extensions.
TEST_F(VkLayerTest,ExtensionDynamicStatesSetWOExtensionEnabled)1966 TEST_F(VkLayerTest, ExtensionDynamicStatesSetWOExtensionEnabled) {
1967     TEST_DESCRIPTION("Create a graphics pipeline with Extension dynamic states without enabling the required Extensions.");
1968 
1969     ASSERT_NO_FATAL_FAILURE(Init());
1970     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1971 
1972     using std::vector;
1973     struct TestCase {
1974         uint32_t dynamic_state_count;
1975         VkDynamicState dynamic_state;
1976 
1977         char const *errmsg;
1978     };
1979 
1980     vector<TestCase> dyn_test_cases = {
1981         {1, VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV,
1982          "contains VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV, but VK_NV_clip_space_w_scaling"},
1983         {1, VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT,
1984          "contains VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT, but VK_EXT_discard_rectangles"},
1985         {1, VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT, "contains VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT, but VK_EXT_sample_locations"},
1986     };
1987 
1988     for (const auto &test_case : dyn_test_cases) {
1989         VkDynamicState state[1];
1990         state[0] = test_case.dynamic_state;
1991         const auto break_vp = [&](CreatePipelineHelper &helper) {
1992             VkPipelineDynamicStateCreateInfo dyn_state_ci = {};
1993             dyn_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1994             dyn_state_ci.dynamicStateCount = test_case.dynamic_state_count;
1995             dyn_state_ci.pDynamicStates = state;
1996             helper.dyn_state_ci_ = dyn_state_ci;
1997         };
1998         CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.errmsg);
1999     }
2000 }
2001 
TEST_F(VkLayerTest,PSOViewportStateMultiViewportTests)2002 TEST_F(VkLayerTest, PSOViewportStateMultiViewportTests) {
2003     TEST_DESCRIPTION("Test VkPipelineViewportStateCreateInfo viewport and scissor count validation for multiViewport feature");
2004 
2005     ASSERT_NO_FATAL_FAILURE(Init());  // enables all supported features
2006 
2007     if (!m_device->phy().features().multiViewport) {
2008         printf("%s VkPhysicalDeviceFeatures::multiViewport is not supported -- skipping test.\n", kSkipPrefix);
2009         return;
2010     }
2011     // at least 16 viewports supported from here on
2012 
2013     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2014 
2015     VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f};
2016     VkViewport viewports[] = {viewport, viewport};
2017     VkRect2D scissor = {{0, 0}, {64, 64}};
2018     VkRect2D scissors[] = {scissor, scissor};
2019 
2020     using std::vector;
2021     struct TestCase {
2022         uint32_t viewport_count;
2023         VkViewport *viewports;
2024         uint32_t scissor_count;
2025         VkRect2D *scissors;
2026 
2027         vector<std::string> vuids;
2028     };
2029 
2030     vector<TestCase> test_cases = {
2031         {0,
2032          viewports,
2033          2,
2034          scissors,
2035          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength",
2036           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
2037         {2,
2038          viewports,
2039          0,
2040          scissors,
2041          {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength",
2042           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
2043         {0,
2044          viewports,
2045          0,
2046          scissors,
2047          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength",
2048           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength"}},
2049         {2, nullptr, 2, scissors, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747"}},
2050         {2, viewports, 2, nullptr, {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}},
2051         {2,
2052          nullptr,
2053          2,
2054          nullptr,
2055          {"VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}},
2056         {0,
2057          nullptr,
2058          0,
2059          nullptr,
2060          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength",
2061           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength"}},
2062     };
2063 
2064     const auto max_viewports = m_device->phy().properties().limits.maxViewports;
2065     const bool max_viewports_maxxed = max_viewports == std::numeric_limits<decltype(max_viewports)>::max();
2066     if (max_viewports_maxxed) {
2067         printf("%s VkPhysicalDeviceLimits::maxViewports is UINT32_MAX -- skipping part of test requiring to exceed maxViewports.\n",
2068                kSkipPrefix);
2069     } else {
2070         const auto too_much_viewports = max_viewports + 1;
2071         // avoid potentially big allocations by using only nullptr
2072         test_cases.push_back({too_much_viewports,
2073                               nullptr,
2074                               2,
2075                               scissors,
2076                               {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218",
2077                                "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220",
2078                                "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747"}});
2079         test_cases.push_back({2,
2080                               viewports,
2081                               too_much_viewports,
2082                               nullptr,
2083                               {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219",
2084                                "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220",
2085                                "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}});
2086         test_cases.push_back(
2087             {too_much_viewports,
2088              nullptr,
2089              too_much_viewports,
2090              nullptr,
2091              {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218",
2092               "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219", "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00747",
2093               "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00748"}});
2094     }
2095 
2096     for (const auto &test_case : test_cases) {
2097         const auto break_vp = [&test_case](CreatePipelineHelper &helper) {
2098             helper.vp_state_ci_.viewportCount = test_case.viewport_count;
2099             helper.vp_state_ci_.pViewports = test_case.viewports;
2100             helper.vp_state_ci_.scissorCount = test_case.scissor_count;
2101             helper.vp_state_ci_.pScissors = test_case.scissors;
2102         };
2103         CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids);
2104     }
2105 
2106     vector<TestCase> dyn_test_cases = {
2107         {0,
2108          viewports,
2109          2,
2110          scissors,
2111          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength",
2112           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
2113         {2,
2114          viewports,
2115          0,
2116          scissors,
2117          {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength",
2118           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}},
2119         {0,
2120          viewports,
2121          0,
2122          scissors,
2123          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength",
2124           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength"}},
2125         {0,
2126          nullptr,
2127          0,
2128          nullptr,
2129          {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-arraylength",
2130           "VUID-VkPipelineViewportStateCreateInfo-scissorCount-arraylength"}},
2131     };
2132 
2133     if (!max_viewports_maxxed) {
2134         const auto too_much_viewports = max_viewports + 1;
2135         // avoid potentially big allocations by using only nullptr
2136         dyn_test_cases.push_back({too_much_viewports,
2137                                   nullptr,
2138                                   2,
2139                                   scissors,
2140                                   {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218",
2141                                    "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}});
2142         dyn_test_cases.push_back({2,
2143                                   viewports,
2144                                   too_much_viewports,
2145                                   nullptr,
2146                                   {"VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219",
2147                                    "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01220"}});
2148         dyn_test_cases.push_back({too_much_viewports,
2149                                   nullptr,
2150                                   too_much_viewports,
2151                                   nullptr,
2152                                   {"VUID-VkPipelineViewportStateCreateInfo-viewportCount-01218",
2153                                    "VUID-VkPipelineViewportStateCreateInfo-scissorCount-01219"}});
2154     }
2155 
2156     const VkDynamicState dyn_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
2157 
2158     for (const auto &test_case : dyn_test_cases) {
2159         const auto break_vp = [&](CreatePipelineHelper &helper) {
2160             VkPipelineDynamicStateCreateInfo dyn_state_ci = {};
2161             dyn_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
2162             dyn_state_ci.dynamicStateCount = size(dyn_states);
2163             dyn_state_ci.pDynamicStates = dyn_states;
2164             helper.dyn_state_ci_ = dyn_state_ci;
2165 
2166             helper.vp_state_ci_.viewportCount = test_case.viewport_count;
2167             helper.vp_state_ci_.pViewports = test_case.viewports;
2168             helper.vp_state_ci_.scissorCount = test_case.scissor_count;
2169             helper.vp_state_ci_.pScissors = test_case.scissors;
2170         };
2171         CreatePipelineHelper::OneshotTest(*this, break_vp, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuids);
2172     }
2173 }
2174 
TEST_F(VkLayerTest,DynViewportAndScissorUndefinedDrawState)2175 TEST_F(VkLayerTest, DynViewportAndScissorUndefinedDrawState) {
2176     TEST_DESCRIPTION("Test viewport and scissor dynamic state that is not set before draw");
2177 
2178     ASSERT_NO_FATAL_FAILURE(Init());
2179 
2180     // TODO: should also test on !multiViewport
2181     if (!m_device->phy().features().multiViewport) {
2182         printf("%s Device does not support multiple viewports/scissors; skipped.\n", kSkipPrefix);
2183         return;
2184     }
2185 
2186     ASSERT_NO_FATAL_FAILURE(InitViewport());
2187     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2188 
2189     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
2190     VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
2191 
2192     const VkPipelineLayoutObj pipeline_layout(m_device);
2193 
2194     VkPipelineObj pipeline_dyn_vp(m_device);
2195     pipeline_dyn_vp.AddShader(&vs);
2196     pipeline_dyn_vp.AddShader(&fs);
2197     pipeline_dyn_vp.AddDefaultColorAttachment();
2198     pipeline_dyn_vp.MakeDynamic(VK_DYNAMIC_STATE_VIEWPORT);
2199     pipeline_dyn_vp.SetScissor(m_scissors);
2200     ASSERT_VK_SUCCESS(pipeline_dyn_vp.CreateVKPipeline(pipeline_layout.handle(), m_renderPass));
2201 
2202     VkPipelineObj pipeline_dyn_sc(m_device);
2203     pipeline_dyn_sc.AddShader(&vs);
2204     pipeline_dyn_sc.AddShader(&fs);
2205     pipeline_dyn_sc.AddDefaultColorAttachment();
2206     pipeline_dyn_sc.SetViewport(m_viewports);
2207     pipeline_dyn_sc.MakeDynamic(VK_DYNAMIC_STATE_SCISSOR);
2208     ASSERT_VK_SUCCESS(pipeline_dyn_sc.CreateVKPipeline(pipeline_layout.handle(), m_renderPass));
2209 
2210     m_commandBuffer->begin();
2211     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
2212 
2213     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
2214                                          "Dynamic viewport(s) 0 are used by pipeline state object, ");
2215     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_dyn_vp.handle());
2216     vkCmdSetViewport(m_commandBuffer->handle(), 1, 1,
2217                      &m_viewports[0]);  // Forgetting to set needed 0th viewport (PSO viewportCount == 1)
2218     m_commandBuffer->Draw(1, 0, 0, 0);
2219     m_errorMonitor->VerifyFound();
2220 
2221     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Dynamic scissor(s) 0 are used by pipeline state object, ");
2222     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_dyn_sc.handle());
2223     vkCmdSetScissor(m_commandBuffer->handle(), 1, 1,
2224                     &m_scissors[0]);  // Forgetting to set needed 0th scissor (PSO scissorCount == 1)
2225     m_commandBuffer->Draw(1, 0, 0, 0);
2226     m_errorMonitor->VerifyFound();
2227 
2228     m_commandBuffer->EndRenderPass();
2229     m_commandBuffer->end();
2230 }
2231 
TEST_F(VkLayerTest,PSOLineWidthInvalid)2232 TEST_F(VkLayerTest, PSOLineWidthInvalid) {
2233     TEST_DESCRIPTION("Test non-1.0 lineWidth errors when pipeline is created and in vkCmdSetLineWidth");
2234     VkPhysicalDeviceFeatures features{};
2235     ASSERT_NO_FATAL_FAILURE(Init(&features));
2236     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2237 
2238     const std::vector<float> test_cases = {-1.0f, 0.0f, NearestSmaller(1.0f), NearestGreater(1.0f), NAN};
2239 
2240     // test VkPipelineRasterizationStateCreateInfo::lineWidth
2241     for (const auto test_case : test_cases) {
2242         const auto set_lineWidth = [&](CreatePipelineHelper &helper) { helper.rs_state_ci_.lineWidth = test_case; };
2243         CreatePipelineHelper::OneshotTest(*this, set_lineWidth, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2244                                           "VUID-VkGraphicsPipelineCreateInfo-pDynamicStates-00749");
2245     }
2246 
2247     // test vkCmdSetLineWidth
2248     m_commandBuffer->begin();
2249 
2250     for (const auto test_case : test_cases) {
2251         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetLineWidth-lineWidth-00788");
2252         vkCmdSetLineWidth(m_commandBuffer->handle(), test_case);
2253         m_errorMonitor->VerifyFound();
2254     }
2255 }
2256 
TEST_F(VkLayerTest,VUID_VkVertexInputBindingDescription_binding_00618)2257 TEST_F(VkLayerTest, VUID_VkVertexInputBindingDescription_binding_00618) {
2258     TEST_DESCRIPTION(
2259         "Test VUID-VkVertexInputBindingDescription-binding-00618: binding must be less than "
2260         "VkPhysicalDeviceLimits::maxVertexInputBindings");
2261 
2262     ASSERT_NO_FATAL_FAILURE(Init());
2263     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2264 
2265     // Test when binding is greater than or equal to VkPhysicalDeviceLimits::maxVertexInputBindings.
2266     VkVertexInputBindingDescription vertex_input_binding_description{};
2267     vertex_input_binding_description.binding = m_device->props.limits.maxVertexInputBindings;
2268 
2269     const auto set_binding = [&](CreatePipelineHelper &helper) {
2270         helper.vi_ci_.pVertexBindingDescriptions = &vertex_input_binding_description;
2271         helper.vi_ci_.vertexBindingDescriptionCount = 1;
2272     };
2273     CreatePipelineHelper::OneshotTest(*this, set_binding, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2274                                       "VUID-VkVertexInputBindingDescription-binding-00618");
2275 }
2276 
TEST_F(VkLayerTest,VUID_VkVertexInputBindingDescription_stride_00619)2277 TEST_F(VkLayerTest, VUID_VkVertexInputBindingDescription_stride_00619) {
2278     TEST_DESCRIPTION(
2279         "Test VUID-VkVertexInputBindingDescription-stride-00619: stride must be less than or equal to "
2280         "VkPhysicalDeviceLimits::maxVertexInputBindingStride");
2281 
2282     ASSERT_NO_FATAL_FAILURE(Init());
2283     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2284 
2285     // Test when stride is greater than VkPhysicalDeviceLimits::maxVertexInputBindingStride.
2286     VkVertexInputBindingDescription vertex_input_binding_description{};
2287     vertex_input_binding_description.stride = m_device->props.limits.maxVertexInputBindingStride + 1;
2288 
2289     const auto set_binding = [&](CreatePipelineHelper &helper) {
2290         helper.vi_ci_.pVertexBindingDescriptions = &vertex_input_binding_description;
2291         helper.vi_ci_.vertexBindingDescriptionCount = 1;
2292     };
2293     CreatePipelineHelper::OneshotTest(*this, set_binding, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2294                                       "VUID-VkVertexInputBindingDescription-stride-00619");
2295 }
2296 
TEST_F(VkLayerTest,VUID_VkVertexInputAttributeDescription_location_00620)2297 TEST_F(VkLayerTest, VUID_VkVertexInputAttributeDescription_location_00620) {
2298     TEST_DESCRIPTION(
2299         "Test VUID-VkVertexInputAttributeDescription-location-00620: location must be less than "
2300         "VkPhysicalDeviceLimits::maxVertexInputAttributes");
2301 
2302     ASSERT_NO_FATAL_FAILURE(Init());
2303     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2304 
2305     // Test when location is greater than or equal to VkPhysicalDeviceLimits::maxVertexInputAttributes.
2306     VkVertexInputAttributeDescription vertex_input_attribute_description{};
2307     vertex_input_attribute_description.location = m_device->props.limits.maxVertexInputAttributes;
2308 
2309     const auto set_attribute = [&](CreatePipelineHelper &helper) {
2310         helper.vi_ci_.pVertexAttributeDescriptions = &vertex_input_attribute_description;
2311         helper.vi_ci_.vertexAttributeDescriptionCount = 1;
2312     };
2313     CreatePipelineHelper::OneshotTest(*this, set_attribute, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2314                                       vector<string>{"VUID-VkVertexInputAttributeDescription-location-00620",
2315                                                      "VUID-VkPipelineVertexInputStateCreateInfo-binding-00615"});
2316 }
2317 
TEST_F(VkLayerTest,VUID_VkVertexInputAttributeDescription_binding_00621)2318 TEST_F(VkLayerTest, VUID_VkVertexInputAttributeDescription_binding_00621) {
2319     TEST_DESCRIPTION(
2320         "Test VUID-VkVertexInputAttributeDescription-binding-00621: binding must be less than "
2321         "VkPhysicalDeviceLimits::maxVertexInputBindings");
2322 
2323     ASSERT_NO_FATAL_FAILURE(Init());
2324     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2325 
2326     // Test when binding is greater than or equal to VkPhysicalDeviceLimits::maxVertexInputBindings.
2327     VkVertexInputAttributeDescription vertex_input_attribute_description{};
2328     vertex_input_attribute_description.binding = m_device->props.limits.maxVertexInputBindings;
2329 
2330     const auto set_attribute = [&](CreatePipelineHelper &helper) {
2331         helper.vi_ci_.pVertexAttributeDescriptions = &vertex_input_attribute_description;
2332         helper.vi_ci_.vertexAttributeDescriptionCount = 1;
2333     };
2334     CreatePipelineHelper::OneshotTest(*this, set_attribute, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2335                                       vector<string>{"VUID-VkVertexInputAttributeDescription-binding-00621",
2336                                                      "VUID-VkPipelineVertexInputStateCreateInfo-binding-00615"});
2337 }
2338 
TEST_F(VkLayerTest,VUID_VkVertexInputAttributeDescription_offset_00622)2339 TEST_F(VkLayerTest, VUID_VkVertexInputAttributeDescription_offset_00622) {
2340     TEST_DESCRIPTION(
2341         "Test VUID-VkVertexInputAttributeDescription-offset-00622: offset must be less than or equal to "
2342         "VkPhysicalDeviceLimits::maxVertexInputAttributeOffset");
2343 
2344     EnableDeviceProfileLayer();
2345 
2346     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2347 
2348     uint32_t maxVertexInputAttributeOffset = 0;
2349     {
2350         VkPhysicalDeviceProperties device_props = {};
2351         vkGetPhysicalDeviceProperties(gpu(), &device_props);
2352         maxVertexInputAttributeOffset = device_props.limits.maxVertexInputAttributeOffset;
2353         if (maxVertexInputAttributeOffset == 0xFFFFFFFF) {
2354             // Attempt to artificially lower maximum offset
2355             PFN_vkSetPhysicalDeviceLimitsEXT fpvkSetPhysicalDeviceLimitsEXT =
2356                 (PFN_vkSetPhysicalDeviceLimitsEXT)vkGetInstanceProcAddr(instance(), "vkSetPhysicalDeviceLimitsEXT");
2357             if (!fpvkSetPhysicalDeviceLimitsEXT) {
2358                 printf("%s All offsets are valid & device_profile_api not found; skipped.\n", kSkipPrefix);
2359                 return;
2360             }
2361             device_props.limits.maxVertexInputAttributeOffset = device_props.limits.maxVertexInputBindingStride - 2;
2362             fpvkSetPhysicalDeviceLimitsEXT(gpu(), &device_props.limits);
2363             maxVertexInputAttributeOffset = device_props.limits.maxVertexInputAttributeOffset;
2364         }
2365     }
2366     ASSERT_NO_FATAL_FAILURE(InitState());
2367     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2368 
2369     VkVertexInputBindingDescription vertex_input_binding_description{};
2370     vertex_input_binding_description.binding = 0;
2371     vertex_input_binding_description.stride = m_device->props.limits.maxVertexInputBindingStride;
2372     vertex_input_binding_description.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
2373     // Test when offset is greater than maximum.
2374     VkVertexInputAttributeDescription vertex_input_attribute_description{};
2375     vertex_input_attribute_description.format = VK_FORMAT_R8_UNORM;
2376     vertex_input_attribute_description.offset = maxVertexInputAttributeOffset + 1;
2377 
2378     const auto set_attribute = [&](CreatePipelineHelper &helper) {
2379         helper.vi_ci_.pVertexBindingDescriptions = &vertex_input_binding_description;
2380         helper.vi_ci_.vertexBindingDescriptionCount = 1;
2381         helper.vi_ci_.pVertexAttributeDescriptions = &vertex_input_attribute_description;
2382         helper.vi_ci_.vertexAttributeDescriptionCount = 1;
2383     };
2384     CreatePipelineHelper::OneshotTest(*this, set_attribute, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2385                                       "VUID-VkVertexInputAttributeDescription-offset-00622");
2386 }
2387 
TEST_F(VkLayerTest,NumSamplesMismatch)2388 TEST_F(VkLayerTest, NumSamplesMismatch) {
2389     // Create CommandBuffer where MSAA samples doesn't match RenderPass
2390     // sampleCount
2391     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Num samples mismatch! ");
2392 
2393     ASSERT_NO_FATAL_FAILURE(Init());
2394     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2395 
2396     OneOffDescriptorSet descriptor_set(m_device, {
2397                                                      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
2398                                                  });
2399 
2400     VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {};
2401     pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
2402     pipe_ms_state_ci.pNext = NULL;
2403     pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT;
2404     pipe_ms_state_ci.sampleShadingEnable = 0;
2405     pipe_ms_state_ci.minSampleShading = 1.0;
2406     pipe_ms_state_ci.pSampleMask = NULL;
2407 
2408     const VkPipelineLayoutObj pipeline_layout(m_device, {&descriptor_set.layout_});
2409 
2410     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
2411     VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);  // We shouldn't need a fragment shader
2412     // but add it to be able to run on more devices
2413     VkPipelineObj pipe(m_device);
2414     pipe.AddShader(&vs);
2415     pipe.AddShader(&fs);
2416     pipe.AddDefaultColorAttachment();
2417     pipe.SetMSAA(&pipe_ms_state_ci);
2418 
2419     m_errorMonitor->SetUnexpectedError("VUID-VkGraphicsPipelineCreateInfo-subpass-00757");
2420     pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass());
2421 
2422     m_commandBuffer->begin();
2423     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
2424     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
2425 
2426     VkViewport viewport = {0, 0, 16, 16, 0, 1};
2427     vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
2428     VkRect2D scissor = {{0, 0}, {16, 16}};
2429     vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
2430 
2431     // Render triangle (the error should trigger on the attempt to draw).
2432     m_commandBuffer->Draw(3, 1, 0, 0);
2433 
2434     // Finalize recording of the command buffer
2435     m_commandBuffer->EndRenderPass();
2436     m_commandBuffer->end();
2437 
2438     m_errorMonitor->VerifyFound();
2439 }
2440 
TEST_F(VkLayerTest,NumBlendAttachMismatch)2441 TEST_F(VkLayerTest, NumBlendAttachMismatch) {
2442     // Create Pipeline where the number of blend attachments doesn't match the
2443     // number of color attachments.  In this case, we don't add any color
2444     // blend attachments even though we have a color attachment.
2445 
2446     ASSERT_NO_FATAL_FAILURE(Init());
2447     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2448 
2449     VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {};
2450     pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
2451     pipe_ms_state_ci.pNext = NULL;
2452     pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
2453     pipe_ms_state_ci.sampleShadingEnable = 0;
2454     pipe_ms_state_ci.minSampleShading = 1.0;
2455     pipe_ms_state_ci.pSampleMask = NULL;
2456 
2457     const auto set_MSAA = [&](CreatePipelineHelper &helper) {
2458         helper.pipe_ms_state_ci_ = pipe_ms_state_ci;
2459         helper.cb_ci_.attachmentCount = 0;
2460     };
2461     CreatePipelineHelper::OneshotTest(*this, set_MSAA, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2462                                       "VUID-VkGraphicsPipelineCreateInfo-attachmentCount-00746");
2463 }
2464 
TEST_F(VkLayerTest,CmdClearAttachmentTests)2465 TEST_F(VkLayerTest, CmdClearAttachmentTests) {
2466     TEST_DESCRIPTION("Various tests for validating usage of vkCmdClearAttachments");
2467 
2468     ASSERT_NO_FATAL_FAILURE(Init());
2469     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2470 
2471     m_commandBuffer->begin();
2472     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
2473 
2474     // Main thing we care about for this test is that the VkImage obj we're
2475     // clearing matches Color Attachment of FB
2476     //  Also pass down other dummy params to keep driver and paramchecker happy
2477     VkClearAttachment color_attachment;
2478     color_attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
2479     color_attachment.clearValue.color.float32[0] = 1.0;
2480     color_attachment.clearValue.color.float32[1] = 1.0;
2481     color_attachment.clearValue.color.float32[2] = 1.0;
2482     color_attachment.clearValue.color.float32[3] = 1.0;
2483     color_attachment.colorAttachment = 0;
2484     VkClearRect clear_rect = {{{0, 0}, {(uint32_t)m_width, (uint32_t)m_height}}, 0, 1};
2485 
2486     // Call for full-sized FB Color attachment prior to issuing a Draw
2487     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2488                                          "UNASSIGNED-CoreValidation-DrawState-ClearCmdBeforeDraw");
2489     vkCmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
2490     m_errorMonitor->VerifyFound();
2491 
2492     clear_rect.rect.extent.width = renderPassBeginInfo().renderArea.extent.width + 4;
2493     clear_rect.rect.extent.height = clear_rect.rect.extent.height / 2;
2494     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearAttachments-pRects-00016");
2495     vkCmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
2496     m_errorMonitor->VerifyFound();
2497 
2498     // baseLayer >= view layers
2499     clear_rect.rect.extent.width = (uint32_t)m_width;
2500     clear_rect.baseArrayLayer = 1;
2501     clear_rect.layerCount = 1;
2502     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearAttachments-pRects-00017");
2503     vkCmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
2504     m_errorMonitor->VerifyFound();
2505 
2506     // baseLayer + layerCount > view layers
2507     clear_rect.rect.extent.width = (uint32_t)m_width;
2508     clear_rect.baseArrayLayer = 0;
2509     clear_rect.layerCount = 2;
2510     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdClearAttachments-pRects-00017");
2511     vkCmdClearAttachments(m_commandBuffer->handle(), 1, &color_attachment, 1, &clear_rect);
2512     m_errorMonitor->VerifyFound();
2513 
2514     m_commandBuffer->EndRenderPass();
2515     m_commandBuffer->end();
2516 }
2517 
TEST_F(VkLayerTest,VtxBufferBadIndex)2518 TEST_F(VkLayerTest, VtxBufferBadIndex) {
2519     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2520                                          "UNASSIGNED-CoreValidation-DrawState-VtxIndexOutOfBounds");
2521 
2522     ASSERT_NO_FATAL_FAILURE(Init());
2523     ASSERT_NO_FATAL_FAILURE(InitViewport());
2524     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2525 
2526     VkPipelineMultisampleStateCreateInfo pipe_ms_state_ci = {};
2527     pipe_ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
2528     pipe_ms_state_ci.pNext = NULL;
2529     pipe_ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
2530     pipe_ms_state_ci.sampleShadingEnable = 0;
2531     pipe_ms_state_ci.minSampleShading = 1.0;
2532     pipe_ms_state_ci.pSampleMask = NULL;
2533 
2534     CreatePipelineHelper pipe(*this);
2535     pipe.InitInfo();
2536     pipe.pipe_ms_state_ci_ = pipe_ms_state_ci;
2537     pipe.InitState();
2538     pipe.CreateGraphicsPipeline();
2539 
2540     m_commandBuffer->begin();
2541     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
2542     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
2543     // Don't care about actual data, just need to get to draw to flag error
2544     const float vbo_data[3] = {1.f, 0.f, 1.f};
2545     VkConstantBufferObj vbo(m_device, sizeof(vbo_data), (const void *)&vbo_data, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
2546     m_commandBuffer->BindVertexBuffer(&vbo, (VkDeviceSize)0, 1);  // VBO idx 1, but no VBO in PSO
2547     m_commandBuffer->Draw(1, 0, 0, 0);
2548 
2549     m_errorMonitor->VerifyFound();
2550 
2551     m_commandBuffer->EndRenderPass();
2552     m_commandBuffer->end();
2553 }
2554 
TEST_F(VkLayerTest,InvalidVertexBindingDescriptions)2555 TEST_F(VkLayerTest, InvalidVertexBindingDescriptions) {
2556     TEST_DESCRIPTION(
2557         "Attempt to create a graphics pipeline where:"
2558         "1) count of vertex bindings exceeds device's maxVertexInputBindings limit"
2559         "2) requested bindings include a duplicate binding value");
2560 
2561     ASSERT_NO_FATAL_FAILURE(Init());
2562     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2563 
2564     const uint32_t binding_count = m_device->props.limits.maxVertexInputBindings + 1;
2565 
2566     std::vector<VkVertexInputBindingDescription> input_bindings(binding_count);
2567     for (uint32_t i = 0; i < binding_count; ++i) {
2568         input_bindings[i].binding = i;
2569         input_bindings[i].stride = 4;
2570         input_bindings[i].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
2571     }
2572     // Let the last binding description use same binding as the first one
2573     input_bindings[binding_count - 1].binding = 0;
2574 
2575     VkVertexInputAttributeDescription input_attrib;
2576     input_attrib.binding = 0;
2577     input_attrib.location = 0;
2578     input_attrib.format = VK_FORMAT_R32G32B32_SFLOAT;
2579     input_attrib.offset = 0;
2580 
2581     const auto set_Info = [&](CreatePipelineHelper &helper) {
2582         helper.vi_ci_.pVertexBindingDescriptions = input_bindings.data();
2583         helper.vi_ci_.vertexBindingDescriptionCount = binding_count;
2584         helper.vi_ci_.pVertexAttributeDescriptions = &input_attrib;
2585         helper.vi_ci_.vertexAttributeDescriptionCount = 1;
2586     };
2587     CreatePipelineHelper::OneshotTest(
2588         *this, set_Info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2589         vector<string>{"VUID-VkPipelineVertexInputStateCreateInfo-vertexBindingDescriptionCount-00613",
2590                        "VUID-VkPipelineVertexInputStateCreateInfo-pVertexBindingDescriptions-00616"});
2591 }
2592 
TEST_F(VkLayerTest,InvalidVertexAttributeDescriptions)2593 TEST_F(VkLayerTest, InvalidVertexAttributeDescriptions) {
2594     TEST_DESCRIPTION(
2595         "Attempt to create a graphics pipeline where:"
2596         "1) count of vertex attributes exceeds device's maxVertexInputAttributes limit"
2597         "2) requested location include a duplicate location value"
2598         "3) binding used by one attribute is not defined by a binding description");
2599 
2600     ASSERT_NO_FATAL_FAILURE(Init());
2601     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2602 
2603     VkVertexInputBindingDescription input_binding;
2604     input_binding.binding = 0;
2605     input_binding.stride = 4;
2606     input_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
2607 
2608     const uint32_t attribute_count = m_device->props.limits.maxVertexInputAttributes + 1;
2609     std::vector<VkVertexInputAttributeDescription> input_attribs(attribute_count);
2610     for (uint32_t i = 0; i < attribute_count; ++i) {
2611         input_attribs[i].binding = 0;
2612         input_attribs[i].location = i;
2613         input_attribs[i].format = VK_FORMAT_R32G32B32_SFLOAT;
2614         input_attribs[i].offset = 0;
2615     }
2616     // Let the last input_attribs description use same location as the first one
2617     input_attribs[attribute_count - 1].location = 0;
2618     // Let the last input_attribs description use binding which is not defined
2619     input_attribs[attribute_count - 1].binding = 1;
2620 
2621     const auto set_Info = [&](CreatePipelineHelper &helper) {
2622         helper.vi_ci_.pVertexBindingDescriptions = &input_binding;
2623         helper.vi_ci_.vertexBindingDescriptionCount = 1;
2624         helper.vi_ci_.pVertexAttributeDescriptions = input_attribs.data();
2625         helper.vi_ci_.vertexAttributeDescriptionCount = attribute_count;
2626     };
2627     CreatePipelineHelper::OneshotTest(
2628         *this, set_Info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2629         vector<string>{"VUID-VkPipelineVertexInputStateCreateInfo-vertexAttributeDescriptionCount-00614",
2630                        "VUID-VkPipelineVertexInputStateCreateInfo-binding-00615",
2631                        "VUID-VkPipelineVertexInputStateCreateInfo-pVertexAttributeDescriptions-00617"});
2632 }
2633 
TEST_F(VkLayerTest,ColorBlendInvalidLogicOp)2634 TEST_F(VkLayerTest, ColorBlendInvalidLogicOp) {
2635     TEST_DESCRIPTION("Attempt to use invalid VkPipelineColorBlendStateCreateInfo::logicOp value.");
2636 
2637     ASSERT_NO_FATAL_FAILURE(Init());  // enables all supported features
2638     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2639 
2640     if (!m_device->phy().features().logicOp) {
2641         printf("%s Device does not support logicOp feature; skipped.\n", kSkipPrefix);
2642         return;
2643     }
2644 
2645     const auto set_shading_enable = [](CreatePipelineHelper &helper) {
2646         helper.cb_ci_.logicOpEnable = VK_TRUE;
2647         helper.cb_ci_.logicOp = static_cast<VkLogicOp>(VK_LOGIC_OP_END_RANGE + 1);  // invalid logicOp to be tested
2648     };
2649     CreatePipelineHelper::OneshotTest(*this, set_shading_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2650                                       "VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00607");
2651 }
2652 
TEST_F(VkLayerTest,ColorBlendUnsupportedLogicOp)2653 TEST_F(VkLayerTest, ColorBlendUnsupportedLogicOp) {
2654     TEST_DESCRIPTION("Attempt enabling VkPipelineColorBlendStateCreateInfo::logicOpEnable when logicOp feature is disabled.");
2655 
2656     VkPhysicalDeviceFeatures features{};
2657     ASSERT_NO_FATAL_FAILURE(Init(&features));
2658     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2659 
2660     const auto set_shading_enable = [](CreatePipelineHelper &helper) { helper.cb_ci_.logicOpEnable = VK_TRUE; };
2661     CreatePipelineHelper::OneshotTest(*this, set_shading_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2662                                       "VUID-VkPipelineColorBlendStateCreateInfo-logicOpEnable-00606");
2663 }
2664 
TEST_F(VkLayerTest,ColorBlendUnsupportedDualSourceBlend)2665 TEST_F(VkLayerTest, ColorBlendUnsupportedDualSourceBlend) {
2666     TEST_DESCRIPTION("Attempt to use dual-source blending when dualSrcBlend feature is disabled.");
2667 
2668     VkPhysicalDeviceFeatures features{};
2669     ASSERT_NO_FATAL_FAILURE(Init(&features));
2670     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2671 
2672     VkPipelineColorBlendAttachmentState cb_attachments = {};
2673 
2674     const auto set_dsb_src_color_enable = [&](CreatePipelineHelper &helper) { helper.cb_attachments_ = cb_attachments; };
2675 
2676     cb_attachments.blendEnable = VK_TRUE;
2677     cb_attachments.srcColorBlendFactor = VK_BLEND_FACTOR_SRC1_COLOR;  // bad!
2678     cb_attachments.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
2679     cb_attachments.colorBlendOp = VK_BLEND_OP_ADD;
2680     cb_attachments.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
2681     cb_attachments.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
2682     cb_attachments.alphaBlendOp = VK_BLEND_OP_ADD;
2683     CreatePipelineHelper::OneshotTest(*this, set_dsb_src_color_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2684                                       "VUID-VkPipelineColorBlendAttachmentState-srcColorBlendFactor-00608");
2685 
2686     cb_attachments.blendEnable = VK_TRUE;
2687     cb_attachments.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR;
2688     cb_attachments.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;  // bad
2689     cb_attachments.colorBlendOp = VK_BLEND_OP_ADD;
2690     cb_attachments.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
2691     cb_attachments.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
2692     cb_attachments.alphaBlendOp = VK_BLEND_OP_ADD;
2693     CreatePipelineHelper::OneshotTest(*this, set_dsb_src_color_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2694                                       "VUID-VkPipelineColorBlendAttachmentState-dstColorBlendFactor-00609");
2695 
2696     cb_attachments.blendEnable = VK_TRUE;
2697     cb_attachments.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR;
2698     cb_attachments.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
2699     cb_attachments.colorBlendOp = VK_BLEND_OP_ADD;
2700     cb_attachments.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC1_ALPHA;  // bad
2701     cb_attachments.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
2702     cb_attachments.alphaBlendOp = VK_BLEND_OP_ADD;
2703     CreatePipelineHelper::OneshotTest(*this, set_dsb_src_color_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2704                                       "VUID-VkPipelineColorBlendAttachmentState-srcAlphaBlendFactor-00610");
2705 
2706     cb_attachments.blendEnable = VK_TRUE;
2707     cb_attachments.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR;
2708     cb_attachments.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
2709     cb_attachments.colorBlendOp = VK_BLEND_OP_ADD;
2710     cb_attachments.srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
2711     cb_attachments.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;  // bad!
2712     cb_attachments.alphaBlendOp = VK_BLEND_OP_ADD;
2713     CreatePipelineHelper::OneshotTest(*this, set_dsb_src_color_enable, VK_DEBUG_REPORT_ERROR_BIT_EXT,
2714                                       "VUID-VkPipelineColorBlendAttachmentState-dstAlphaBlendFactor-00611");
2715 }
2716 
TEST_F(VkLayerTest,InvalidSPIRVCodeSize)2717 TEST_F(VkLayerTest, InvalidSPIRVCodeSize) {
2718     TEST_DESCRIPTION("Test that errors are produced for a spirv modules with invalid code sizes");
2719 
2720     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Invalid SPIR-V header");
2721 
2722     ASSERT_NO_FATAL_FAILURE(Init());
2723     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2724 
2725     VkShaderModule module;
2726     VkShaderModuleCreateInfo moduleCreateInfo;
2727     struct icd_spv_header spv;
2728 
2729     spv.magic = ICD_SPV_MAGIC;
2730     spv.version = ICD_SPV_VERSION;
2731     spv.gen_magic = 0;
2732 
2733     moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
2734     moduleCreateInfo.pNext = NULL;
2735     moduleCreateInfo.pCode = (const uint32_t *)&spv;
2736     moduleCreateInfo.codeSize = 4;
2737     moduleCreateInfo.flags = 0;
2738     vkCreateShaderModule(m_device->device(), &moduleCreateInfo, NULL, &module);
2739 
2740     m_errorMonitor->VerifyFound();
2741 
2742     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkShaderModuleCreateInfo-pCode-01376");
2743     std::vector<unsigned int> shader;
2744     VkShaderModuleCreateInfo module_create_info;
2745     VkShaderModule shader_module;
2746     module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
2747     module_create_info.pNext = NULL;
2748     this->GLSLtoSPV(VK_SHADER_STAGE_VERTEX_BIT, bindStateVertShaderText, shader);
2749     module_create_info.pCode = shader.data();
2750     // Introduce failure by making codeSize a non-multiple of 4
2751     module_create_info.codeSize = shader.size() * sizeof(unsigned int) - 1;
2752     module_create_info.flags = 0;
2753     vkCreateShaderModule(m_device->handle(), &module_create_info, NULL, &shader_module);
2754 
2755     m_errorMonitor->VerifyFound();
2756 }
2757 
TEST_F(VkLayerTest,InvalidSPIRVMagic)2758 TEST_F(VkLayerTest, InvalidSPIRVMagic) {
2759     TEST_DESCRIPTION("Test that an error is produced for a spirv module with a bad magic number");
2760 
2761     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Invalid SPIR-V magic number");
2762 
2763     ASSERT_NO_FATAL_FAILURE(Init());
2764     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2765 
2766     VkShaderModule module;
2767     VkShaderModuleCreateInfo moduleCreateInfo;
2768     struct icd_spv_header spv;
2769 
2770     spv.magic = (uint32_t)~ICD_SPV_MAGIC;
2771     spv.version = ICD_SPV_VERSION;
2772     spv.gen_magic = 0;
2773 
2774     moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
2775     moduleCreateInfo.pNext = NULL;
2776     moduleCreateInfo.pCode = (const uint32_t *)&spv;
2777     moduleCreateInfo.codeSize = sizeof(spv) + 16;
2778     moduleCreateInfo.flags = 0;
2779     vkCreateShaderModule(m_device->device(), &moduleCreateInfo, NULL, &module);
2780 
2781     m_errorMonitor->VerifyFound();
2782 }
2783 
TEST_F(VkLayerTest,CreatePipelineVertexOutputNotConsumed)2784 TEST_F(VkLayerTest, CreatePipelineVertexOutputNotConsumed) {
2785     TEST_DESCRIPTION("Test that a warning is produced for a vertex output that is not consumed by the fragment stage");
2786 
2787     ASSERT_NO_FATAL_FAILURE(Init());
2788     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2789 
2790     char const *vsSource =
2791         "#version 450\n"
2792         "layout(location=0) out float x;\n"
2793         "void main(){\n"
2794         "   gl_Position = vec4(1);\n"
2795         "   x = 0;\n"
2796         "}\n";
2797     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
2798 
2799     const auto set_info = [&](CreatePipelineHelper &helper) {
2800         helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
2801     };
2802     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2803                                       "not consumed by fragment shader");
2804 }
2805 
TEST_F(VkLayerTest,CreatePipelineCheckShaderBadSpecialization)2806 TEST_F(VkLayerTest, CreatePipelineCheckShaderBadSpecialization) {
2807     TEST_DESCRIPTION("Challenge core_validation with shader validation issues related to vkCreateGraphicsPipelines.");
2808 
2809     ASSERT_NO_FATAL_FAILURE(Init());
2810     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2811 
2812     char const *fsSource =
2813         "#version 450\n"
2814         "layout (constant_id = 0) const float r = 0.0f;\n"
2815         "layout(location = 0) out vec4 uFragColor;\n"
2816         "void main(){\n"
2817         "   uFragColor = vec4(r,1,0,1);\n"
2818         "}\n";
2819     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
2820 
2821     // This structure maps constant ids to data locations.
2822     const VkSpecializationMapEntry entry =
2823         // id,  offset,                size
2824         {0, 4, sizeof(uint32_t)};  // Challenge core validation by using a bogus offset.
2825 
2826     uint32_t data = 1;
2827 
2828     // Set up the info describing spec map and data
2829     const VkSpecializationInfo specialization_info = {
2830         1,
2831         &entry,
2832         1 * sizeof(float),
2833         &data,
2834     };
2835 
2836     const auto set_info = [&](CreatePipelineHelper &helper) {
2837         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
2838         helper.shader_stages_[1].pSpecializationInfo = &specialization_info;
2839     };
2840     CreatePipelineHelper::OneshotTest(
2841         *this, set_info, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
2842         "Specialization entry 0 (for constant id 0) references memory outside provided specialization data ");
2843 }
2844 
TEST_F(VkLayerTest,CreatePipelineCheckShaderDescriptorTypeMismatch)2845 TEST_F(VkLayerTest, CreatePipelineCheckShaderDescriptorTypeMismatch) {
2846     TEST_DESCRIPTION("Challenge core_validation with shader validation issues related to vkCreateGraphicsPipelines.");
2847 
2848     ASSERT_NO_FATAL_FAILURE(Init());
2849     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2850 
2851     OneOffDescriptorSet descriptor_set(m_device, {
2852                                                      {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
2853                                                  });
2854 
2855     char const *vsSource =
2856         "#version 450\n"
2857         "\n"
2858         "layout (std140, set = 0, binding = 0) uniform buf {\n"
2859         "    mat4 mvp;\n"
2860         "} ubuf;\n"
2861         "void main(){\n"
2862         "   gl_Position = ubuf.mvp * vec4(1);\n"
2863         "}\n";
2864 
2865     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
2866 
2867     CreatePipelineHelper pipe(*this);
2868     pipe.InitInfo();
2869     pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
2870     pipe.InitState();
2871     pipe.pipeline_layout_ = VkPipelineLayoutObj(m_device, {&descriptor_set.layout_});
2872 
2873     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Type mismatch on descriptor slot 0.0 ");
2874     pipe.CreateGraphicsPipeline();
2875     m_errorMonitor->VerifyFound();
2876 }
2877 
TEST_F(VkLayerTest,CreatePipelineCheckShaderDescriptorNotAccessible)2878 TEST_F(VkLayerTest, CreatePipelineCheckShaderDescriptorNotAccessible) {
2879     TEST_DESCRIPTION(
2880         "Create a pipeline in which a descriptor used by a shader stage does not include that stage in its stageFlags.");
2881 
2882     ASSERT_NO_FATAL_FAILURE(Init());
2883     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2884 
2885     OneOffDescriptorSet ds(m_device, {
2886                                          {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT /*!*/, nullptr},
2887                                      });
2888 
2889     char const *vsSource =
2890         "#version 450\n"
2891         "\n"
2892         "layout (std140, set = 0, binding = 0) uniform buf {\n"
2893         "    mat4 mvp;\n"
2894         "} ubuf;\n"
2895         "void main(){\n"
2896         "   gl_Position = ubuf.mvp * vec4(1);\n"
2897         "}\n";
2898 
2899     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
2900 
2901     CreatePipelineHelper pipe(*this);
2902     pipe.InitInfo();
2903     pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
2904     pipe.InitState();
2905     pipe.pipeline_layout_ = VkPipelineLayoutObj(m_device, {&ds.layout_});
2906 
2907     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Shader uses descriptor slot 0.0 ");
2908     pipe.CreateGraphicsPipeline();
2909     m_errorMonitor->VerifyFound();
2910 }
2911 
TEST_F(VkLayerTest,CreatePipelineCheckShaderPushConstantNotAccessible)2912 TEST_F(VkLayerTest, CreatePipelineCheckShaderPushConstantNotAccessible) {
2913     TEST_DESCRIPTION(
2914         "Create a graphics pipeline in which a push constant range containing a push constant block member is not accessible from "
2915         "the current shader stage.");
2916 
2917     ASSERT_NO_FATAL_FAILURE(Init());
2918     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2919 
2920     char const *vsSource =
2921         "#version 450\n"
2922         "\n"
2923         "layout(push_constant, std430) uniform foo { float x; } consts;\n"
2924         "void main(){\n"
2925         "   gl_Position = vec4(consts.x);\n"
2926         "}\n";
2927 
2928     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
2929 
2930     // Set up a push constant range
2931     VkPushConstantRange push_constant_range = {};
2932     // Set to the wrong stage to challenge core_validation
2933     push_constant_range.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
2934     push_constant_range.size = 4;
2935 
2936     const VkPipelineLayoutObj pipeline_layout(m_device, {}, {push_constant_range});
2937 
2938     CreatePipelineHelper pipe(*this);
2939     pipe.InitInfo();
2940     pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
2941     pipe.InitState();
2942     pipe.pipeline_layout_ = VkPipelineLayoutObj(m_device, {}, {push_constant_range});
2943 
2944     m_errorMonitor->SetDesiredFailureMsg(
2945         VK_DEBUG_REPORT_ERROR_BIT_EXT,
2946         "Push constant range covering variable starting at offset 0 not accessible from stage VK_SHADER_STAGE_VERTEX_BIT");
2947     pipe.CreateGraphicsPipeline();
2948     m_errorMonitor->VerifyFound();
2949 }
2950 
TEST_F(VkLayerTest,CreatePipelineCheckShaderNotEnabled)2951 TEST_F(VkLayerTest, CreatePipelineCheckShaderNotEnabled) {
2952     TEST_DESCRIPTION(
2953         "Create a graphics pipeline in which a capability declared by the shader requires a feature not enabled on the device.");
2954 
2955     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2956 
2957     // Some awkward steps are required to test with custom device features.
2958     VkPhysicalDeviceFeatures device_features = {};
2959     // Disable support for 64 bit floats
2960     device_features.shaderFloat64 = false;
2961     // The sacrificial device object
2962     ASSERT_NO_FATAL_FAILURE(InitState(&device_features));
2963     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2964 
2965     char const *fsSource =
2966         "#version 450\n"
2967         "\n"
2968         "layout(location=0) out vec4 color;\n"
2969         "void main(){\n"
2970         "   dvec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
2971         "   color = vec4(green);\n"
2972         "}\n";
2973     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
2974 
2975     CreatePipelineHelper pipe(*this);
2976     pipe.InitInfo();
2977     pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
2978     pipe.InitState();
2979     pipe.pipeline_layout_ = VkPipelineLayoutObj(m_device);
2980 
2981     m_errorMonitor->SetDesiredFailureMsg(
2982         VK_DEBUG_REPORT_ERROR_BIT_EXT, "Shader requires VkPhysicalDeviceFeatures::shaderFloat64 but is not enabled on the device");
2983     pipe.CreateGraphicsPipeline();
2984     m_errorMonitor->VerifyFound();
2985 }
2986 
TEST_F(VkLayerTest,CreateShaderModuleCheckBadCapability)2987 TEST_F(VkLayerTest, CreateShaderModuleCheckBadCapability) {
2988     TEST_DESCRIPTION("Create a shader in which a capability declared by the shader is not supported.");
2989     // Note that this failure message comes from spirv-tools, specifically the validator.
2990 
2991     ASSERT_NO_FATAL_FAILURE(Init());
2992     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2993 
2994     const std::string spv_source = R"(
2995                   OpCapability ImageRect
2996                   OpEntryPoint Vertex %main "main"
2997           %main = OpFunction %void None %3
2998                   OpReturn
2999                   OpFunctionEnd
3000         )";
3001 
3002     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Capability ImageRect is not allowed by Vulkan");
3003 
3004     std::vector<unsigned int> spv;
3005     VkShaderModuleCreateInfo module_create_info;
3006     VkShaderModule shader_module;
3007     module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
3008     module_create_info.pNext = NULL;
3009     ASMtoSPV(SPV_ENV_VULKAN_1_0, 0, spv_source.data(), spv);
3010     module_create_info.pCode = spv.data();
3011     module_create_info.codeSize = spv.size() * sizeof(unsigned int);
3012     module_create_info.flags = 0;
3013 
3014     VkResult err = vkCreateShaderModule(m_device->handle(), &module_create_info, NULL, &shader_module);
3015     m_errorMonitor->VerifyFound();
3016     if (err == VK_SUCCESS) {
3017         vkDestroyShaderModule(m_device->handle(), shader_module, NULL);
3018     }
3019 }
3020 
TEST_F(VkLayerTest,CreatePipelineFragmentInputNotProvided)3021 TEST_F(VkLayerTest, CreatePipelineFragmentInputNotProvided) {
3022     TEST_DESCRIPTION(
3023         "Test that an error is produced for a fragment shader input which is not present in the outputs of the previous stage");
3024 
3025     ASSERT_NO_FATAL_FAILURE(Init());
3026     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3027 
3028     char const *fsSource =
3029         "#version 450\n"
3030         "\n"
3031         "layout(location=0) in float x;\n"
3032         "layout(location=0) out vec4 color;\n"
3033         "void main(){\n"
3034         "   color = vec4(x);\n"
3035         "}\n";
3036     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3037 
3038     const auto set_info = [&](CreatePipelineHelper &helper) {
3039         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
3040     };
3041     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "not written by vertex shader");
3042 }
3043 
TEST_F(VkLayerTest,CreatePipelineFragmentInputNotProvidedInBlock)3044 TEST_F(VkLayerTest, CreatePipelineFragmentInputNotProvidedInBlock) {
3045     TEST_DESCRIPTION(
3046         "Test that an error is produced for a fragment shader input within an interace block, which is not present in the outputs "
3047         "of the previous stage.");
3048 
3049     ASSERT_NO_FATAL_FAILURE(Init());
3050     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3051 
3052     char const *fsSource =
3053         "#version 450\n"
3054         "\n"
3055         "in block { layout(location=0) float x; } ins;\n"
3056         "layout(location=0) out vec4 color;\n"
3057         "void main(){\n"
3058         "   color = vec4(ins.x);\n"
3059         "}\n";
3060 
3061     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3062 
3063     const auto set_info = [&](CreatePipelineHelper &helper) {
3064         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
3065     };
3066     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "not written by vertex shader");
3067 }
3068 
TEST_F(VkLayerTest,CreatePipelineVsFsTypeMismatchArraySize)3069 TEST_F(VkLayerTest, CreatePipelineVsFsTypeMismatchArraySize) {
3070     TEST_DESCRIPTION("Test that an error is produced for mismatched array sizes across the vertex->fragment shader interface");
3071 
3072     ASSERT_NO_FATAL_FAILURE(Init());
3073     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3074 
3075     char const *vsSource =
3076         "#version 450\n"
3077         "\n"
3078         "layout(location=0) out float x[2];\n"
3079         "void main(){\n"
3080         "   x[0] = 0; x[1] = 0;\n"
3081         "   gl_Position = vec4(1);\n"
3082         "}\n";
3083     char const *fsSource =
3084         "#version 450\n"
3085         "\n"
3086         "layout(location=0) in float x[1];\n"
3087         "layout(location=0) out vec4 color;\n"
3088         "void main(){\n"
3089         "   color = vec4(x[0]);\n"
3090         "}\n";
3091 
3092     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
3093     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3094 
3095     const auto set_info = [&](CreatePipelineHelper &helper) {
3096         helper.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
3097     };
3098     CreatePipelineHelper::OneshotTest(
3099         *this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3100         "Type mismatch on location 0.0: 'ptr to output arr[2] of float32' vs 'ptr to input arr[1] of float32'");
3101 }
3102 
TEST_F(VkLayerTest,CreatePipelineVsFsTypeMismatch)3103 TEST_F(VkLayerTest, CreatePipelineVsFsTypeMismatch) {
3104     TEST_DESCRIPTION("Test that an error is produced for mismatched types across the vertex->fragment shader interface");
3105 
3106     ASSERT_NO_FATAL_FAILURE(Init());
3107     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3108 
3109     char const *vsSource =
3110         "#version 450\n"
3111         "\n"
3112         "layout(location=0) out int x;\n"
3113         "void main(){\n"
3114         "   x = 0;\n"
3115         "   gl_Position = vec4(1);\n"
3116         "}\n";
3117     char const *fsSource =
3118         "#version 450\n"
3119         "\n"
3120         "layout(location=0) in float x;\n" /* VS writes int */
3121         "layout(location=0) out vec4 color;\n"
3122         "void main(){\n"
3123         "   color = vec4(x);\n"
3124         "}\n";
3125 
3126     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
3127     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3128 
3129     const auto set_info = [&](CreatePipelineHelper &helper) {
3130         helper.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
3131     };
3132     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "Type mismatch on location 0");
3133 }
3134 
TEST_F(VkLayerTest,CreatePipelineVsFsTypeMismatchInBlock)3135 TEST_F(VkLayerTest, CreatePipelineVsFsTypeMismatchInBlock) {
3136     TEST_DESCRIPTION(
3137         "Test that an error is produced for mismatched types across the vertex->fragment shader interface, when the variable is "
3138         "contained within an interface block");
3139 
3140     ASSERT_NO_FATAL_FAILURE(Init());
3141     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3142 
3143     char const *vsSource =
3144         "#version 450\n"
3145         "\n"
3146         "out block { layout(location=0) int x; } outs;\n"
3147         "void main(){\n"
3148         "   outs.x = 0;\n"
3149         "   gl_Position = vec4(1);\n"
3150         "}\n";
3151     char const *fsSource =
3152         "#version 450\n"
3153         "\n"
3154         "in block { layout(location=0) float x; } ins;\n" /* VS writes int */
3155         "layout(location=0) out vec4 color;\n"
3156         "void main(){\n"
3157         "   color = vec4(ins.x);\n"
3158         "}\n";
3159 
3160     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
3161     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3162 
3163     const auto set_info = [&](CreatePipelineHelper &helper) {
3164         helper.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
3165     };
3166     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "Type mismatch on location 0");
3167 }
3168 
TEST_F(VkLayerTest,CreatePipelineVsFsMismatchByLocation)3169 TEST_F(VkLayerTest, CreatePipelineVsFsMismatchByLocation) {
3170     TEST_DESCRIPTION(
3171         "Test that an error is produced for location mismatches across the vertex->fragment shader interface; This should manifest "
3172         "as a not-written/not-consumed pair, but flushes out broken walking of the interfaces");
3173 
3174     ASSERT_NO_FATAL_FAILURE(Init());
3175     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3176 
3177     char const *vsSource =
3178         "#version 450\n"
3179         "\n"
3180         "out block { layout(location=1) float x; } outs;\n"
3181         "void main(){\n"
3182         "   outs.x = 0;\n"
3183         "   gl_Position = vec4(1);\n"
3184         "}\n";
3185     char const *fsSource =
3186         "#version 450\n"
3187         "\n"
3188         "in block { layout(location=0) float x; } ins;\n"
3189         "layout(location=0) out vec4 color;\n"
3190         "void main(){\n"
3191         "   color = vec4(ins.x);\n"
3192         "}\n";
3193 
3194     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
3195     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3196 
3197     const auto set_info = [&](CreatePipelineHelper &helper) {
3198         helper.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
3199     };
3200     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3201                                       "location 0.0 which is not written by vertex shader");
3202 }
3203 
TEST_F(VkLayerTest,CreatePipelineVsFsMismatchByComponent)3204 TEST_F(VkLayerTest, CreatePipelineVsFsMismatchByComponent) {
3205     TEST_DESCRIPTION(
3206         "Test that an error is produced for component mismatches across the vertex->fragment shader interface. It's not enough to "
3207         "have the same set of locations in use; matching is defined in terms of spirv variables.");
3208 
3209     ASSERT_NO_FATAL_FAILURE(Init());
3210     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3211 
3212     char const *vsSource =
3213         "#version 450\n"
3214         "\n"
3215         "out block { layout(location=0, component=0) float x; } outs;\n"
3216         "void main(){\n"
3217         "   outs.x = 0;\n"
3218         "   gl_Position = vec4(1);\n"
3219         "}\n";
3220     char const *fsSource =
3221         "#version 450\n"
3222         "\n"
3223         "in block { layout(location=0, component=1) float x; } ins;\n"
3224         "layout(location=0) out vec4 color;\n"
3225         "void main(){\n"
3226         "   color = vec4(ins.x);\n"
3227         "}\n";
3228 
3229     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
3230     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3231 
3232     const auto set_info = [&](CreatePipelineHelper &helper) {
3233         helper.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
3234     };
3235     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3236                                       "location 0.1 which is not written by vertex shader");
3237 }
3238 
TEST_F(VkLayerTest,CreatePipelineVsFsMismatchByPrecision)3239 TEST_F(VkLayerTest, CreatePipelineVsFsMismatchByPrecision) {
3240     TEST_DESCRIPTION("Test that the RelaxedPrecision decoration is validated to match");
3241 
3242     ASSERT_NO_FATAL_FAILURE(Init());
3243     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3244 
3245     char const *vsSource =
3246         "#version 450\n"
3247         "layout(location=0) out mediump float x;\n"
3248         "void main() { gl_Position = vec4(0); x = 1.0; }\n";
3249     char const *fsSource =
3250         "#version 450\n"
3251         "layout(location=0) in highp float x;\n"
3252         "layout(location=0) out vec4 color;\n"
3253         "void main() { color = vec4(x); }\n";
3254 
3255     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
3256     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3257 
3258     const auto set_info = [&](CreatePipelineHelper &helper) {
3259         helper.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
3260     };
3261     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "differ in precision");
3262 }
3263 
TEST_F(VkLayerTest,CreatePipelineVsFsMismatchByPrecisionBlock)3264 TEST_F(VkLayerTest, CreatePipelineVsFsMismatchByPrecisionBlock) {
3265     TEST_DESCRIPTION("Test that the RelaxedPrecision decoration is validated to match");
3266 
3267     ASSERT_NO_FATAL_FAILURE(Init());
3268     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3269 
3270     char const *vsSource =
3271         "#version 450\n"
3272         "out block { layout(location=0) mediump float x; };\n"
3273         "void main() { gl_Position = vec4(0); x = 1.0; }\n";
3274     char const *fsSource =
3275         "#version 450\n"
3276         "in block { layout(location=0) highp float x; };\n"
3277         "layout(location=0) out vec4 color;\n"
3278         "void main() { color = vec4(x); }\n";
3279 
3280     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
3281     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3282 
3283     const auto set_info = [&](CreatePipelineHelper &helper) {
3284         helper.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
3285     };
3286     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "differ in precision");
3287 }
3288 
TEST_F(VkLayerTest,CreatePipelineAttribNotConsumed)3289 TEST_F(VkLayerTest, CreatePipelineAttribNotConsumed) {
3290     TEST_DESCRIPTION("Test that a warning is produced for a vertex attribute which is not consumed by the vertex shader");
3291 
3292     ASSERT_NO_FATAL_FAILURE(Init());
3293     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3294 
3295     VkVertexInputBindingDescription input_binding;
3296     memset(&input_binding, 0, sizeof(input_binding));
3297 
3298     VkVertexInputAttributeDescription input_attrib;
3299     memset(&input_attrib, 0, sizeof(input_attrib));
3300     input_attrib.format = VK_FORMAT_R32_SFLOAT;
3301 
3302     const auto set_info = [&](CreatePipelineHelper &helper) {
3303         helper.vi_ci_.pVertexBindingDescriptions = &input_binding;
3304         helper.vi_ci_.vertexBindingDescriptionCount = 1;
3305         helper.vi_ci_.pVertexAttributeDescriptions = &input_attrib;
3306         helper.vi_ci_.vertexAttributeDescriptionCount = 1;
3307     };
3308     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
3309                                       "location 0 not consumed by vertex shader");
3310 }
3311 
TEST_F(VkLayerTest,CreatePipelineAttribLocationMismatch)3312 TEST_F(VkLayerTest, CreatePipelineAttribLocationMismatch) {
3313     TEST_DESCRIPTION(
3314         "Test that a warning is produced for a location mismatch on vertex attributes. This flushes out bad behavior in the "
3315         "interface walker");
3316 
3317     ASSERT_NO_FATAL_FAILURE(Init());
3318     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3319 
3320     VkVertexInputBindingDescription input_binding;
3321     memset(&input_binding, 0, sizeof(input_binding));
3322 
3323     VkVertexInputAttributeDescription input_attrib;
3324     memset(&input_attrib, 0, sizeof(input_attrib));
3325     input_attrib.format = VK_FORMAT_R32_SFLOAT;
3326 
3327     const auto set_info = [&](CreatePipelineHelper &helper) {
3328         helper.vi_ci_.pVertexBindingDescriptions = &input_binding;
3329         helper.vi_ci_.vertexBindingDescriptionCount = 1;
3330         helper.vi_ci_.pVertexAttributeDescriptions = &input_attrib;
3331         helper.vi_ci_.vertexAttributeDescriptionCount = 1;
3332     };
3333     m_errorMonitor->SetUnexpectedError("Vertex shader consumes input at location 1 but not provided");
3334 
3335     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
3336                                       "location 0 not consumed by vertex shader");
3337 }
3338 
TEST_F(VkLayerTest,CreatePipelineAttribNotProvided)3339 TEST_F(VkLayerTest, CreatePipelineAttribNotProvided) {
3340     TEST_DESCRIPTION("Test that an error is produced for a vertex shader input which is not provided by a vertex attribute");
3341 
3342     ASSERT_NO_FATAL_FAILURE(Init());
3343     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3344 
3345     char const *vsSource =
3346         "#version 450\n"
3347         "\n"
3348         "layout(location=0) in vec4 x;\n" /* not provided */
3349         "void main(){\n"
3350         "   gl_Position = x;\n"
3351         "}\n";
3352     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
3353 
3354     const auto set_info = [&](CreatePipelineHelper &helper) {
3355         helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
3356     };
3357     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3358                                       "Vertex shader consumes input at location 0 but not provided");
3359 }
3360 
TEST_F(VkLayerTest,CreatePipelineAttribTypeMismatch)3361 TEST_F(VkLayerTest, CreatePipelineAttribTypeMismatch) {
3362     TEST_DESCRIPTION(
3363         "Test that an error is produced for a mismatch between the fundamental type (float/int/uint) of an attribute and the "
3364         "vertex shader input that consumes it");
3365 
3366     ASSERT_NO_FATAL_FAILURE(Init());
3367     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3368 
3369     VkVertexInputBindingDescription input_binding;
3370     memset(&input_binding, 0, sizeof(input_binding));
3371 
3372     VkVertexInputAttributeDescription input_attrib;
3373     memset(&input_attrib, 0, sizeof(input_attrib));
3374     input_attrib.format = VK_FORMAT_R32_SFLOAT;
3375 
3376     char const *vsSource =
3377         "#version 450\n"
3378         "\n"
3379         "layout(location=0) in int x;\n" /* attrib provided float */
3380         "void main(){\n"
3381         "   gl_Position = vec4(x);\n"
3382         "}\n";
3383     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
3384 
3385     const auto set_info = [&](CreatePipelineHelper &helper) {
3386         helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
3387         helper.vi_ci_.pVertexBindingDescriptions = &input_binding;
3388         helper.vi_ci_.vertexBindingDescriptionCount = 1;
3389         helper.vi_ci_.pVertexAttributeDescriptions = &input_attrib;
3390         helper.vi_ci_.vertexAttributeDescriptionCount = 1;
3391     };
3392     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3393                                       "location 0 does not match vertex shader input type");
3394 }
3395 
TEST_F(VkLayerTest,CreatePipelineDuplicateStage)3396 TEST_F(VkLayerTest, CreatePipelineDuplicateStage) {
3397     TEST_DESCRIPTION("Test that an error is produced for a pipeline containing multiple shaders for the same stage");
3398 
3399     ASSERT_NO_FATAL_FAILURE(Init());
3400     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3401 
3402     const auto set_info = [&](CreatePipelineHelper &helper) {
3403         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), helper.vs_->GetStageCreateInfo(),
3404                                  helper.fs_->GetStageCreateInfo()};
3405     };
3406     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3407                                       "Multiple shaders provided for stage VK_SHADER_STAGE_VERTEX_BIT");
3408 }
3409 
TEST_F(VkLayerTest,CreatePipelineMissingEntrypoint)3410 TEST_F(VkLayerTest, CreatePipelineMissingEntrypoint) {
3411     ASSERT_NO_FATAL_FAILURE(Init());
3412     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3413 
3414     VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this, "foo");
3415 
3416     const auto set_info = [&](CreatePipelineHelper &helper) {
3417         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
3418     };
3419     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "No entrypoint found named `foo`");
3420 }
3421 
TEST_F(VkLayerTest,CreatePipelineDepthStencilRequired)3422 TEST_F(VkLayerTest, CreatePipelineDepthStencilRequired) {
3423     m_errorMonitor->SetDesiredFailureMsg(
3424         VK_DEBUG_REPORT_ERROR_BIT_EXT,
3425         "pDepthStencilState is NULL when rasterization is enabled and subpass uses a depth/stencil attachment");
3426 
3427     ASSERT_NO_FATAL_FAILURE(Init());
3428     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3429 
3430     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
3431     VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3432 
3433     VkPipelineObj pipe(m_device);
3434     pipe.AddDefaultColorAttachment();
3435     pipe.AddShader(&vs);
3436     pipe.AddShader(&fs);
3437 
3438     VkDescriptorSetObj descriptorSet(m_device);
3439     descriptorSet.AppendDummy();
3440     descriptorSet.CreateVKDescriptorSet(m_commandBuffer);
3441 
3442     VkAttachmentDescription attachments[] = {
3443         {
3444             0,
3445             VK_FORMAT_B8G8R8A8_UNORM,
3446             VK_SAMPLE_COUNT_1_BIT,
3447             VK_ATTACHMENT_LOAD_OP_DONT_CARE,
3448             VK_ATTACHMENT_STORE_OP_DONT_CARE,
3449             VK_ATTACHMENT_LOAD_OP_DONT_CARE,
3450             VK_ATTACHMENT_STORE_OP_DONT_CARE,
3451             VK_IMAGE_LAYOUT_UNDEFINED,
3452             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
3453         },
3454         {
3455             0,
3456             VK_FORMAT_D16_UNORM,
3457             VK_SAMPLE_COUNT_1_BIT,
3458             VK_ATTACHMENT_LOAD_OP_DONT_CARE,
3459             VK_ATTACHMENT_STORE_OP_DONT_CARE,
3460             VK_ATTACHMENT_LOAD_OP_DONT_CARE,
3461             VK_ATTACHMENT_STORE_OP_DONT_CARE,
3462             VK_IMAGE_LAYOUT_UNDEFINED,
3463             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
3464         },
3465     };
3466     VkAttachmentReference refs[] = {
3467         {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
3468         {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL},
3469     };
3470     VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &refs[0], nullptr, &refs[1], 0, nullptr};
3471     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 2, attachments, 1, &subpass, 0, nullptr};
3472     VkRenderPass rp;
3473     VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp);
3474     ASSERT_VK_SUCCESS(err);
3475 
3476     pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), rp);
3477 
3478     m_errorMonitor->VerifyFound();
3479 
3480     vkDestroyRenderPass(m_device->device(), rp, nullptr);
3481 }
3482 
TEST_F(VkLayerTest,CreatePipelineTessPatchDecorationMismatch)3483 TEST_F(VkLayerTest, CreatePipelineTessPatchDecorationMismatch) {
3484     TEST_DESCRIPTION(
3485         "Test that an error is produced for a variable output from the TCS without the patch decoration, but consumed in the TES "
3486         "with the decoration.");
3487 
3488     ASSERT_NO_FATAL_FAILURE(Init());
3489     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3490 
3491     if (!m_device->phy().features().tessellationShader) {
3492         printf("%s Device does not support tessellation shaders; skipped.\n", kSkipPrefix);
3493         return;
3494     }
3495 
3496     char const *tcsSource =
3497         "#version 450\n"
3498         "layout(location=0) out int x[];\n"
3499         "layout(vertices=3) out;\n"
3500         "void main(){\n"
3501         "   gl_TessLevelOuter[0] = gl_TessLevelOuter[1] = gl_TessLevelOuter[2] = 1;\n"
3502         "   gl_TessLevelInner[0] = 1;\n"
3503         "   x[gl_InvocationID] = gl_InvocationID;\n"
3504         "}\n";
3505     char const *tesSource =
3506         "#version 450\n"
3507         "layout(triangles, equal_spacing, cw) in;\n"
3508         "layout(location=0) patch in int x;\n"
3509         "void main(){\n"
3510         "   gl_Position.xyz = gl_TessCoord;\n"
3511         "   gl_Position.w = x;\n"
3512         "}\n";
3513     VkShaderObj tcs(m_device, tcsSource, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this);
3514     VkShaderObj tes(m_device, tesSource, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this);
3515 
3516     VkPipelineInputAssemblyStateCreateInfo iasci{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0,
3517                                                  VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE};
3518 
3519     VkPipelineTessellationStateCreateInfo tsci{VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, nullptr, 0, 3};
3520 
3521     const auto set_info = [&](CreatePipelineHelper &helper) {
3522         helper.gp_ci_.pTessellationState = &tsci;
3523         helper.gp_ci_.pInputAssemblyState = &iasci;
3524         helper.shader_stages_.emplace_back(tcs.GetStageCreateInfo());
3525         helper.shader_stages_.emplace_back(tes.GetStageCreateInfo());
3526     };
3527     CreatePipelineHelper::OneshotTest(
3528         *this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3529         "is per-vertex in tessellation control shader stage but per-patch in tessellation evaluation shader stage");
3530 }
3531 
TEST_F(VkLayerTest,CreatePipelineTessErrors)3532 TEST_F(VkLayerTest, CreatePipelineTessErrors) {
3533     TEST_DESCRIPTION("Test various errors when creating a graphics pipeline with tessellation stages active.");
3534 
3535     ASSERT_NO_FATAL_FAILURE(Init());
3536     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3537 
3538     if (!m_device->phy().features().tessellationShader) {
3539         printf("%s Device does not support tessellation shaders; skipped.\n", kSkipPrefix);
3540         return;
3541     }
3542 
3543     char const *tcsSource =
3544         "#version 450\n"
3545         "layout(vertices=3) out;\n"
3546         "void main(){\n"
3547         "   gl_TessLevelOuter[0] = gl_TessLevelOuter[1] = gl_TessLevelOuter[2] = 1;\n"
3548         "   gl_TessLevelInner[0] = 1;\n"
3549         "}\n";
3550     char const *tesSource =
3551         "#version 450\n"
3552         "layout(triangles, equal_spacing, cw) in;\n"
3553         "void main(){\n"
3554         "   gl_Position.xyz = gl_TessCoord;\n"
3555         "   gl_Position.w = 0;\n"
3556         "}\n";
3557     VkShaderObj tcs(m_device, tcsSource, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this);
3558     VkShaderObj tes(m_device, tesSource, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this);
3559 
3560     VkPipelineInputAssemblyStateCreateInfo iasci{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0,
3561                                                  VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE};
3562 
3563     VkPipelineTessellationStateCreateInfo tsci{VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, nullptr, 0, 3};
3564 
3565     std::vector<VkPipelineShaderStageCreateInfo> shader_stages = {};
3566     VkPipelineInputAssemblyStateCreateInfo iasci_bad = iasci;
3567     VkPipelineInputAssemblyStateCreateInfo *p_iasci = nullptr;
3568     VkPipelineTessellationStateCreateInfo tsci_bad = tsci;
3569     VkPipelineTessellationStateCreateInfo *p_tsci = nullptr;
3570 
3571     const auto set_info = [&](CreatePipelineHelper &helper) {
3572         helper.gp_ci_.pTessellationState = p_tsci;
3573         helper.gp_ci_.pInputAssemblyState = p_iasci;
3574         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
3575         helper.shader_stages_.insert(helper.shader_stages_.end(), shader_stages.begin(), shader_stages.end());
3576     };
3577 
3578     iasci_bad.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;  // otherwise we get a failure about invalid topology
3579     p_iasci = &iasci_bad;
3580     // Pass a tess control shader without a tess eval shader
3581     shader_stages = {tcs.GetStageCreateInfo()};
3582     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3583                                       "VUID-VkGraphicsPipelineCreateInfo-pStages-00729");
3584 
3585     // Pass a tess eval shader without a tess control shader
3586     shader_stages = {tes.GetStageCreateInfo()};
3587     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3588                                       "VUID-VkGraphicsPipelineCreateInfo-pStages-00730");
3589 
3590     p_iasci = &iasci;
3591     shader_stages = {};
3592     // Pass patch topology without tessellation shaders
3593     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3594                                       "VUID-VkGraphicsPipelineCreateInfo-topology-00737");
3595 
3596     shader_stages = {tcs.GetStageCreateInfo(), tes.GetStageCreateInfo()};
3597     // Pass a NULL pTessellationState (with active tessellation shader stages)
3598     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3599                                       "VUID-VkGraphicsPipelineCreateInfo-pStages-00731");
3600 
3601     // Pass an invalid pTessellationState (bad sType)
3602     tsci_bad.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
3603     p_tsci = &tsci_bad;
3604     shader_stages = {tcs.GetStageCreateInfo(), tes.GetStageCreateInfo()};
3605     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3606                                       "VUID-VkPipelineTessellationStateCreateInfo-sType-sType");
3607 
3608     // Pass out-of-range patchControlPoints
3609     p_iasci = &iasci;
3610     tsci_bad = tsci;
3611     tsci_bad.patchControlPoints = 0;
3612     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3613                                       "VUID-VkPipelineTessellationStateCreateInfo-patchControlPoints-01214");
3614 
3615     tsci_bad.patchControlPoints = m_device->props.limits.maxTessellationPatchSize + 1;
3616     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3617                                       "VUID-VkPipelineTessellationStateCreateInfo-patchControlPoints-01214");
3618 
3619     p_tsci = &tsci;
3620     // Pass an invalid primitive topology
3621     iasci_bad = iasci;
3622     iasci_bad.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
3623     p_iasci = &iasci_bad;
3624     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3625                                       "VUID-VkGraphicsPipelineCreateInfo-pStages-00736");
3626 }
3627 
TEST_F(VkLayerTest,CreatePipelineAttribBindingConflict)3628 TEST_F(VkLayerTest, CreatePipelineAttribBindingConflict) {
3629     TEST_DESCRIPTION(
3630         "Test that an error is produced for a vertex attribute setup where multiple bindings provide the same location");
3631 
3632     ASSERT_NO_FATAL_FAILURE(Init());
3633     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3634 
3635     /* Two binding descriptions for binding 0 */
3636     VkVertexInputBindingDescription input_bindings[2];
3637     memset(input_bindings, 0, sizeof(input_bindings));
3638 
3639     VkVertexInputAttributeDescription input_attrib;
3640     memset(&input_attrib, 0, sizeof(input_attrib));
3641     input_attrib.format = VK_FORMAT_R32_SFLOAT;
3642 
3643     char const *vsSource =
3644         "#version 450\n"
3645         "\n"
3646         "layout(location=0) in float x;\n" /* attrib provided float */
3647         "void main(){\n"
3648         "   gl_Position = vec4(x);\n"
3649         "}\n";
3650 
3651     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
3652 
3653     m_errorMonitor->VerifyFound();
3654     const auto set_info = [&](CreatePipelineHelper &helper) {
3655         helper.shader_stages_ = {vs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
3656         helper.vi_ci_.pVertexBindingDescriptions = input_bindings;
3657         helper.vi_ci_.vertexBindingDescriptionCount = 2;
3658         helper.vi_ci_.pVertexAttributeDescriptions = &input_attrib;
3659         helper.vi_ci_.vertexAttributeDescriptionCount = 1;
3660     };
3661     m_errorMonitor->SetUnexpectedError("VUID-VkPipelineVertexInputStateCreateInfo-pVertexBindingDescriptions-00616 ");
3662     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3663                                       "Duplicate vertex input binding descriptions for binding 0");
3664 }
3665 
TEST_F(VkLayerTest,CreatePipelineFragmentOutputNotWritten)3666 TEST_F(VkLayerTest, CreatePipelineFragmentOutputNotWritten) {
3667     TEST_DESCRIPTION(
3668         "Test that an error is produced for a fragment shader which does not provide an output for one of the pipeline's color "
3669         "attachments");
3670 
3671     ASSERT_NO_FATAL_FAILURE(Init());
3672     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3673 
3674     VkShaderObj fs(m_device, bindStateMinimalShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3675 
3676     const auto set_info = [&](CreatePipelineHelper &helper) {
3677         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
3678         helper.cb_attachments_.colorWriteMask = 1;
3679     };
3680     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_WARNING_BIT_EXT,
3681                                       "Attachment 0 not written by fragment shader");
3682 }
3683 
TEST_F(VkLayerTest,CreatePipelineFragmentOutputNotConsumed)3684 TEST_F(VkLayerTest, CreatePipelineFragmentOutputNotConsumed) {
3685     TEST_DESCRIPTION(
3686         "Test that a warning is produced for a fragment shader which provides a spurious output with no matching attachment");
3687 
3688     ASSERT_NO_FATAL_FAILURE(Init());
3689     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3690 
3691     char const *fsSource =
3692         "#version 450\n"
3693         "\n"
3694         "layout(location=0) out vec4 x;\n"
3695         "layout(location=1) out vec4 y;\n" /* no matching attachment for this */
3696         "void main(){\n"
3697         "   x = vec4(1);\n"
3698         "   y = vec4(1);\n"
3699         "}\n";
3700     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3701 
3702     const auto set_info = [&](CreatePipelineHelper &helper) {
3703         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
3704     };
3705     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_WARNING_BIT_EXT,
3706                                       "fragment shader writes to output location 1 with no matching attachment");
3707 }
3708 
TEST_F(VkLayerTest,CreatePipelineFragmentNoOutputLocation0ButAlphaToCoverageEnabled)3709 TEST_F(VkLayerTest, CreatePipelineFragmentNoOutputLocation0ButAlphaToCoverageEnabled) {
3710     TEST_DESCRIPTION("Test that an error is produced when alpha to coverage is enabled but no output at location 0 is declared.");
3711 
3712     ASSERT_NO_FATAL_FAILURE(Init());
3713     ASSERT_NO_FATAL_FAILURE(InitRenderTarget(0u));
3714 
3715     VkShaderObj fs(m_device, bindStateMinimalShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3716 
3717     VkPipelineMultisampleStateCreateInfo ms_state_ci = {};
3718     ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
3719     ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
3720     ms_state_ci.alphaToCoverageEnable = VK_TRUE;
3721 
3722     const auto set_info = [&](CreatePipelineHelper &helper) {
3723         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
3724         helper.pipe_ms_state_ci_ = ms_state_ci;
3725     };
3726     CreatePipelineHelper::OneshotTest(
3727         *this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3728         "fragment shader doesn't declare alpha output at location 0 even though alpha to coverage is enabled.");
3729 }
3730 
TEST_F(VkLayerTest,CreatePipelineFragmentNoAlphaLocation0ButAlphaToCoverageEnabled)3731 TEST_F(VkLayerTest, CreatePipelineFragmentNoAlphaLocation0ButAlphaToCoverageEnabled) {
3732     TEST_DESCRIPTION(
3733         "Test that an error is produced when alpha to coverage is enabled but output at location 0 doesn't have alpha channel.");
3734 
3735     ASSERT_NO_FATAL_FAILURE(Init());
3736     ASSERT_NO_FATAL_FAILURE(InitRenderTarget(0u));
3737 
3738     char const *fsSource =
3739         "#version 450\n"
3740         "layout(location=0) out vec3 x;\n"
3741         "\n"
3742         "void main(){\n"
3743         "   x = vec3(1);\n"
3744         "}\n";
3745     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3746 
3747     VkPipelineMultisampleStateCreateInfo ms_state_ci = {};
3748     ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
3749     ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
3750     ms_state_ci.alphaToCoverageEnable = VK_TRUE;
3751 
3752     const auto set_info = [&](CreatePipelineHelper &helper) {
3753         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
3754         helper.pipe_ms_state_ci_ = ms_state_ci;
3755     };
3756     CreatePipelineHelper::OneshotTest(
3757         *this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3758         "fragment shader doesn't declare alpha output at location 0 even though alpha to coverage is enabled.");
3759 }
3760 
TEST_F(VkLayerTest,CreatePipelineFragmentOutputTypeMismatch)3761 TEST_F(VkLayerTest, CreatePipelineFragmentOutputTypeMismatch) {
3762     TEST_DESCRIPTION(
3763         "Test that an error is produced for a mismatch between the fundamental type of an fragment shader output variable, and the "
3764         "format of the corresponding attachment");
3765 
3766     ASSERT_NO_FATAL_FAILURE(Init());
3767     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3768 
3769     char const *fsSource =
3770         "#version 450\n"
3771         "\n"
3772         "layout(location=0) out ivec4 x;\n" /* not UNORM */
3773         "void main(){\n"
3774         "   x = ivec4(1);\n"
3775         "}\n";
3776 
3777     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3778 
3779     const auto set_info = [&](CreatePipelineHelper &helper) {
3780         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
3781     };
3782     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_WARNING_BIT_EXT,
3783                                       "does not match fragment shader output type");
3784 }
3785 
TEST_F(VkLayerTest,CreatePipelineExceedMaxVertexOutputComponents)3786 TEST_F(VkLayerTest, CreatePipelineExceedMaxVertexOutputComponents) {
3787     TEST_DESCRIPTION(
3788         "Test that an error is produced when the number of output components from the vertex stage exceeds the device limit");
3789 
3790     ASSERT_NO_FATAL_FAILURE(Init());
3791     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3792 
3793     for (int overflow = 0; overflow < 2; ++overflow) {
3794         m_errorMonitor->Reset();
3795 
3796         const uint32_t maxVsOutComp = m_device->props.limits.maxVertexOutputComponents + overflow;
3797         std::string vsSourceStr = "#version 450\n\n";
3798         const uint32_t numVec4 = maxVsOutComp / 4;
3799         uint32_t location = 0;
3800         for (uint32_t i = 0; i < numVec4; i++) {
3801             vsSourceStr += "layout(location=" + std::to_string(location) + ") out vec4 v" + std::to_string(i) + ";\n";
3802             location += 1;
3803         }
3804         const uint32_t remainder = maxVsOutComp % 4;
3805         if (remainder != 0) {
3806             if (remainder == 1) {
3807                 vsSourceStr += "layout(location=" + std::to_string(location) + ") out float" + " vn;\n";
3808             } else {
3809                 vsSourceStr += "layout(location=" + std::to_string(location) + ") out vec" + std::to_string(remainder) + " vn;\n";
3810             }
3811             location += 1;
3812         }
3813         vsSourceStr +=
3814             "void main(){\n"
3815             "}\n";
3816 
3817         std::string fsSourceStr =
3818             "#version 450\n"
3819             "\n"
3820             "layout(location=0) out vec4 color;\n"
3821             "\n"
3822             "void main(){\n"
3823             "    color = vec4(1);\n"
3824             "}\n";
3825 
3826         VkShaderObj vs(m_device, vsSourceStr.c_str(), VK_SHADER_STAGE_VERTEX_BIT, this);
3827         VkShaderObj fs(m_device, fsSourceStr.c_str(), VK_SHADER_STAGE_FRAGMENT_BIT, this);
3828 
3829         const auto set_info = [&](CreatePipelineHelper &helper) {
3830             helper.shader_stages_ = {vs.GetStageCreateInfo(), fs.GetStageCreateInfo()};
3831         };
3832         if (overflow) {
3833             CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_WARNING_BIT_EXT,
3834                                               "Vertex shader exceeds VkPhysicalDeviceLimits::maxVertexOutputComponents");
3835         } else {
3836             CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_WARNING_BIT_EXT, "", true);
3837         }
3838     }
3839 }
3840 
TEST_F(VkLayerTest,CreatePipelineExceedMaxTessellationControlInputOutputComponents)3841 TEST_F(VkLayerTest, CreatePipelineExceedMaxTessellationControlInputOutputComponents) {
3842     TEST_DESCRIPTION(
3843         "Test that errors are produced when the number of per-vertex input and/or output components to the tessellation control "
3844         "stage exceeds the device limit");
3845 
3846     ASSERT_NO_FATAL_FAILURE(Init());
3847     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3848 
3849     for (int overflow = 0; overflow < 2; ++overflow) {
3850         m_errorMonitor->Reset();
3851         VkPhysicalDeviceFeatures feat;
3852         vkGetPhysicalDeviceFeatures(gpu(), &feat);
3853         if (!feat.tessellationShader) {
3854             printf("%s tessellation shader stage(s) unsupported.\n", kSkipPrefix);
3855             return;
3856         }
3857 
3858         // Tessellation control stage
3859         std::string tcsSourceStr =
3860             "#version 450\n"
3861             "\n";
3862         // Input components
3863         const uint32_t maxTescInComp = m_device->props.limits.maxTessellationControlPerVertexInputComponents + overflow;
3864         const uint32_t numInVec4 = maxTescInComp / 4;
3865         uint32_t inLocation = 0;
3866         for (uint32_t i = 0; i < numInVec4; i++) {
3867             tcsSourceStr += "layout(location=" + std::to_string(inLocation) + ") in vec4 v" + std::to_string(i) + "In[];\n";
3868             inLocation += 1;
3869         }
3870         const uint32_t inRemainder = maxTescInComp % 4;
3871         if (inRemainder != 0) {
3872             if (inRemainder == 1) {
3873                 tcsSourceStr += "layout(location=" + std::to_string(inLocation) + ") in float" + " vnIn[];\n";
3874             } else {
3875                 tcsSourceStr +=
3876                     "layout(location=" + std::to_string(inLocation) + ") in vec" + std::to_string(inRemainder) + " vnIn[];\n";
3877             }
3878             inLocation += 1;
3879         }
3880 
3881         // Output components
3882         const uint32_t maxTescOutComp = m_device->props.limits.maxTessellationControlPerVertexOutputComponents + overflow;
3883         const uint32_t numOutVec4 = maxTescOutComp / 4;
3884         uint32_t outLocation = 0;
3885         for (uint32_t i = 0; i < numOutVec4; i++) {
3886             tcsSourceStr += "layout(location=" + std::to_string(outLocation) + ") out vec4 v" + std::to_string(i) + "Out[3];\n";
3887             outLocation += 1;
3888         }
3889         const uint32_t outRemainder = maxTescOutComp % 4;
3890         if (outRemainder != 0) {
3891             if (outRemainder == 1) {
3892                 tcsSourceStr += "layout(location=" + std::to_string(outLocation) + ") out float" + " vnOut[3];\n";
3893             } else {
3894                 tcsSourceStr +=
3895                     "layout(location=" + std::to_string(outLocation) + ") out vec" + std::to_string(outRemainder) + " vnOut[3];\n";
3896             }
3897             outLocation += 1;
3898         }
3899 
3900         tcsSourceStr += "layout(vertices=3) out;\n";
3901         // Finalize
3902         tcsSourceStr +=
3903             "\n"
3904             "void main(){\n"
3905             "}\n";
3906 
3907         VkShaderObj tcs(m_device, tcsSourceStr.c_str(), VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this);
3908         VkShaderObj tes(m_device, bindStateTeshaderText, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this);
3909 
3910         VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = {};
3911         inputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
3912         inputAssemblyInfo.pNext = NULL;
3913         inputAssemblyInfo.flags = 0;
3914         inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
3915         inputAssemblyInfo.primitiveRestartEnable = VK_FALSE;
3916 
3917         VkPipelineTessellationStateCreateInfo tessInfo = {};
3918         tessInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
3919         tessInfo.pNext = NULL;
3920         tessInfo.flags = 0;
3921         tessInfo.patchControlPoints = 3;
3922 
3923         m_errorMonitor->SetUnexpectedError("UNASSIGNED-CoreValidation-Shader-InputNotProduced");
3924 
3925         const auto set_info = [&](CreatePipelineHelper &helper) {
3926             helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), tcs.GetStageCreateInfo(), tes.GetStageCreateInfo(),
3927                                      helper.fs_->GetStageCreateInfo()};
3928             helper.gp_ci_.pTessellationState = &tessInfo;
3929             helper.gp_ci_.pInputAssemblyState = &inputAssemblyInfo;
3930         };
3931         if (overflow) {
3932             CreatePipelineHelper::OneshotTest(
3933                 *this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
3934                 vector<string>{
3935                     "Tessellation control shader exceeds VkPhysicalDeviceLimits::maxTessellationControlPerVertexInputComponents",
3936                     "Tessellation control shader exceeds VkPhysicalDeviceLimits::maxTessellationControlPerVertexOutputComponents"});
3937         } else {
3938             CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "", true);
3939         }
3940     }
3941 }
3942 
TEST_F(VkLayerTest,CreatePipelineExceedMaxTessellationEvaluationInputOutputComponents)3943 TEST_F(VkLayerTest, CreatePipelineExceedMaxTessellationEvaluationInputOutputComponents) {
3944     TEST_DESCRIPTION(
3945         "Test that errors are produced when the number of input and/or output components to the tessellation evaluation stage "
3946         "exceeds the device limit");
3947 
3948     ASSERT_NO_FATAL_FAILURE(Init());
3949     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3950 
3951     for (int overflow = 0; overflow < 2; ++overflow) {
3952         m_errorMonitor->Reset();
3953         VkPhysicalDeviceFeatures feat;
3954         vkGetPhysicalDeviceFeatures(gpu(), &feat);
3955         if (!feat.tessellationShader) {
3956             printf("%s tessellation shader stage(s) unsupported.\n", kSkipPrefix);
3957             return;
3958         }
3959 
3960         // Tessellation evaluation stage
3961         std::string tesSourceStr =
3962             "#version 450\n"
3963             "\n"
3964             "layout (triangles) in;\n"
3965             "\n";
3966         // Input components
3967         const uint32_t maxTeseInComp = m_device->props.limits.maxTessellationEvaluationInputComponents + overflow;
3968         const uint32_t numInVec4 = maxTeseInComp / 4;
3969         uint32_t inLocation = 0;
3970         for (uint32_t i = 0; i < numInVec4; i++) {
3971             tesSourceStr += "layout(location=" + std::to_string(inLocation) + ") in vec4 v" + std::to_string(i) + "In[];\n";
3972             inLocation += 1;
3973         }
3974         const uint32_t inRemainder = maxTeseInComp % 4;
3975         if (inRemainder != 0) {
3976             if (inRemainder == 1) {
3977                 tesSourceStr += "layout(location=" + std::to_string(inLocation) + ") in float" + " vnIn[];\n";
3978             } else {
3979                 tesSourceStr +=
3980                     "layout(location=" + std::to_string(inLocation) + ") in vec" + std::to_string(inRemainder) + " vnIn[];\n";
3981             }
3982             inLocation += 1;
3983         }
3984 
3985         // Output components
3986         const uint32_t maxTeseOutComp = m_device->props.limits.maxTessellationEvaluationOutputComponents + overflow;
3987         const uint32_t numOutVec4 = maxTeseOutComp / 4;
3988         uint32_t outLocation = 0;
3989         for (uint32_t i = 0; i < numOutVec4; i++) {
3990             tesSourceStr += "layout(location=" + std::to_string(outLocation) + ") out vec4 v" + std::to_string(i) + "Out;\n";
3991             outLocation += 1;
3992         }
3993         const uint32_t outRemainder = maxTeseOutComp % 4;
3994         if (outRemainder != 0) {
3995             if (outRemainder == 1) {
3996                 tesSourceStr += "layout(location=" + std::to_string(outLocation) + ") out float" + " vnOut;\n";
3997             } else {
3998                 tesSourceStr +=
3999                     "layout(location=" + std::to_string(outLocation) + ") out vec" + std::to_string(outRemainder) + " vnOut;\n";
4000             }
4001             outLocation += 1;
4002         }
4003 
4004         // Finalize
4005         tesSourceStr +=
4006             "\n"
4007             "void main(){\n"
4008             "}\n";
4009 
4010         VkShaderObj tcs(m_device, bindStateTscShaderText, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this);
4011         VkShaderObj tes(m_device, tesSourceStr.c_str(), VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this);
4012 
4013         VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = {};
4014         inputAssemblyInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
4015         inputAssemblyInfo.pNext = NULL;
4016         inputAssemblyInfo.flags = 0;
4017         inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
4018         inputAssemblyInfo.primitiveRestartEnable = VK_FALSE;
4019 
4020         VkPipelineTessellationStateCreateInfo tessInfo = {};
4021         tessInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
4022         tessInfo.pNext = NULL;
4023         tessInfo.flags = 0;
4024         tessInfo.patchControlPoints = 3;
4025 
4026         m_errorMonitor->SetUnexpectedError("UNASSIGNED-CoreValidation-Shader-InputNotProduced");
4027 
4028         const auto set_info = [&](CreatePipelineHelper &helper) {
4029             helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), tcs.GetStageCreateInfo(), tes.GetStageCreateInfo(),
4030                                      helper.fs_->GetStageCreateInfo()};
4031             helper.gp_ci_.pTessellationState = &tessInfo;
4032             helper.gp_ci_.pInputAssemblyState = &inputAssemblyInfo;
4033         };
4034         if (overflow) {
4035             CreatePipelineHelper::OneshotTest(
4036                 *this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4037                 vector<string>{
4038                     "Tessellation evaluation shader exceeds VkPhysicalDeviceLimits::maxTessellationEvaluationInputComponents",
4039                     "Tessellation evaluation shader exceeds VkPhysicalDeviceLimits::maxTessellationEvaluationOutputComponents"});
4040         } else {
4041             CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "", true);
4042         }
4043     }
4044 }
4045 
TEST_F(VkLayerTest,CreatePipelineExceedMaxGeometryInputOutputComponents)4046 TEST_F(VkLayerTest, CreatePipelineExceedMaxGeometryInputOutputComponents) {
4047     TEST_DESCRIPTION(
4048         "Test that errors are produced when the number of input and/or output components to the geometry stage exceeds the device "
4049         "limit");
4050 
4051     ASSERT_NO_FATAL_FAILURE(Init());
4052     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4053 
4054     for (int overflow = 0; overflow < 2; ++overflow) {
4055         m_errorMonitor->Reset();
4056         VkPhysicalDeviceFeatures feat;
4057         vkGetPhysicalDeviceFeatures(gpu(), &feat);
4058         if (!feat.geometryShader) {
4059             printf("%s geometry shader stage unsupported.\n", kSkipPrefix);
4060             return;
4061         }
4062 
4063         std::string gsSourceStr =
4064             "#version 450\n"
4065             "\n"
4066             "layout(triangles) in;\n"
4067             "layout(invocations=1) in;\n";
4068 
4069         // Input components
4070         const uint32_t maxGeomInComp = m_device->props.limits.maxGeometryInputComponents + overflow;
4071         const uint32_t numInVec4 = maxGeomInComp / 4;
4072         uint32_t inLocation = 0;
4073         for (uint32_t i = 0; i < numInVec4; i++) {
4074             gsSourceStr += "layout(location=" + std::to_string(inLocation) + ") in vec4 v" + std::to_string(i) + "In[];\n";
4075             inLocation += 1;
4076         }
4077         const uint32_t inRemainder = maxGeomInComp % 4;
4078         if (inRemainder != 0) {
4079             if (inRemainder == 1) {
4080                 gsSourceStr += "layout(location=" + std::to_string(inLocation) + ") in float" + " vnIn[];\n";
4081             } else {
4082                 gsSourceStr +=
4083                     "layout(location=" + std::to_string(inLocation) + ") in vec" + std::to_string(inRemainder) + " vnIn[];\n";
4084             }
4085             inLocation += 1;
4086         }
4087 
4088         // Output components
4089         const uint32_t maxGeomOutComp = m_device->props.limits.maxGeometryOutputComponents + overflow;
4090         const uint32_t numOutVec4 = maxGeomOutComp / 4;
4091         uint32_t outLocation = 0;
4092         for (uint32_t i = 0; i < numOutVec4; i++) {
4093             gsSourceStr += "layout(location=" + std::to_string(outLocation) + ") out vec4 v" + std::to_string(i) + "Out;\n";
4094             outLocation += 1;
4095         }
4096         const uint32_t outRemainder = maxGeomOutComp % 4;
4097         if (outRemainder != 0) {
4098             if (outRemainder == 1) {
4099                 gsSourceStr += "layout(location=" + std::to_string(outLocation) + ") out float" + " vnOut;\n";
4100             } else {
4101                 gsSourceStr +=
4102                     "layout(location=" + std::to_string(outLocation) + ") out vec" + std::to_string(outRemainder) + " vnOut;\n";
4103             }
4104             outLocation += 1;
4105         }
4106 
4107         // Finalize
4108         int max_vertices = overflow ? (m_device->props.limits.maxGeometryTotalOutputComponents / maxGeomOutComp + 1) : 1;
4109         gsSourceStr += "layout(triangle_strip, max_vertices = " + std::to_string(max_vertices) +
4110                        ") out;\n"
4111                        "\n"
4112                        "void main(){\n"
4113                        "}\n";
4114 
4115         VkShaderObj gs(m_device, gsSourceStr.c_str(), VK_SHADER_STAGE_GEOMETRY_BIT, this);
4116 
4117         m_errorMonitor->SetUnexpectedError("UNASSIGNED-CoreValidation-Shader-InputNotProduced");
4118 
4119         const auto set_info = [&](CreatePipelineHelper &helper) {
4120             helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), gs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
4121         };
4122         if (overflow) {
4123             CreatePipelineHelper::OneshotTest(
4124                 *this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4125                 vector<string>{"Geometry shader exceeds VkPhysicalDeviceLimits::maxGeometryInputComponents",
4126                                "Geometry shader exceeds VkPhysicalDeviceLimits::maxGeometryOutputComponents",
4127                                "Geometry shader exceeds VkPhysicalDeviceLimits::maxGeometryTotalOutputComponents"});
4128         } else {
4129             CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "", true);
4130         }
4131     }
4132 }
4133 
TEST_F(VkLayerTest,CreatePipelineExceedMaxFragmentInputComponents)4134 TEST_F(VkLayerTest, CreatePipelineExceedMaxFragmentInputComponents) {
4135     TEST_DESCRIPTION(
4136         "Test that an error is produced when the number of input components from the fragment stage exceeds the device limit");
4137 
4138     ASSERT_NO_FATAL_FAILURE(Init());
4139     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4140 
4141     for (int overflow = 0; overflow < 2; ++overflow) {
4142         m_errorMonitor->Reset();
4143 
4144         const uint32_t maxFsInComp = m_device->props.limits.maxFragmentInputComponents + overflow;
4145         std::string fsSourceStr = "#version 450\n\n";
4146         const uint32_t numVec4 = maxFsInComp / 4;
4147         uint32_t location = 0;
4148         for (uint32_t i = 0; i < numVec4; i++) {
4149             fsSourceStr += "layout(location=" + std::to_string(location) + ") in vec4 v" + std::to_string(i) + ";\n";
4150             location += 1;
4151         }
4152         const uint32_t remainder = maxFsInComp % 4;
4153         if (remainder != 0) {
4154             if (remainder == 1) {
4155                 fsSourceStr += "layout(location=" + std::to_string(location) + ") in float" + " vn;\n";
4156             } else {
4157                 fsSourceStr += "layout(location=" + std::to_string(location) + ") in vec" + std::to_string(remainder) + " vn;\n";
4158             }
4159             location += 1;
4160         }
4161         fsSourceStr +=
4162             "layout(location=0) out vec4 color;"
4163             "\n"
4164             "void main(){\n"
4165             "    color = vec4(1);\n"
4166             "}\n";
4167         VkShaderObj fs(m_device, fsSourceStr.c_str(), VK_SHADER_STAGE_FRAGMENT_BIT, this);
4168 
4169         m_errorMonitor->SetUnexpectedError("UNASSIGNED-CoreValidation-Shader-InputNotProduced");
4170         const auto set_info = [&](CreatePipelineHelper &helper) {
4171             helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
4172         };
4173         if (overflow) {
4174             CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4175                                               "Fragment shader exceeds "
4176                                               "VkPhysicalDeviceLimits::maxFragmentInputComponents");
4177         } else {
4178             CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "", true);
4179         }
4180     }
4181 }
4182 
TEST_F(VkLayerTest,CreatePipelineExceedMaxGeometryInstanceVertexCount)4183 TEST_F(VkLayerTest, CreatePipelineExceedMaxGeometryInstanceVertexCount) {
4184     TEST_DESCRIPTION(
4185         "Test that errors are produced when the number of output vertices/instances in the geometry stage exceeds the device "
4186         "limit");
4187 
4188     ASSERT_NO_FATAL_FAILURE(Init());
4189     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4190 
4191     for (int overflow = 0; overflow < 2; ++overflow) {
4192         m_errorMonitor->Reset();
4193         VkPhysicalDeviceFeatures feat;
4194         vkGetPhysicalDeviceFeatures(gpu(), &feat);
4195         if (!feat.geometryShader) {
4196             printf("%s geometry shader stage unsupported.\n", kSkipPrefix);
4197             return;
4198         }
4199 
4200         std::string gsSourceStr = R"(
4201                OpCapability Geometry
4202                OpMemoryModel Logical GLSL450
4203                OpEntryPoint Geometry %main "main"
4204                OpExecutionMode %main InputPoints
4205                OpExecutionMode %main OutputTriangleStrip
4206                )";
4207         if (overflow) {
4208             gsSourceStr += "OpExecutionMode %main Invocations " +
4209                            std::to_string(m_device->props.limits.maxGeometryShaderInvocations + 1) +
4210                            "\n\
4211                 OpExecutionMode %main OutputVertices " +
4212                            std::to_string(m_device->props.limits.maxGeometryOutputVertices + 1);
4213         } else {
4214             gsSourceStr += R"(
4215                OpExecutionMode %main Invocations 1
4216                OpExecutionMode %main OutputVertices 1
4217                )";
4218         }
4219         gsSourceStr += R"(
4220                OpSource GLSL 450
4221        %void = OpTypeVoid
4222           %3 = OpTypeFunction %void
4223        %main = OpFunction %void None %3
4224           %5 = OpLabel
4225                OpReturn
4226                OpFunctionEnd
4227         )";
4228         VkShaderObj gs(m_device, gsSourceStr, VK_SHADER_STAGE_GEOMETRY_BIT, this);
4229 
4230         const auto set_info = [&](CreatePipelineHelper &helper) {
4231             helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), gs.GetStageCreateInfo(), helper.fs_->GetStageCreateInfo()};
4232         };
4233         if (overflow) {
4234             CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4235                                               vector<string>{"VUID-VkPipelineShaderStageCreateInfo-stage-00714",
4236                                                              "VUID-VkPipelineShaderStageCreateInfo-stage-00715"});
4237         } else {
4238             CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "", true);
4239         }
4240     }
4241 }
4242 
TEST_F(VkLayerTest,CreatePipelineUniformBlockNotProvided)4243 TEST_F(VkLayerTest, CreatePipelineUniformBlockNotProvided) {
4244     TEST_DESCRIPTION(
4245         "Test that an error is produced for a shader consuming a uniform block which has no corresponding binding in the pipeline "
4246         "layout");
4247     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "not declared in pipeline layout");
4248 
4249     ASSERT_NO_FATAL_FAILURE(Init());
4250 
4251     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
4252     VkShaderObj fs(m_device, bindStateFragUniformShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
4253 
4254     VkPipelineObj pipe(m_device);
4255     pipe.AddShader(&vs);
4256     pipe.AddShader(&fs);
4257 
4258     /* set up CB 0; type is UNORM by default */
4259     pipe.AddDefaultColorAttachment();
4260     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4261 
4262     VkDescriptorSetObj descriptorSet(m_device);
4263     descriptorSet.CreateVKDescriptorSet(m_commandBuffer);
4264 
4265     pipe.CreateVKPipeline(descriptorSet.GetPipelineLayout(), renderPass());
4266 
4267     m_errorMonitor->VerifyFound();
4268 }
4269 
TEST_F(VkLayerTest,CreatePipelinePushConstantsNotInLayout)4270 TEST_F(VkLayerTest, CreatePipelinePushConstantsNotInLayout) {
4271     TEST_DESCRIPTION(
4272         "Test that an error is produced for a shader consuming push constants which are not provided in the pipeline layout");
4273 
4274     ASSERT_NO_FATAL_FAILURE(Init());
4275     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4276 
4277     char const *vsSource =
4278         "#version 450\n"
4279         "\n"
4280         "layout(push_constant, std430) uniform foo { float x; } consts;\n"
4281         "void main(){\n"
4282         "   gl_Position = vec4(consts.x);\n"
4283         "}\n";
4284 
4285     VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
4286 
4287     CreatePipelineHelper pipe(*this);
4288     pipe.InitInfo();
4289     pipe.shader_stages_ = {vs.GetStageCreateInfo(), pipe.fs_->GetStageCreateInfo()};
4290     pipe.InitState();
4291     pipe.pipeline_layout_ = VkPipelineLayoutObj(m_device, {});
4292     /* should have generated an error -- no push constant ranges provided! */
4293     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "not declared in layout");
4294     pipe.CreateGraphicsPipeline();
4295     m_errorMonitor->VerifyFound();
4296 }
4297 
TEST_F(VkLayerTest,CreatePipelineInputAttachmentMissing)4298 TEST_F(VkLayerTest, CreatePipelineInputAttachmentMissing) {
4299     TEST_DESCRIPTION(
4300         "Test that an error is produced for a shader consuming an input attachment which is not included in the subpass "
4301         "description");
4302 
4303     ASSERT_NO_FATAL_FAILURE(Init());
4304     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4305 
4306     char const *fsSource =
4307         "#version 450\n"
4308         "\n"
4309         "layout(input_attachment_index=0, set=0, binding=0) uniform subpassInput x;\n"
4310         "layout(location=0) out vec4 color;\n"
4311         "void main() {\n"
4312         "   color = subpassLoad(x);\n"
4313         "}\n";
4314 
4315     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
4316 
4317     const auto set_info = [&](CreatePipelineHelper &helper) {
4318         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
4319         helper.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}};
4320     };
4321     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4322                                       "consumes input attachment index 0 but not provided in subpass");
4323 }
4324 
TEST_F(VkLayerTest,CreatePipelineInputAttachmentTypeMismatch)4325 TEST_F(VkLayerTest, CreatePipelineInputAttachmentTypeMismatch) {
4326     TEST_DESCRIPTION(
4327         "Test that an error is produced for a shader consuming an input attachment with a format having a different fundamental "
4328         "type");
4329     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4330                                          "input attachment 0 format of VK_FORMAT_R8G8B8A8_UINT does not match");
4331 
4332     ASSERT_NO_FATAL_FAILURE(Init());
4333 
4334     char const *fsSource =
4335         "#version 450\n"
4336         "\n"
4337         "layout(input_attachment_index=0, set=0, binding=0) uniform subpassInput x;\n"
4338         "layout(location=0) out vec4 color;\n"
4339         "void main() {\n"
4340         "   color = subpassLoad(x);\n"
4341         "}\n";
4342 
4343     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
4344     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
4345 
4346     VkPipelineObj pipe(m_device);
4347     pipe.AddShader(&vs);
4348     pipe.AddShader(&fs);
4349     pipe.AddDefaultColorAttachment();
4350     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4351 
4352     VkDescriptorSetLayoutBinding dslb = {0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr};
4353     const VkDescriptorSetLayoutObj dsl(m_device, {dslb});
4354 
4355     const VkPipelineLayoutObj pl(m_device, {&dsl});
4356 
4357     VkAttachmentDescription descs[2] = {
4358         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
4359          VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4360          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
4361         {0, VK_FORMAT_R8G8B8A8_UINT, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
4362          VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL},
4363     };
4364     VkAttachmentReference color = {
4365         0,
4366         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4367     };
4368     VkAttachmentReference input = {
4369         1,
4370         VK_IMAGE_LAYOUT_GENERAL,
4371     };
4372 
4373     VkSubpassDescription sd = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &input, 1, &color, nullptr, nullptr, 0, nullptr};
4374 
4375     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 2, descs, 1, &sd, 0, nullptr};
4376     VkRenderPass rp;
4377     VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp);
4378     ASSERT_VK_SUCCESS(err);
4379 
4380     // error here.
4381     pipe.CreateVKPipeline(pl.handle(), rp);
4382 
4383     m_errorMonitor->VerifyFound();
4384 
4385     vkDestroyRenderPass(m_device->device(), rp, nullptr);
4386 }
4387 
TEST_F(VkLayerTest,CreatePipelineInputAttachmentMissingArray)4388 TEST_F(VkLayerTest, CreatePipelineInputAttachmentMissingArray) {
4389     TEST_DESCRIPTION(
4390         "Test that an error is produced for a shader consuming an input attachment which is not included in the subpass "
4391         "description -- array case");
4392 
4393     ASSERT_NO_FATAL_FAILURE(Init());
4394     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4395 
4396     char const *fsSource =
4397         "#version 450\n"
4398         "\n"
4399         "layout(input_attachment_index=0, set=0, binding=0) uniform subpassInput xs[1];\n"
4400         "layout(location=0) out vec4 color;\n"
4401         "void main() {\n"
4402         "   color = subpassLoad(xs[0]);\n"
4403         "}\n";
4404 
4405     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
4406 
4407     const auto set_info = [&](CreatePipelineHelper &helper) {
4408         helper.shader_stages_ = {helper.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
4409         helper.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr}};
4410     };
4411     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4412                                       "consumes input attachment index 0 but not provided in subpass");
4413 }
4414 
TEST_F(VkLayerTest,CreateComputePipelineMissingDescriptor)4415 TEST_F(VkLayerTest, CreateComputePipelineMissingDescriptor) {
4416     TEST_DESCRIPTION(
4417         "Test that an error is produced for a compute pipeline consuming a descriptor which is not provided in the pipeline "
4418         "layout");
4419 
4420     ASSERT_NO_FATAL_FAILURE(Init());
4421 
4422     char const *csSource =
4423         "#version 450\n"
4424         "\n"
4425         "layout(local_size_x=1) in;\n"
4426         "layout(set=0, binding=0) buffer block { vec4 x; };\n"
4427         "void main(){\n"
4428         "   x = vec4(1);\n"
4429         "}\n";
4430 
4431     CreateComputePipelineHelper pipe(*this);
4432     pipe.InitInfo();
4433     pipe.cs_.reset(new VkShaderObj(m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this));
4434     pipe.InitState();
4435     pipe.pipeline_layout_ = VkPipelineLayoutObj(m_device, {});
4436     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Shader uses descriptor slot 0.0");
4437     pipe.CreateComputePipeline();
4438     m_errorMonitor->VerifyFound();
4439 }
4440 
TEST_F(VkLayerTest,CreateComputePipelineDescriptorTypeMismatch)4441 TEST_F(VkLayerTest, CreateComputePipelineDescriptorTypeMismatch) {
4442     TEST_DESCRIPTION("Test that an error is produced for a pipeline consuming a descriptor-backed resource of a mismatched type");
4443 
4444     ASSERT_NO_FATAL_FAILURE(Init());
4445 
4446     char const *csSource =
4447         "#version 450\n"
4448         "\n"
4449         "layout(local_size_x=1) in;\n"
4450         "layout(set=0, binding=0) buffer block { vec4 x; };\n"
4451         "void main() {\n"
4452         "   x.x = 1.0f;\n"
4453         "}\n";
4454 
4455     const auto set_info = [&](CreateComputePipelineHelper &helper) {
4456         helper.cs_.reset(new VkShaderObj(m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this));
4457         helper.dsl_bindings_ = {{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}};
4458     };
4459     CreateComputePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4460                                              "but descriptor of type VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER");
4461 }
4462 
TEST_F(VkLayerTest,MultiplePushDescriptorSets)4463 TEST_F(VkLayerTest, MultiplePushDescriptorSets) {
4464     TEST_DESCRIPTION("Verify an error message for multiple push descriptor sets.");
4465 
4466     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
4467         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
4468     } else {
4469         printf("%s Did not find VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; skipped.\n", kSkipPrefix);
4470         return;
4471     }
4472     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
4473     if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)) {
4474         m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
4475     } else {
4476         printf("%s Push Descriptors Extension not supported, skipping tests\n", kSkipPrefix);
4477         return;
4478     }
4479     ASSERT_NO_FATAL_FAILURE(InitState());
4480 
4481     auto push_descriptor_prop = GetPushDescriptorProperties(instance(), gpu());
4482     if (push_descriptor_prop.maxPushDescriptors < 1) {
4483         // Some implementations report an invalid maxPushDescriptors of 0
4484         printf("%s maxPushDescriptors is zero, skipping tests\n", kSkipPrefix);
4485         return;
4486     }
4487 
4488     VkDescriptorSetLayoutBinding dsl_binding = {};
4489     dsl_binding.binding = 0;
4490     dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
4491     dsl_binding.descriptorCount = 1;
4492     dsl_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
4493     dsl_binding.pImmutableSamplers = NULL;
4494 
4495     const unsigned int descriptor_set_layout_count = 2;
4496     std::vector<VkDescriptorSetLayoutObj> ds_layouts;
4497     for (uint32_t i = 0; i < descriptor_set_layout_count; ++i) {
4498         dsl_binding.binding = i;
4499         ds_layouts.emplace_back(m_device, std::vector<VkDescriptorSetLayoutBinding>(1, dsl_binding),
4500                                 VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR);
4501     }
4502     const auto &ds_vk_layouts = MakeVkHandles<VkDescriptorSetLayout>(ds_layouts);
4503 
4504     VkPipelineLayout pipeline_layout;
4505     VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
4506     pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
4507     pipeline_layout_ci.pNext = NULL;
4508     pipeline_layout_ci.pushConstantRangeCount = 0;
4509     pipeline_layout_ci.pPushConstantRanges = NULL;
4510     pipeline_layout_ci.setLayoutCount = ds_vk_layouts.size();
4511     pipeline_layout_ci.pSetLayouts = ds_vk_layouts.data();
4512 
4513     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-00293");
4514     vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
4515     m_errorMonitor->VerifyFound();
4516 }
4517 
TEST_F(VkLayerTest,AMDMixedAttachmentSamplesValidateGraphicsPipeline)4518 TEST_F(VkLayerTest, AMDMixedAttachmentSamplesValidateGraphicsPipeline) {
4519     TEST_DESCRIPTION("Verify an error message for an incorrect graphics pipeline rasterization sample count.");
4520 
4521     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
4522     if (DeviceExtensionSupported(gpu(), nullptr, VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME)) {
4523         m_device_extension_names.push_back(VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME);
4524     } else {
4525         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME);
4526         return;
4527     }
4528     ASSERT_NO_FATAL_FAILURE(InitState());
4529     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4530 
4531     // Set a mismatched sample count
4532     VkPipelineMultisampleStateCreateInfo ms_state_ci = {};
4533     ms_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
4534     ms_state_ci.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT;
4535 
4536     const auto set_info = [&](CreatePipelineHelper &helper) { helper.pipe_ms_state_ci_ = ms_state_ci; };
4537     CreatePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4538                                       "VUID-VkGraphicsPipelineCreateInfo-subpass-01505");
4539 }
4540 
TEST_F(VkLayerTest,FramebufferMixedSamplesNV)4541 TEST_F(VkLayerTest, FramebufferMixedSamplesNV) {
4542     TEST_DESCRIPTION("Verify VK_NV_framebuffer_mixed_samples.");
4543 
4544     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
4545 
4546     if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME)) {
4547         m_device_extension_names.push_back(VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME);
4548     } else {
4549         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_NV_FRAMEBUFFER_MIXED_SAMPLES_EXTENSION_NAME);
4550         return;
4551     }
4552 
4553     VkPhysicalDeviceFeatures device_features = {};
4554     ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features));
4555     if (VK_TRUE != device_features.sampleRateShading) {
4556         printf("%s Test requires unsupported sampleRateShading feature.\n", kSkipPrefix);
4557         return;
4558     }
4559 
4560     ASSERT_NO_FATAL_FAILURE(InitState());
4561     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4562 
4563     struct TestCase {
4564         VkSampleCountFlagBits color_samples;
4565         VkSampleCountFlagBits depth_samples;
4566         VkSampleCountFlagBits raster_samples;
4567         VkBool32 depth_test;
4568         VkBool32 sample_shading;
4569         uint32_t table_count;
4570         bool positiveTest;
4571         std::string vuid;
4572     };
4573 
4574     std::vector<TestCase> test_cases = {
4575         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_FALSE, 1, true,
4576          "VUID-VkGraphicsPipelineCreateInfo-subpass-00757"},
4577         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT, VK_FALSE, VK_FALSE, 4, false,
4578          "VUID-VkPipelineCoverageModulationStateCreateInfoNV-coverageModulationTableEnable-01405"},
4579         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT, VK_FALSE, VK_FALSE, 2, true,
4580          "VUID-VkPipelineCoverageModulationStateCreateInfoNV-coverageModulationTableEnable-01405"},
4581         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_TRUE, VK_FALSE, 1, false,
4582          "VUID-VkGraphicsPipelineCreateInfo-subpass-01411"},
4583         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_8_BIT, VK_TRUE, VK_FALSE, 1, true,
4584          "VUID-VkGraphicsPipelineCreateInfo-subpass-01411"},
4585         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_1_BIT, VK_FALSE, VK_FALSE, 1, false,
4586          "VUID-VkGraphicsPipelineCreateInfo-subpass-01412"},
4587         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_FALSE, 1, true,
4588          "VUID-VkGraphicsPipelineCreateInfo-subpass-01412"},
4589         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_TRUE, 1, false,
4590          "VUID-VkPipelineMultisampleStateCreateInfo-rasterizationSamples-01415"},
4591         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_FALSE, VK_FALSE, 1, true,
4592          "VUID-VkPipelineMultisampleStateCreateInfo-rasterizationSamples-01415"},
4593         {VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_FALSE, VK_FALSE, 1, true,
4594          "VUID-VkGraphicsPipelineCreateInfo-subpass-00757"}};
4595 
4596     for (const auto &test_case : test_cases) {
4597         VkAttachmentDescription att[2] = {{}, {}};
4598         att[0].format = VK_FORMAT_R8G8B8A8_UNORM;
4599         att[0].samples = test_case.color_samples;
4600         att[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
4601         att[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
4602 
4603         att[1].format = VK_FORMAT_D24_UNORM_S8_UINT;
4604         att[1].samples = test_case.depth_samples;
4605         att[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
4606         att[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
4607 
4608         VkAttachmentReference cr = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
4609         VkAttachmentReference dr = {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
4610 
4611         VkSubpassDescription sp = {};
4612         sp.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
4613         sp.colorAttachmentCount = 1;
4614         sp.pColorAttachments = &cr;
4615         sp.pResolveAttachments = NULL;
4616         sp.pDepthStencilAttachment = &dr;
4617 
4618         VkRenderPassCreateInfo rpi = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
4619         rpi.attachmentCount = 2;
4620         rpi.pAttachments = att;
4621         rpi.subpassCount = 1;
4622         rpi.pSubpasses = &sp;
4623 
4624         VkRenderPass rp;
4625 
4626         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4627                                              "VUID-VkSubpassDescription-pDepthStencilAttachment-01418");
4628         VkResult err = vkCreateRenderPass(m_device->device(), &rpi, nullptr, &rp);
4629         m_errorMonitor->VerifyNotFound();
4630 
4631         ASSERT_VK_SUCCESS(err);
4632 
4633         VkPipelineDepthStencilStateCreateInfo ds = {VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
4634         VkPipelineCoverageModulationStateCreateInfoNV cmi = {VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV};
4635 
4636         // Create a dummy modulation table that can be used for the positive
4637         // coverageModulationTableCount test.
4638         std::vector<float> cm_table{};
4639 
4640         const auto break_samples = [&cmi, &rp, &ds, &cm_table, &test_case](CreatePipelineHelper &helper) {
4641             cm_table.resize(test_case.raster_samples / test_case.color_samples);
4642 
4643             cmi.flags = 0;
4644             cmi.coverageModulationTableEnable = (test_case.table_count > 1);
4645             cmi.coverageModulationTableCount = test_case.table_count;
4646             cmi.pCoverageModulationTable = cm_table.data();
4647 
4648             ds.depthTestEnable = test_case.depth_test;
4649 
4650             helper.pipe_ms_state_ci_.pNext = &cmi;
4651             helper.pipe_ms_state_ci_.rasterizationSamples = test_case.raster_samples;
4652             helper.pipe_ms_state_ci_.sampleShadingEnable = test_case.sample_shading;
4653 
4654             helper.gp_ci_.renderPass = rp;
4655             helper.gp_ci_.pDepthStencilState = &ds;
4656         };
4657 
4658         CreatePipelineHelper::OneshotTest(*this, break_samples, VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.vuid,
4659                                           test_case.positiveTest);
4660 
4661         vkDestroyRenderPass(m_device->device(), rp, nullptr);
4662     }
4663 }
4664 
TEST_F(VkLayerTest,FramebufferMixedSamples)4665 TEST_F(VkLayerTest, FramebufferMixedSamples) {
4666     TEST_DESCRIPTION("Verify that the expected VUIds are hits when VK_NV_framebuffer_mixed_samples is disabled.");
4667 
4668     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
4669     ASSERT_NO_FATAL_FAILURE(InitState());
4670     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4671 
4672     struct TestCase {
4673         VkSampleCountFlagBits color_samples;
4674         VkSampleCountFlagBits depth_samples;
4675         VkSampleCountFlagBits raster_samples;
4676         bool positiveTest;
4677     };
4678 
4679     std::vector<TestCase> test_cases = {
4680         {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT,
4681          false},  // Fails vkCreateRenderPass and vkCreateGraphicsPipeline
4682         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, false},  // Fails vkCreateGraphicsPipeline
4683         {VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_4_BIT, true}    // Pass
4684     };
4685 
4686     for (const auto &test_case : test_cases) {
4687         VkAttachmentDescription att[2] = {{}, {}};
4688         att[0].format = VK_FORMAT_R8G8B8A8_UNORM;
4689         att[0].samples = test_case.color_samples;
4690         att[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
4691         att[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
4692 
4693         att[1].format = VK_FORMAT_D24_UNORM_S8_UINT;
4694         att[1].samples = test_case.depth_samples;
4695         att[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
4696         att[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
4697 
4698         VkAttachmentReference cr = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
4699         VkAttachmentReference dr = {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
4700 
4701         VkSubpassDescription sp = {};
4702         sp.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
4703         sp.colorAttachmentCount = 1;
4704         sp.pColorAttachments = &cr;
4705         sp.pResolveAttachments = NULL;
4706         sp.pDepthStencilAttachment = &dr;
4707 
4708         VkRenderPassCreateInfo rpi = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
4709         rpi.attachmentCount = 2;
4710         rpi.pAttachments = att;
4711         rpi.subpassCount = 1;
4712         rpi.pSubpasses = &sp;
4713 
4714         VkRenderPass rp;
4715 
4716         if (test_case.color_samples == test_case.depth_samples) {
4717             m_errorMonitor->ExpectSuccess();
4718         } else {
4719             m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4720                                                  "VUID-VkSubpassDescription-pDepthStencilAttachment-01418");
4721         }
4722 
4723         VkResult err = vkCreateRenderPass(m_device->device(), &rpi, nullptr, &rp);
4724 
4725         if (test_case.color_samples == test_case.depth_samples) {
4726             m_errorMonitor->VerifyNotFound();
4727         } else {
4728             m_errorMonitor->VerifyFound();
4729             continue;
4730         }
4731 
4732         ASSERT_VK_SUCCESS(err);
4733 
4734         VkPipelineDepthStencilStateCreateInfo ds = {VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO};
4735 
4736         const auto break_samples = [&rp, &ds, &test_case](CreatePipelineHelper &helper) {
4737             helper.pipe_ms_state_ci_.rasterizationSamples = test_case.raster_samples;
4738 
4739             helper.gp_ci_.renderPass = rp;
4740             helper.gp_ci_.pDepthStencilState = &ds;
4741         };
4742 
4743         CreatePipelineHelper::OneshotTest(*this, break_samples, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4744                                           "VUID-VkGraphicsPipelineCreateInfo-subpass-00757", test_case.positiveTest);
4745 
4746         vkDestroyRenderPass(m_device->device(), rp, nullptr);
4747     }
4748 }
4749 
TEST_F(VkLayerTest,FragmentCoverageToColorNV)4750 TEST_F(VkLayerTest, FragmentCoverageToColorNV) {
4751     TEST_DESCRIPTION("Verify VK_NV_fragment_coverage_to_color.");
4752 
4753     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
4754 
4755     if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME)) {
4756         m_device_extension_names.push_back(VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME);
4757     } else {
4758         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_NV_FRAGMENT_COVERAGE_TO_COLOR_EXTENSION_NAME);
4759         return;
4760     }
4761 
4762     ASSERT_NO_FATAL_FAILURE(InitState());
4763     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4764 
4765     struct TestCase {
4766         VkFormat format;
4767         VkBool32 enabled;
4768         uint32_t location;
4769         bool positive;
4770     };
4771 
4772     const std::array<TestCase, 9> test_cases = {{
4773         {VK_FORMAT_R8G8B8A8_UNORM, VK_FALSE, 0, true},
4774         {VK_FORMAT_R8_UINT, VK_TRUE, 1, true},
4775         {VK_FORMAT_R16_UINT, VK_TRUE, 1, true},
4776         {VK_FORMAT_R16_SINT, VK_TRUE, 1, true},
4777         {VK_FORMAT_R32_UINT, VK_TRUE, 1, true},
4778         {VK_FORMAT_R32_SINT, VK_TRUE, 1, true},
4779         {VK_FORMAT_R32_SINT, VK_TRUE, 2, false},
4780         {VK_FORMAT_R8_SINT, VK_TRUE, 3, false},
4781         {VK_FORMAT_R8G8B8A8_UNORM, VK_TRUE, 1, false},
4782     }};
4783 
4784     for (const auto &test_case : test_cases) {
4785         std::array<VkAttachmentDescription, 2> att = {{{}, {}}};
4786         att[0].format = VK_FORMAT_R8G8B8A8_UNORM;
4787         att[0].samples = VK_SAMPLE_COUNT_1_BIT;
4788         att[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
4789         att[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
4790 
4791         att[1].format = VK_FORMAT_R8G8B8A8_UNORM;
4792         att[1].samples = VK_SAMPLE_COUNT_1_BIT;
4793         att[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
4794         att[1].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
4795 
4796         if (test_case.location < att.size()) {
4797             att[test_case.location].format = test_case.format;
4798         }
4799 
4800         const std::array<VkAttachmentReference, 3> cr = {{{0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
4801                                                           {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
4802                                                           {VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}}};
4803 
4804         VkSubpassDescription sp = {};
4805         sp.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
4806         sp.colorAttachmentCount = cr.size();
4807         sp.pColorAttachments = cr.data();
4808 
4809         VkRenderPassCreateInfo rpi = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO};
4810         rpi.attachmentCount = att.size();
4811         rpi.pAttachments = att.data();
4812         rpi.subpassCount = 1;
4813         rpi.pSubpasses = &sp;
4814 
4815         const std::array<VkPipelineColorBlendAttachmentState, 3> cba = {{{}, {}, {}}};
4816 
4817         VkPipelineColorBlendStateCreateInfo cbi = {VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO};
4818         cbi.attachmentCount = cba.size();
4819         cbi.pAttachments = cba.data();
4820 
4821         VkRenderPass rp;
4822         VkResult err = vkCreateRenderPass(m_device->device(), &rpi, nullptr, &rp);
4823         ASSERT_VK_SUCCESS(err);
4824 
4825         VkPipelineCoverageToColorStateCreateInfoNV cci = {VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV};
4826 
4827         const auto break_samples = [&cci, &cbi, &rp, &test_case](CreatePipelineHelper &helper) {
4828             cci.coverageToColorEnable = test_case.enabled;
4829             cci.coverageToColorLocation = test_case.location;
4830 
4831             helper.pipe_ms_state_ci_.pNext = &cci;
4832             helper.gp_ci_.renderPass = rp;
4833             helper.gp_ci_.pColorBlendState = &cbi;
4834         };
4835 
4836         CreatePipelineHelper::OneshotTest(*this, break_samples, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4837                                           "VUID-VkPipelineCoverageToColorStateCreateInfoNV-coverageToColorEnable-01404",
4838                                           test_case.positive);
4839 
4840         vkDestroyRenderPass(m_device->device(), rp, nullptr);
4841     }
4842 }
4843 
TEST_F(VkLayerTest,ViewportSwizzleNV)4844 TEST_F(VkLayerTest, ViewportSwizzleNV) {
4845     TEST_DESCRIPTION("Verify VK_NV_viewprot_swizzle.");
4846 
4847     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
4848 
4849     if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME)) {
4850         m_device_extension_names.push_back(VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME);
4851     } else {
4852         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_NV_VIEWPORT_SWIZZLE_EXTENSION_NAME);
4853         return;
4854     }
4855 
4856     ASSERT_NO_FATAL_FAILURE(InitState());
4857     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4858 
4859     VkViewportSwizzleNV invalid_swizzles = {
4860         VkViewportCoordinateSwizzleNV(-1),
4861         VkViewportCoordinateSwizzleNV(-1),
4862         VkViewportCoordinateSwizzleNV(-1),
4863         VkViewportCoordinateSwizzleNV(-1),
4864     };
4865 
4866     VkPipelineViewportSwizzleStateCreateInfoNV vp_swizzle_state = {
4867         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_SWIZZLE_STATE_CREATE_INFO_NV};
4868     vp_swizzle_state.viewportCount = 1;
4869     vp_swizzle_state.pViewportSwizzles = &invalid_swizzles;
4870 
4871     const std::vector<std::string> expected_vuids = {"VUID-VkViewportSwizzleNV-x-parameter", "VUID-VkViewportSwizzleNV-y-parameter",
4872                                                      "VUID-VkViewportSwizzleNV-z-parameter",
4873                                                      "VUID-VkViewportSwizzleNV-w-parameter"};
4874 
4875     auto break_swizzles = [&vp_swizzle_state](CreatePipelineHelper &helper) { helper.vp_state_ci_.pNext = &vp_swizzle_state; };
4876 
4877     CreatePipelineHelper::OneshotTest(*this, break_swizzles, VK_DEBUG_REPORT_ERROR_BIT_EXT, expected_vuids);
4878 
4879     struct TestCase {
4880         VkBool32 rasterizerDiscardEnable;
4881         uint32_t vp_count;
4882         uint32_t swizzel_vp_count;
4883         bool positive;
4884     };
4885 
4886     const std::array<TestCase, 3> test_cases = {{{VK_TRUE, 1, 2, true}, {VK_FALSE, 1, 1, true}, {VK_FALSE, 1, 2, false}}};
4887 
4888     std::array<VkViewportSwizzleNV, 2> swizzles = {
4889         {{VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV,
4890           VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV},
4891          {VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_X_NV, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Y_NV,
4892           VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_Z_NV, VK_VIEWPORT_COORDINATE_SWIZZLE_POSITIVE_W_NV}}};
4893 
4894     for (const auto &test_case : test_cases) {
4895         assert(test_case.vp_count <= swizzles.size());
4896 
4897         vp_swizzle_state.viewportCount = test_case.swizzel_vp_count;
4898         vp_swizzle_state.pViewportSwizzles = swizzles.data();
4899 
4900         auto break_vp_count = [&vp_swizzle_state, &test_case](CreatePipelineHelper &helper) {
4901             helper.rs_state_ci_.rasterizerDiscardEnable = test_case.rasterizerDiscardEnable;
4902             helper.vp_state_ci_.viewportCount = test_case.vp_count;
4903 
4904             helper.vp_state_ci_.pNext = &vp_swizzle_state;
4905         };
4906 
4907         CreatePipelineHelper::OneshotTest(*this, break_vp_count, VK_DEBUG_REPORT_ERROR_BIT_EXT,
4908                                           "VUID-VkPipelineViewportSwizzleStateCreateInfoNV-viewportCount-01215",
4909                                           test_case.positive);
4910     }
4911 }
4912 
TEST_F(VkLayerTest,CooperativeMatrixNV)4913 TEST_F(VkLayerTest, CooperativeMatrixNV) {
4914     TEST_DESCRIPTION("Test VK_NV_cooperative_matrix.");
4915 
4916     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
4917         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
4918     } else {
4919         printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix,
4920                VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
4921         return;
4922     }
4923     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
4924     std::array<const char *, 2> required_device_extensions = {
4925         {VK_NV_COOPERATIVE_MATRIX_EXTENSION_NAME, VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME}};
4926     for (auto device_extension : required_device_extensions) {
4927         if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) {
4928             m_device_extension_names.push_back(device_extension);
4929         } else {
4930             printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension);
4931             return;
4932         }
4933     }
4934 
4935     if (DeviceIsMockICD() || DeviceSimulation()) {
4936         printf("%s Test not supported by MockICD, skipping tests\n", kSkipPrefix);
4937         return;
4938     }
4939 
4940     PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR =
4941         (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR");
4942     ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr);
4943 
4944     auto float16_features = lvl_init_struct<VkPhysicalDeviceFloat16Int8FeaturesKHR>();
4945     auto cooperative_matrix_features = lvl_init_struct<VkPhysicalDeviceCooperativeMatrixFeaturesNV>(&float16_features);
4946     auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&cooperative_matrix_features);
4947     vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2);
4948 
4949     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2));
4950 
4951     std::vector<VkDescriptorSetLayoutBinding> bindings(0);
4952     const VkDescriptorSetLayoutObj dsl(m_device, bindings);
4953     const VkPipelineLayoutObj pl(m_device, {&dsl});
4954 
4955     char const *csSource =
4956         "#version 450\n"
4957         "#extension GL_NV_cooperative_matrix : enable\n"
4958         "#extension GL_KHR_shader_subgroup_basic : enable\n"
4959         "#extension GL_KHR_memory_scope_semantics : enable\n"
4960         "#extension GL_EXT_shader_explicit_arithmetic_types_float16 : enable\n"
4961         "layout(local_size_x = 32) in;\n"
4962         "layout(constant_id = 0) const uint C0 = 1;"
4963         "layout(constant_id = 1) const uint C1 = 1;"
4964         "void main() {\n"
4965         // Bad type
4966         "   fcoopmatNV<16, gl_ScopeSubgroup, 3, 5> badSize = fcoopmatNV<16, gl_ScopeSubgroup, 3, 5>(float16_t(0.0));\n"
4967         // Not a valid multiply when C0 != C1
4968         "   fcoopmatNV<16, gl_ScopeSubgroup, C0, C1> A;\n"
4969         "   fcoopmatNV<16, gl_ScopeSubgroup, C0, C1> B;\n"
4970         "   fcoopmatNV<16, gl_ScopeSubgroup, C0, C1> C;\n"
4971         "   coopMatMulAddNV(A, B, C);\n"
4972         "}\n";
4973 
4974     const uint32_t specData[] = {
4975         16,
4976         8,
4977     };
4978     VkSpecializationMapEntry entries[] = {
4979         {0, sizeof(uint32_t) * 0, sizeof(uint32_t)},
4980         {1, sizeof(uint32_t) * 1, sizeof(uint32_t)},
4981     };
4982 
4983     VkSpecializationInfo specInfo = {
4984         2,
4985         entries,
4986         sizeof(specData),
4987         specData,
4988     };
4989 
4990     CreateComputePipelineHelper pipe(*this);
4991     pipe.InitInfo();
4992     pipe.cs_.reset(new VkShaderObj(m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this, "main", false, &specInfo));
4993     pipe.InitState();
4994     pipe.pipeline_layout_ = VkPipelineLayoutObj(m_device, {});
4995     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-Shader-CooperativeMatrixType");
4996     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-Shader-CooperativeMatrixMulAdd");
4997     pipe.CreateComputePipeline();
4998     m_errorMonitor->VerifyFound();
4999 }
5000 
TEST_F(VkLayerTest,SubgroupSupportedOperations)5001 TEST_F(VkLayerTest, SubgroupSupportedOperations) {
5002     TEST_DESCRIPTION("Test shader validation support for subgroup supportedOperations.");
5003 
5004     SetTargetApiVersion(VK_API_VERSION_1_1);
5005     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
5006     ASSERT_NO_FATAL_FAILURE(InitState());
5007     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
5008 
5009     // 1.1 and up only.
5010     if (m_device->props.apiVersion < VK_API_VERSION_1_1) {
5011         printf("%s Vulkan 1.1 not supported, skipping test\n", kSkipPrefix);
5012         return;
5013     }
5014 
5015     if (DeviceIsMockICD() || DeviceSimulation()) {
5016         printf("%s DevSim doesn't support Vulkan 1.1, skipping tests\n", kSkipPrefix);
5017         return;
5018     }
5019 
5020     VkPhysicalDeviceSubgroupProperties subgroup_prop = GetSubgroupProperties(instance(), gpu());
5021 
5022     // CreatePipelineLayout
5023     VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
5024     pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
5025     pipeline_layout_ci.pNext = NULL;
5026     pipeline_layout_ci.flags = 0;
5027     pipeline_layout_ci.setLayoutCount = 0;
5028     pipeline_layout_ci.pSetLayouts = VK_NULL_HANDLE;
5029     VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
5030     vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
5031 
5032     const std::pair<const char *, VkSubgroupFeatureFlagBits> capabilities[] = {
5033         {"GroupNonUniform", VK_SUBGROUP_FEATURE_BASIC_BIT},
5034         {"GroupNonUniformVote", VK_SUBGROUP_FEATURE_VOTE_BIT},
5035         {"GroupNonUniformArithmetic", VK_SUBGROUP_FEATURE_ARITHMETIC_BIT},
5036         {"GroupNonUniformBallot", VK_SUBGROUP_FEATURE_BALLOT_BIT},
5037         {"GroupNonUniformShuffle", VK_SUBGROUP_FEATURE_SHUFFLE_BIT},
5038         {"GroupNonUniformShuffleRelative", VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT},
5039         {"GroupNonUniformClustered", VK_SUBGROUP_FEATURE_CLUSTERED_BIT},
5040         {"GroupNonUniformQuad", VK_SUBGROUP_FEATURE_QUAD_BIT},
5041     };
5042 
5043     for (auto &capability : capabilities) {
5044         std::string spv_source[3];
5045 
5046         spv_source[0] = "OpCapability " + std::string(capability.first) + "\n" + R"(
5047                    OpCapability Shader
5048                    OpMemoryModel Logical GLSL450
5049                    OpEntryPoint GLCompute %main "main"
5050                    OpExecutionMode %main LocalSize 1 1 1
5051            %void = OpTypeVoid
5052            %func = OpTypeFunction %void
5053            %main = OpFunction %void None %func
5054              %40 = OpLabel
5055                    OpReturn
5056                    OpFunctionEnd
5057         )";
5058 
5059         spv_source[1] = "OpCapability " + std::string(capability.first) + "\n" + R"(
5060                    OpCapability Shader
5061                    OpMemoryModel Logical GLSL450
5062                    OpEntryPoint Vertex %main "main"
5063            %void = OpTypeVoid
5064            %func = OpTypeFunction %void
5065            %main = OpFunction %void None %func
5066              %40 = OpLabel
5067                    OpReturn
5068                    OpFunctionEnd
5069         )";
5070 
5071         spv_source[2] = "OpCapability " + std::string(capability.first) + "\n" + R"(
5072                    OpCapability Shader
5073                    OpMemoryModel Logical GLSL450
5074                    OpEntryPoint Fragment %main "main"
5075                    OpExecutionMode %main OriginUpperLeft
5076            %void = OpTypeVoid
5077            %func = OpTypeFunction %void
5078            %main = OpFunction %void None %func
5079              %40 = OpLabel
5080                    OpReturn
5081                    OpFunctionEnd
5082         )";
5083 
5084         VkShaderModule shader_module[3];
5085         VkPipelineShaderStageCreateInfo stage[3];
5086 
5087         for (int i = 0; i < 3; ++i) {
5088             // CreateShaderModule
5089             std::vector<unsigned int> spv;
5090             VkShaderModuleCreateInfo module_create_info;
5091             module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
5092             module_create_info.pNext = NULL;
5093             ASMtoSPV(SPV_ENV_VULKAN_1_1, 0, spv_source[i].data(), spv);
5094             module_create_info.pCode = spv.data();
5095             module_create_info.codeSize = spv.size() * sizeof(unsigned int);
5096             module_create_info.flags = 0;
5097 
5098             VkResult result = vkCreateShaderModule(m_device->handle(), &module_create_info, NULL, &shader_module[i]);
5099 
5100             // NOTE: It appears that for the case of invalid capabilities some drivers (recent AMD) fail at CreateShaderModule time.
5101             //       Likely the capability test should be moved up to CSM time, implementing ShaderModuleCreateInfo-pCode-01090
5102             //       Note(2) -- yes I truncated the above VUID s.t. the VUID checking tools would not catch it.
5103             if (result != VK_SUCCESS) shader_module[i] = VK_NULL_HANDLE;
5104 
5105             stage[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
5106             stage[i].pNext = nullptr;
5107             stage[i].flags = 0;
5108             // stage[i].stage initialized later;
5109             stage[i].module = shader_module[i];
5110             stage[i].pName = "main";
5111             stage[i].pSpecializationInfo = nullptr;
5112         }
5113 
5114         // CreateComputePipelines
5115         VkComputePipelineCreateInfo pipeline_info = {};
5116         pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
5117         pipeline_info.pNext = nullptr;
5118         pipeline_info.flags = 0;
5119         pipeline_info.layout = pipeline_layout;
5120         pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
5121         pipeline_info.basePipelineIndex = -1;
5122         pipeline_info.stage = stage[0];
5123         pipeline_info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
5124 
5125         if (pipeline_info.stage.module != VK_NULL_HANDLE) {
5126             if (!(subgroup_prop.supportedOperations & capability.second)) {
5127                 m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
5128                                                      "VkPhysicalDeviceSubgroupProperties::supportedOperations");
5129             }
5130             if (!(subgroup_prop.supportedStages & VK_SHADER_STAGE_COMPUTE_BIT)) {
5131                 m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
5132                                                      "VkPhysicalDeviceSubgroupProperties::supportedStages");
5133             }
5134 
5135             VkPipeline cs_pipeline;
5136             vkCreateComputePipelines(device(), VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &cs_pipeline);
5137             vkDestroyPipeline(device(), cs_pipeline, nullptr);
5138 
5139             m_errorMonitor->VerifyFound();
5140         }
5141 
5142         if ((stage[1].module != VK_NULL_HANDLE) && (stage[2].module != VK_NULL_HANDLE)) {
5143             stage[1].stage = VK_SHADER_STAGE_VERTEX_BIT;
5144             stage[2].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
5145 
5146             VkPipelineObj pipe(m_device);
5147             pipe.AddShader(stage[1]);
5148             pipe.AddShader(stage[2]);
5149             pipe.AddDefaultColorAttachment();
5150 
5151             if (!(subgroup_prop.supportedOperations & capability.second)) {
5152                 m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
5153                                                      "VkPhysicalDeviceSubgroupProperties::supportedOperations");
5154             }
5155             if (!(subgroup_prop.supportedStages & VK_SHADER_STAGE_VERTEX_BIT)) {
5156                 m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
5157                                                      "VkPhysicalDeviceSubgroupProperties::supportedStages");
5158             }
5159             if (!(subgroup_prop.supportedOperations & capability.second)) {
5160                 m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
5161                                                      "VkPhysicalDeviceSubgroupProperties::supportedOperations");
5162             }
5163             if (!(subgroup_prop.supportedStages & VK_SHADER_STAGE_FRAGMENT_BIT)) {
5164                 m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
5165                                                      "VkPhysicalDeviceSubgroupProperties::supportedStages");
5166             }
5167             pipe.CreateVKPipeline(pipeline_layout, renderPass());
5168 
5169             m_errorMonitor->VerifyFound();
5170         }
5171 
5172         vkDestroyShaderModule(device(), shader_module[0], nullptr);
5173         vkDestroyShaderModule(device(), shader_module[1], nullptr);
5174         vkDestroyShaderModule(device(), shader_module[2], nullptr);
5175     }
5176 
5177     vkDestroyPipelineLayout(device(), pipeline_layout, nullptr);
5178 }
5179 
TEST_F(VkLayerTest,SubgroupRequired)5180 TEST_F(VkLayerTest, SubgroupRequired) {
5181     TEST_DESCRIPTION("Test that the minimum required functionality for subgroups is present.");
5182 
5183     SetTargetApiVersion(VK_API_VERSION_1_1);
5184     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
5185     ASSERT_NO_FATAL_FAILURE(InitState());
5186 
5187     // 1.1 and up only.
5188     if (m_device->props.apiVersion < VK_API_VERSION_1_1) {
5189         printf("%s Vulkan 1.1 not supported, skipping test\n", kSkipPrefix);
5190         return;
5191     }
5192 
5193     if (DeviceIsMockICD() || DeviceSimulation()) {
5194         printf("%s DevSim doesn't support Vulkan 1.1, skipping tests\n", kSkipPrefix);
5195         return;
5196     }
5197 
5198     VkPhysicalDeviceSubgroupProperties subgroup_prop = GetSubgroupProperties(instance(), gpu());
5199 
5200     auto queue_family_properties = m_device->phy().queue_properties();
5201 
5202     bool foundGraphics = false;
5203     bool foundCompute = false;
5204 
5205     for (auto queue_family : queue_family_properties) {
5206         if (queue_family.queueFlags & VK_QUEUE_COMPUTE_BIT) {
5207             foundCompute = true;
5208             break;
5209         }
5210 
5211         if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
5212             foundGraphics = true;
5213         }
5214     }
5215 
5216     if (!(foundGraphics || foundCompute)) return;
5217 
5218     ASSERT_GE(subgroup_prop.subgroupSize, 1u);
5219 
5220     if (foundCompute) {
5221         ASSERT_TRUE(subgroup_prop.supportedStages & VK_SHADER_STAGE_COMPUTE_BIT);
5222     }
5223 
5224     ASSERT_TRUE(subgroup_prop.supportedOperations & VK_SUBGROUP_FEATURE_BASIC_BIT);
5225 }
5226 
TEST_F(VkLayerTest,GraphicsPipelineStageCreationFeedbackCount)5227 TEST_F(VkLayerTest, GraphicsPipelineStageCreationFeedbackCount) {
5228     TEST_DESCRIPTION("Test graphics pipeline feedback stage count check.");
5229 
5230     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
5231     if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME)) {
5232         m_device_extension_names.push_back(VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME);
5233     } else {
5234         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME);
5235         return;
5236     }
5237     ASSERT_NO_FATAL_FAILURE(InitState());
5238     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
5239 
5240     auto feedback_info = lvl_init_struct<VkPipelineCreationFeedbackCreateInfoEXT>();
5241     VkPipelineCreationFeedbackEXT feedbacks[3] = {};
5242 
5243     feedback_info.pPipelineCreationFeedback = &feedbacks[0];
5244     feedback_info.pipelineStageCreationFeedbackCount = 2;
5245     feedback_info.pPipelineStageCreationFeedbacks = &feedbacks[1];
5246 
5247     auto set_feedback = [&feedback_info](CreatePipelineHelper &helper) { helper.gp_ci_.pNext = &feedback_info; };
5248 
5249     CreatePipelineHelper::OneshotTest(*this, set_feedback, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5250                                       "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02668",
5251                                       true);
5252 
5253     feedback_info.pipelineStageCreationFeedbackCount = 1;
5254     CreatePipelineHelper::OneshotTest(*this, set_feedback, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5255                                       "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02668",
5256                                       false);
5257 }
5258 
TEST_F(VkLayerTest,ComputePipelineStageCreationFeedbackCount)5259 TEST_F(VkLayerTest, ComputePipelineStageCreationFeedbackCount) {
5260     TEST_DESCRIPTION("Test compute pipeline feedback stage count check.");
5261 
5262     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
5263     if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME)) {
5264         m_device_extension_names.push_back(VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME);
5265     } else {
5266         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME);
5267         return;
5268     }
5269     ASSERT_NO_FATAL_FAILURE(InitState());
5270     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
5271 
5272     VkPipelineCreationFeedbackCreateInfoEXT feedback_info = {};
5273     VkPipelineCreationFeedbackEXT feedbacks[3] = {};
5274     feedback_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT;
5275     feedback_info.pPipelineCreationFeedback = &feedbacks[0];
5276     feedback_info.pipelineStageCreationFeedbackCount = 1;
5277     feedback_info.pPipelineStageCreationFeedbacks = &feedbacks[1];
5278 
5279     const auto set_info = [&](CreateComputePipelineHelper &helper) { helper.cp_ci_.pNext = &feedback_info; };
5280 
5281     CreateComputePipelineHelper::OneshotTest(*this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT, "", true);
5282 
5283     feedback_info.pipelineStageCreationFeedbackCount = 2;
5284     CreateComputePipelineHelper::OneshotTest(
5285         *this, set_info, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5286         "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02669");
5287 }
5288 
TEST_F(VkLayerTest,NVRayTracingPipelineStageCreationFeedbackCount)5289 TEST_F(VkLayerTest, NVRayTracingPipelineStageCreationFeedbackCount) {
5290     TEST_DESCRIPTION("Test NV ray tracing pipeline feedback stage count check.");
5291 
5292     if (!CreateNVRayTracingPipelineHelper::InitInstanceExtensions(*this, m_instance_extension_names)) {
5293         return;
5294     }
5295     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
5296 
5297     if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME)) {
5298         m_device_extension_names.push_back(VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME);
5299     } else {
5300         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME);
5301         return;
5302     }
5303 
5304     if (!CreateNVRayTracingPipelineHelper::InitDeviceExtensions(*this, m_device_extension_names)) {
5305         return;
5306     }
5307     ASSERT_NO_FATAL_FAILURE(InitState());
5308 
5309     auto feedback_info = lvl_init_struct<VkPipelineCreationFeedbackCreateInfoEXT>();
5310     VkPipelineCreationFeedbackEXT feedbacks[4] = {};
5311 
5312     feedback_info.pPipelineCreationFeedback = &feedbacks[0];
5313     feedback_info.pipelineStageCreationFeedbackCount = 2;
5314     feedback_info.pPipelineStageCreationFeedbacks = &feedbacks[1];
5315 
5316     auto set_feedback = [&feedback_info](CreateNVRayTracingPipelineHelper &helper) { helper.rp_ci_.pNext = &feedback_info; };
5317 
5318     feedback_info.pipelineStageCreationFeedbackCount = 3;
5319     CreateNVRayTracingPipelineHelper::OneshotPositiveTest(*this, set_feedback);
5320 
5321     feedback_info.pipelineStageCreationFeedbackCount = 2;
5322     CreateNVRayTracingPipelineHelper::OneshotTest(
5323         *this, set_feedback, "VUID-VkPipelineCreationFeedbackCreateInfoEXT-pipelineStageCreationFeedbackCount-02670");
5324 }
5325 
TEST_F(VkLayerTest,CreatePipelineCheckShaderImageFootprintEnabled)5326 TEST_F(VkLayerTest, CreatePipelineCheckShaderImageFootprintEnabled) {
5327     TEST_DESCRIPTION("Create a pipeline requiring the shader image footprint feature which has not enabled on the device.");
5328 
5329     ASSERT_NO_FATAL_FAILURE(Init());
5330 
5331     if (!DeviceExtensionSupported(gpu(), nullptr, VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME)) {
5332         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_NV_SHADER_IMAGE_FOOTPRINT_EXTENSION_NAME);
5333         return;
5334     }
5335 
5336     std::vector<const char *> device_extension_names;
5337     auto features = m_device->phy().features();
5338 
5339     // Disable the image footprint feature.
5340     auto image_footprint_features = lvl_init_struct<VkPhysicalDeviceShaderImageFootprintFeaturesNV>();
5341     image_footprint_features.imageFootprint = VK_FALSE;
5342 
5343     VkDeviceObj test_device(0, gpu(), device_extension_names, &features, &image_footprint_features);
5344 
5345     char const *fsSource =
5346         "#version 450\n"
5347         "#extension GL_NV_shader_texture_footprint  : require\n"
5348         "layout(set=0, binding=0) uniform sampler2D s;\n"
5349         "layout(location=0) out vec4 color;\n"
5350         "void main(){\n"
5351         "  gl_TextureFootprint2DNV footprint;\n"
5352         "  if (textureFootprintNV(s, vec2(1.0), 5, false, footprint)) {\n"
5353         "    color = vec4(0.0, 1.0, 0.0, 1.0);\n"
5354         "  } else {\n"
5355         "    color = vec4(vec2(footprint.anchor), vec2(footprint.offset));\n"
5356         "  }\n"
5357         "}\n";
5358 
5359     VkShaderObj vs(&test_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
5360     VkShaderObj fs(&test_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
5361 
5362     VkRenderpassObj render_pass(&test_device);
5363 
5364     VkPipelineObj pipe(&test_device);
5365     pipe.AddDefaultColorAttachment();
5366     pipe.AddShader(&vs);
5367     pipe.AddShader(&fs);
5368 
5369     VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr};
5370     const VkDescriptorSetLayoutObj ds_layout(&test_device, {binding});
5371     ASSERT_TRUE(ds_layout.initialized());
5372 
5373     const VkPipelineLayoutObj pipeline_layout(&test_device, {&ds_layout});
5374 
5375     m_errorMonitor->SetDesiredFailureMsg(
5376         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5377         "Shader requires VkPhysicalDeviceShaderImageFootprintFeaturesNV::imageFootprint but is not enabled on the device");
5378     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
5379                                          "Shader requires extension VkPhysicalDeviceShaderImageFootprintFeaturesNV::imageFootprint "
5380                                          "but is not enabled on the device");
5381     pipe.CreateVKPipeline(pipeline_layout.handle(), render_pass.handle());
5382     m_errorMonitor->VerifyFound();
5383 }
5384 
TEST_F(VkLayerTest,CreatePipelineCheckFragmentShaderBarycentricEnabled)5385 TEST_F(VkLayerTest, CreatePipelineCheckFragmentShaderBarycentricEnabled) {
5386     TEST_DESCRIPTION("Create a pipeline requiring the fragment shader barycentric feature which has not enabled on the device.");
5387 
5388     ASSERT_NO_FATAL_FAILURE(Init());
5389 
5390     std::vector<const char *> device_extension_names;
5391     auto features = m_device->phy().features();
5392 
5393     // Disable the fragment shader barycentric feature.
5394     auto fragment_shader_barycentric_features = lvl_init_struct<VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV>();
5395     fragment_shader_barycentric_features.fragmentShaderBarycentric = VK_FALSE;
5396 
5397     VkDeviceObj test_device(0, gpu(), device_extension_names, &features, &fragment_shader_barycentric_features);
5398 
5399     char const *fsSource =
5400         "#version 450\n"
5401         "#extension GL_NV_fragment_shader_barycentric : require\n"
5402         "layout(location=0) out float value;\n"
5403         "void main(){\n"
5404         "  value = gl_BaryCoordNV.x;\n"
5405         "}\n";
5406 
5407     VkShaderObj vs(&test_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
5408     VkShaderObj fs(&test_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
5409 
5410     VkRenderpassObj render_pass(&test_device);
5411 
5412     VkPipelineObj pipe(&test_device);
5413     pipe.AddDefaultColorAttachment();
5414     pipe.AddShader(&vs);
5415     pipe.AddShader(&fs);
5416 
5417     const VkPipelineLayoutObj pipeline_layout(&test_device);
5418 
5419     m_errorMonitor->SetDesiredFailureMsg(
5420         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5421         "Shader requires VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV::fragmentShaderBarycentric but is not enabled on the "
5422         "device");
5423     m_errorMonitor->SetDesiredFailureMsg(
5424         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5425         "Shader requires extension VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV::fragmentShaderBarycentric but is not "
5426         "enabled on the device");
5427     pipe.CreateVKPipeline(pipeline_layout.handle(), render_pass.handle());
5428     m_errorMonitor->VerifyFound();
5429 }
5430 
TEST_F(VkLayerTest,CreatePipelineCheckComputeShaderDerivativesEnabled)5431 TEST_F(VkLayerTest, CreatePipelineCheckComputeShaderDerivativesEnabled) {
5432     TEST_DESCRIPTION("Create a pipeline requiring the compute shader derivatives feature which has not enabled on the device.");
5433 
5434     ASSERT_NO_FATAL_FAILURE(Init());
5435 
5436     std::vector<const char *> device_extension_names;
5437     auto features = m_device->phy().features();
5438 
5439     // Disable the compute shader derivatives features.
5440     auto compute_shader_derivatives_features = lvl_init_struct<VkPhysicalDeviceComputeShaderDerivativesFeaturesNV>();
5441     compute_shader_derivatives_features.computeDerivativeGroupLinear = VK_FALSE;
5442     compute_shader_derivatives_features.computeDerivativeGroupQuads = VK_FALSE;
5443 
5444     VkDeviceObj test_device(0, gpu(), device_extension_names, &features, &compute_shader_derivatives_features);
5445 
5446     VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr};
5447     const VkDescriptorSetLayoutObj dsl(&test_device, {binding});
5448     const VkPipelineLayoutObj pl(&test_device, {&dsl});
5449 
5450     char const *csSource =
5451         "#version 450\n"
5452         "#extension GL_NV_compute_shader_derivatives : require\n"
5453         "\n"
5454         "layout(local_size_x=2, local_size_y=4) in;\n"
5455         "layout(derivative_group_quadsNV) in;\n"
5456         "\n"
5457         "layout(set=0, binding=0) buffer InputOutputBuffer {\n"
5458         "  float values[];\n"
5459         "};\n"
5460         "\n"
5461         "void main(){\n"
5462         "   values[gl_LocalInvocationIndex] = dFdx(values[gl_LocalInvocationIndex]);"
5463         "}\n";
5464 
5465     VkShaderObj cs(&test_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this);
5466 
5467     VkComputePipelineCreateInfo cpci = {VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
5468                                         nullptr,
5469                                         0,
5470                                         {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0,
5471                                          VK_SHADER_STAGE_COMPUTE_BIT, cs.handle(), "main", nullptr},
5472                                         pl.handle(),
5473                                         VK_NULL_HANDLE,
5474                                         -1};
5475 
5476     m_errorMonitor->SetDesiredFailureMsg(
5477         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5478         "Shader requires VkPhysicalDeviceComputeShaderDerivativesFeaturesNV::computeDerivativeGroupQuads but is not enabled on the "
5479         "device");
5480     m_errorMonitor->SetDesiredFailureMsg(
5481         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5482         "Shader requires extension VkPhysicalDeviceComputeShaderDerivativesFeaturesNV::computeDerivativeGroupQuads but is not "
5483         "enabled on the device");
5484 
5485     VkPipeline pipe = VK_NULL_HANDLE;
5486     vkCreateComputePipelines(test_device.device(), VK_NULL_HANDLE, 1, &cpci, nullptr, &pipe);
5487     m_errorMonitor->VerifyFound();
5488     vkDestroyPipeline(test_device.device(), pipe, nullptr);
5489     m_errorMonitor->VerifyFound();
5490 }
5491 
TEST_F(VkLayerTest,CreatePipelineCheckFragmentShaderInterlockEnabled)5492 TEST_F(VkLayerTest, CreatePipelineCheckFragmentShaderInterlockEnabled) {
5493     TEST_DESCRIPTION("Create a pipeline requiring the fragment shader interlock feature which has not enabled on the device.");
5494 
5495     ASSERT_NO_FATAL_FAILURE(Init());
5496 
5497     std::vector<const char *> device_extension_names;
5498     if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME)) {
5499         // Note: we intentionally do not add the required extension to the device extension list.
5500         //       in order to create the error below
5501     } else {
5502         // We skip this test if the extension is not supported by the driver as in some cases this will cause
5503         // the vkCreateShaderModule to fail without generating an error message
5504         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_FRAGMENT_SHADER_INTERLOCK_EXTENSION_NAME);
5505         return;
5506     }
5507 
5508     auto features = m_device->phy().features();
5509 
5510     // Disable the fragment shader interlock feature.
5511     auto fragment_shader_interlock_features = lvl_init_struct<VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT>();
5512     fragment_shader_interlock_features.fragmentShaderSampleInterlock = VK_FALSE;
5513     fragment_shader_interlock_features.fragmentShaderPixelInterlock = VK_FALSE;
5514     fragment_shader_interlock_features.fragmentShaderShadingRateInterlock = VK_FALSE;
5515 
5516     VkDeviceObj test_device(0, gpu(), device_extension_names, &features, &fragment_shader_interlock_features);
5517 
5518     char const *fsSource =
5519         "#version 450\n"
5520         "#extension GL_ARB_fragment_shader_interlock : require\n"
5521         "layout(sample_interlock_ordered) in;\n"
5522         "void main(){\n"
5523         "}\n";
5524 
5525     VkShaderObj vs(&test_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
5526     VkShaderObj fs(&test_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
5527 
5528     VkRenderpassObj render_pass(&test_device);
5529 
5530     VkPipelineObj pipe(&test_device);
5531     pipe.AddDefaultColorAttachment();
5532     pipe.AddShader(&vs);
5533     pipe.AddShader(&fs);
5534 
5535     const VkPipelineLayoutObj pipeline_layout(&test_device);
5536 
5537     m_errorMonitor->SetDesiredFailureMsg(
5538         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5539         "Shader requires VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT::fragmentShaderSampleInterlock but is not enabled on "
5540         "the device");
5541     m_errorMonitor->SetDesiredFailureMsg(
5542         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5543         "Shader requires extension VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT::fragmentShaderSampleInterlock but is not "
5544         "enabled on the device");
5545     pipe.CreateVKPipeline(pipeline_layout.handle(), render_pass.handle());
5546     m_errorMonitor->VerifyFound();
5547 }
5548 
TEST_F(VkLayerTest,CreatePipelineCheckDemoteToHelperInvocation)5549 TEST_F(VkLayerTest, CreatePipelineCheckDemoteToHelperInvocation) {
5550     TEST_DESCRIPTION("Create a pipeline requiring the demote to helper invocation feature which has not enabled on the device.");
5551 
5552     ASSERT_NO_FATAL_FAILURE(Init());
5553 
5554     std::vector<const char *> device_extension_names;
5555     if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME)) {
5556         // Note: we intentionally do not add the required extension to the device extension list.
5557         //       in order to create the error below
5558     } else {
5559         // We skip this test if the extension is not supported by the driver as in some cases this will cause
5560         // the vkCreateShaderModule to fail without generating an error message
5561         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
5562         return;
5563     }
5564 
5565     auto features = m_device->phy().features();
5566 
5567     // Disable the demote to helper invocation feature.
5568     auto demote_features = lvl_init_struct<VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT>();
5569     demote_features.shaderDemoteToHelperInvocation = VK_FALSE;
5570 
5571     VkDeviceObj test_device(0, gpu(), device_extension_names, &features, &demote_features);
5572 
5573     char const *fsSource =
5574         "#version 450\n"
5575         "#extension GL_EXT_demote_to_helper_invocation : require\n"
5576         "void main(){\n"
5577         "    demote;\n"
5578         "}\n";
5579 
5580     VkShaderObj vs(&test_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
5581     VkShaderObj fs(&test_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
5582 
5583     VkRenderpassObj render_pass(&test_device);
5584 
5585     VkPipelineObj pipe(&test_device);
5586     pipe.AddDefaultColorAttachment();
5587     pipe.AddShader(&vs);
5588     pipe.AddShader(&fs);
5589 
5590     const VkPipelineLayoutObj pipeline_layout(&test_device);
5591 
5592     m_errorMonitor->SetDesiredFailureMsg(
5593         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5594         "Shader requires VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT::shaderDemoteToHelperInvocation but is not "
5595         "enabled on "
5596         "the device");
5597     m_errorMonitor->SetDesiredFailureMsg(
5598         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5599         "Shader requires extension VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT::shaderDemoteToHelperInvocation but "
5600         "is not "
5601         "enabled on the device");
5602     pipe.CreateVKPipeline(pipeline_layout.handle(), render_pass.handle());
5603     m_errorMonitor->VerifyFound();
5604 }
5605 
TEST_F(VkLayerTest,CreatePipelineCheckLineRasterization)5606 TEST_F(VkLayerTest, CreatePipelineCheckLineRasterization) {
5607     TEST_DESCRIPTION("Test VK_EXT_line_rasterization state against feature enables.");
5608 
5609     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
5610         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
5611     } else {
5612         printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix,
5613                VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
5614         return;
5615     }
5616     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
5617     std::array<const char *, 1> required_device_extensions = {{VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME}};
5618     for (auto device_extension : required_device_extensions) {
5619         if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) {
5620             m_device_extension_names.push_back(device_extension);
5621         } else {
5622             printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension);
5623             return;
5624         }
5625     }
5626 
5627     PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR =
5628         (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR");
5629     ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr);
5630 
5631     auto line_rasterization_features = lvl_init_struct<VkPhysicalDeviceLineRasterizationFeaturesEXT>();
5632     auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&line_rasterization_features);
5633     vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2);
5634 
5635     line_rasterization_features.rectangularLines = VK_FALSE;
5636     line_rasterization_features.bresenhamLines = VK_FALSE;
5637     line_rasterization_features.smoothLines = VK_FALSE;
5638     line_rasterization_features.stippledRectangularLines = VK_FALSE;
5639     line_rasterization_features.stippledBresenhamLines = VK_FALSE;
5640     line_rasterization_features.stippledSmoothLines = VK_FALSE;
5641 
5642     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
5643     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
5644 
5645     CreatePipelineHelper::OneshotTest(
5646         *this,
5647         [&](CreatePipelineHelper &helper) {
5648             helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
5649             helper.pipe_ms_state_ci_.alphaToCoverageEnable = VK_TRUE;
5650         },
5651         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5652         std::vector<const char *>{"VUID-VkGraphicsPipelineCreateInfo-lineRasterizationMode-02766",
5653                                   "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769"});
5654 
5655     CreatePipelineHelper::OneshotTest(
5656         *this,
5657         [&](CreatePipelineHelper &helper) {
5658             helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
5659             helper.line_state_ci_.stippledLineEnable = VK_TRUE;
5660         },
5661         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5662         std::vector<const char *>{"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767",
5663                                   "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02769",
5664                                   "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02772"});
5665 
5666     CreatePipelineHelper::OneshotTest(
5667         *this,
5668         [&](CreatePipelineHelper &helper) {
5669             helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
5670             helper.line_state_ci_.stippledLineEnable = VK_TRUE;
5671         },
5672         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5673         std::vector<const char *>{"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767",
5674                                   "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02768",
5675                                   "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02771"});
5676 
5677     CreatePipelineHelper::OneshotTest(
5678         *this,
5679         [&](CreatePipelineHelper &helper) {
5680             helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT;
5681             helper.line_state_ci_.stippledLineEnable = VK_TRUE;
5682         },
5683         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5684         std::vector<const char *>{"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767",
5685                                   "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-lineRasterizationMode-02770",
5686                                   "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02773"});
5687 
5688     CreatePipelineHelper::OneshotTest(
5689         *this,
5690         [&](CreatePipelineHelper &helper) {
5691             helper.line_state_ci_.lineRasterizationMode = VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
5692             helper.line_state_ci_.stippledLineEnable = VK_TRUE;
5693         },
5694         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5695         std::vector<const char *>{"VUID-VkGraphicsPipelineCreateInfo-stippledLineEnable-02767",
5696                                   "VUID-VkPipelineRasterizationLineStateCreateInfoEXT-stippledLineEnable-02774"});
5697 
5698     PFN_vkCmdSetLineStippleEXT vkCmdSetLineStippleEXT =
5699         (PFN_vkCmdSetLineStippleEXT)vkGetDeviceProcAddr(m_device->device(), "vkCmdSetLineStippleEXT");
5700     ASSERT_TRUE(vkCmdSetLineStippleEXT != nullptr);
5701 
5702     m_commandBuffer->begin();
5703     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdSetLineStippleEXT-lineStippleFactor-02776");
5704     vkCmdSetLineStippleEXT(m_commandBuffer->handle(), 0, 0);
5705     m_errorMonitor->VerifyFound();
5706     vkCmdSetLineStippleEXT(m_commandBuffer->handle(), 1, 1);
5707     m_errorMonitor->VerifyFound();
5708 }
5709 
TEST_F(VkLayerTest,FillRectangleNV)5710 TEST_F(VkLayerTest, FillRectangleNV) {
5711     TEST_DESCRIPTION("Verify VK_NV_fill_rectangle");
5712 
5713     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
5714 
5715     VkPhysicalDeviceFeatures device_features = {};
5716     ASSERT_NO_FATAL_FAILURE(GetPhysicalDeviceFeatures(&device_features));
5717 
5718     // Disable non-solid fill modes to make sure that the usage of VK_POLYGON_MODE_LINE and
5719     // VK_POLYGON_MODE_POINT will cause an error when the VK_NV_fill_rectangle extension is enabled.
5720     device_features.fillModeNonSolid = VK_FALSE;
5721 
5722     if (DeviceExtensionSupported(gpu(), nullptr, VK_NV_FILL_RECTANGLE_EXTENSION_NAME)) {
5723         m_device_extension_names.push_back(VK_NV_FILL_RECTANGLE_EXTENSION_NAME);
5724     } else {
5725         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_NV_FILL_RECTANGLE_EXTENSION_NAME);
5726         return;
5727     }
5728 
5729     ASSERT_NO_FATAL_FAILURE(InitState(&device_features));
5730     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
5731 
5732     VkPolygonMode polygon_mode = VK_POLYGON_MODE_LINE;
5733 
5734     auto set_polygon_mode = [&polygon_mode](CreatePipelineHelper &helper) { helper.rs_state_ci_.polygonMode = polygon_mode; };
5735 
5736     // Set unsupported polygon mode VK_POLYGON_MODE_LINE
5737     CreatePipelineHelper::OneshotTest(*this, set_polygon_mode, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5738                                       "VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01507", false);
5739 
5740     // Set unsupported polygon mode VK_POLYGON_MODE_POINT
5741     polygon_mode = VK_POLYGON_MODE_POINT;
5742     CreatePipelineHelper::OneshotTest(*this, set_polygon_mode, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5743                                       "VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01507", false);
5744 
5745     // Set supported polygon mode VK_POLYGON_MODE_FILL
5746     polygon_mode = VK_POLYGON_MODE_FILL;
5747     CreatePipelineHelper::OneshotTest(*this, set_polygon_mode, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5748                                       "VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01507", true);
5749 
5750     // Set supported polygon mode VK_POLYGON_MODE_FILL_RECTANGLE_NV
5751     polygon_mode = VK_POLYGON_MODE_FILL_RECTANGLE_NV;
5752     CreatePipelineHelper::OneshotTest(*this, set_polygon_mode, VK_DEBUG_REPORT_ERROR_BIT_EXT,
5753                                       "VUID-VkPipelineRasterizationStateCreateInfo-polygonMode-01507", true);
5754 }
5755