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