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,GpuValidationArrayOOBGraphicsShaders)30 TEST_F(VkLayerTest, GpuValidationArrayOOBGraphicsShaders) {
31     TEST_DESCRIPTION(
32         "GPU validation: Verify detection of out-of-bounds descriptor array indexing and use of uninitialized descriptors.");
33     if (!VkRenderFramework::DeviceCanDraw()) {
34         printf("%s GPU-Assisted validation test requires a driver that can draw.\n", kSkipPrefix);
35         return;
36     }
37 
38     VkValidationFeatureEnableEXT enables[] = {VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT};
39     VkValidationFeaturesEXT features = {};
40     features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
41     features.enabledValidationFeatureCount = 1;
42     features.pEnabledValidationFeatures = enables;
43     bool descriptor_indexing = CheckDescriptorIndexingSupportAndInitFramework(this, m_instance_extension_names,
44                                                                               m_device_extension_names, &features, m_errorMonitor);
45     VkPhysicalDeviceFeatures2KHR features2 = {};
46     auto indexing_features = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>();
47     if (descriptor_indexing) {
48         PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR =
49             (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR");
50         ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr);
51 
52         features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&indexing_features);
53         vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2);
54 
55         if (!indexing_features.runtimeDescriptorArray || !indexing_features.descriptorBindingSampledImageUpdateAfterBind ||
56             !indexing_features.descriptorBindingPartiallyBound || !indexing_features.descriptorBindingVariableDescriptorCount ||
57             !indexing_features.shaderSampledImageArrayNonUniformIndexing ||
58             !indexing_features.shaderStorageBufferArrayNonUniformIndexing) {
59             printf("Not all descriptor indexing features supported, skipping descriptor indexing tests\n");
60             descriptor_indexing = false;
61         }
62     }
63 
64     VkCommandPoolCreateFlags pool_flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
65     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2, pool_flags));
66     if (m_device->props.apiVersion < VK_API_VERSION_1_1) {
67         printf("%s GPU-Assisted validation test requires Vulkan 1.1+.\n", kSkipPrefix);
68         return;
69     }
70     ASSERT_NO_FATAL_FAILURE(InitViewport());
71     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
72 
73     // Make a uniform buffer to be passed to the shader that contains the invalid array index.
74     uint32_t qfi = 0;
75     VkBufferCreateInfo bci = {};
76     bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
77     bci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
78     bci.size = 1024;
79     bci.queueFamilyIndexCount = 1;
80     bci.pQueueFamilyIndices = &qfi;
81     VkBufferObj buffer0;
82     VkMemoryPropertyFlags mem_props = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
83     buffer0.init(*m_device, bci, mem_props);
84 
85     bci.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
86     // Make another buffer to populate the buffer array to be indexed
87     VkBufferObj buffer1;
88     buffer1.init(*m_device, bci, mem_props);
89 
90     void *layout_pnext = nullptr;
91     void *allocate_pnext = nullptr;
92     auto pool_create_flags = 0;
93     auto layout_create_flags = 0;
94     VkDescriptorBindingFlagsEXT ds_binding_flags[2] = {};
95     VkDescriptorSetLayoutBindingFlagsCreateInfoEXT layout_createinfo_binding_flags[1] = {};
96     if (descriptor_indexing) {
97         ds_binding_flags[0] = 0;
98         ds_binding_flags[1] = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT;
99 
100         layout_createinfo_binding_flags[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT;
101         layout_createinfo_binding_flags[0].pNext = NULL;
102         layout_createinfo_binding_flags[0].bindingCount = 2;
103         layout_createinfo_binding_flags[0].pBindingFlags = ds_binding_flags;
104         layout_create_flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
105         pool_create_flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
106         layout_pnext = layout_createinfo_binding_flags;
107     }
108 
109     // Prepare descriptors
110     OneOffDescriptorSet descriptor_set(m_device,
111                                        {
112                                            {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
113                                            {1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6, VK_SHADER_STAGE_ALL, nullptr},
114                                        },
115                                        layout_create_flags, layout_pnext, pool_create_flags);
116 
117     VkDescriptorSetVariableDescriptorCountAllocateInfoEXT variable_count = {};
118     uint32_t desc_counts;
119     if (descriptor_indexing) {
120         layout_create_flags = 0;
121         pool_create_flags = 0;
122         ds_binding_flags[1] =
123             VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT;
124         desc_counts = 6;  // We'll reserve 8 spaces in the layout, but the descriptor will only use 6
125         variable_count.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT;
126         variable_count.descriptorSetCount = 1;
127         variable_count.pDescriptorCounts = &desc_counts;
128         allocate_pnext = &variable_count;
129     }
130 
131     OneOffDescriptorSet descriptor_set_variable(m_device,
132                                                 {
133                                                     {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
134                                                     {1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 8, VK_SHADER_STAGE_ALL, nullptr},
135                                                 },
136                                                 layout_create_flags, layout_pnext, pool_create_flags, allocate_pnext);
137 
138     const VkPipelineLayoutObj pipeline_layout(m_device, {&descriptor_set.layout_});
139     const VkPipelineLayoutObj pipeline_layout_variable(m_device, {&descriptor_set_variable.layout_});
140     VkTextureObj texture(m_device, nullptr);
141     VkSamplerObj sampler(m_device);
142 
143     VkDescriptorBufferInfo buffer_info[1] = {};
144     buffer_info[0].buffer = buffer0.handle();
145     buffer_info[0].offset = 0;
146     buffer_info[0].range = sizeof(uint32_t);
147 
148     VkDescriptorImageInfo image_info[6] = {};
149     for (int i = 0; i < 6; i++) {
150         image_info[i] = texture.DescriptorImageInfo();
151         image_info[i].sampler = sampler.handle();
152         image_info[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
153     }
154 
155     VkWriteDescriptorSet descriptor_writes[2] = {};
156     descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
157     descriptor_writes[0].dstSet = descriptor_set.set_;  // descriptor_set;
158     descriptor_writes[0].dstBinding = 0;
159     descriptor_writes[0].descriptorCount = 1;
160     descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
161     descriptor_writes[0].pBufferInfo = buffer_info;
162     descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
163     descriptor_writes[1].dstSet = descriptor_set.set_;  // descriptor_set;
164     descriptor_writes[1].dstBinding = 1;
165     if (descriptor_indexing)
166         descriptor_writes[1].descriptorCount = 5;  // Intentionally don't write index 5
167     else
168         descriptor_writes[1].descriptorCount = 6;
169     descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
170     descriptor_writes[1].pImageInfo = image_info;
171     vkUpdateDescriptorSets(m_device->device(), 2, descriptor_writes, 0, NULL);
172     if (descriptor_indexing) {
173         descriptor_writes[0].dstSet = descriptor_set_variable.set_;
174         descriptor_writes[1].dstSet = descriptor_set_variable.set_;
175         vkUpdateDescriptorSets(m_device->device(), 2, descriptor_writes, 0, NULL);
176     }
177 
178     ds_binding_flags[0] = 0;
179     ds_binding_flags[1] = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT;
180 
181     // Resources for buffer tests
182     OneOffDescriptorSet descriptor_set_buffer(m_device,
183                                               {
184                                                   {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
185                                                   {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 6, VK_SHADER_STAGE_ALL, nullptr},
186                                               },
187                                               0, layout_pnext, 0);
188 
189     const VkPipelineLayoutObj pipeline_layout_buffer(m_device, {&descriptor_set_buffer.layout_});
190 
191     VkDescriptorBufferInfo buffer_test_buffer_info[7] = {};
192     buffer_test_buffer_info[0].buffer = buffer0.handle();
193     buffer_test_buffer_info[0].offset = 0;
194     buffer_test_buffer_info[0].range = sizeof(uint32_t);
195 
196     for (int i = 1; i < 7; i++) {
197         buffer_test_buffer_info[i].buffer = buffer1.handle();
198         buffer_test_buffer_info[i].offset = 0;
199         buffer_test_buffer_info[i].range = 4 * sizeof(float);
200     }
201 
202     if (descriptor_indexing) {
203         VkWriteDescriptorSet buffer_descriptor_writes[2] = {};
204         buffer_descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
205         buffer_descriptor_writes[0].dstSet = descriptor_set_buffer.set_;  // descriptor_set;
206         buffer_descriptor_writes[0].dstBinding = 0;
207         buffer_descriptor_writes[0].descriptorCount = 1;
208         buffer_descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
209         buffer_descriptor_writes[0].pBufferInfo = buffer_test_buffer_info;
210         buffer_descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
211         buffer_descriptor_writes[1].dstSet = descriptor_set_buffer.set_;  // descriptor_set;
212         buffer_descriptor_writes[1].dstBinding = 1;
213         buffer_descriptor_writes[1].descriptorCount = 5;  // Intentionally don't write index 5
214         buffer_descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
215         buffer_descriptor_writes[1].pBufferInfo = &buffer_test_buffer_info[1];
216         vkUpdateDescriptorSets(m_device->device(), 2, buffer_descriptor_writes, 0, NULL);
217     }
218 
219     // Shader programs for array OOB test in vertex stage:
220     // - The vertex shader fetches the invalid index from the uniform buffer and uses it to make an invalid index into another
221     // array.
222     char const *vsSource_vert =
223         "#version 450\n"
224         "\n"
225         "layout(std140, set = 0, binding = 0) uniform foo { uint tex_index[1]; } uniform_index_buffer;\n"
226         "layout(set = 0, binding = 1) uniform sampler2D tex[6];\n"
227         "vec2 vertices[3];\n"
228         "void main(){\n"
229         "      vertices[0] = vec2(-1.0, -1.0);\n"
230         "      vertices[1] = vec2( 1.0, -1.0);\n"
231         "      vertices[2] = vec2( 0.0,  1.0);\n"
232         "   gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n"
233         "   gl_Position += 1e-30 * texture(tex[uniform_index_buffer.tex_index[0]], vec2(0, 0));\n"
234         "}\n";
235     char const *fsSource_vert =
236         "#version 450\n"
237         "\n"
238         "layout(set = 0, binding = 1) uniform sampler2D tex[6];\n"
239         "layout(location = 0) out vec4 uFragColor;\n"
240         "void main(){\n"
241         "   uFragColor = texture(tex[0], vec2(0, 0));\n"
242         "}\n";
243 
244     // Shader programs for array OOB test in fragment stage:
245     // - The vertex shader fetches the invalid index from the uniform buffer and passes it to the fragment shader.
246     // - The fragment shader makes the invalid array access.
247     char const *vsSource_frag =
248         "#version 450\n"
249         "\n"
250         "layout(std140, binding = 0) uniform foo { uint tex_index[1]; } uniform_index_buffer;\n"
251         "layout(location = 0) out flat uint index;\n"
252         "vec2 vertices[3];\n"
253         "void main(){\n"
254         "      vertices[0] = vec2(-1.0, -1.0);\n"
255         "      vertices[1] = vec2( 1.0, -1.0);\n"
256         "      vertices[2] = vec2( 0.0,  1.0);\n"
257         "   gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);\n"
258         "   index = uniform_index_buffer.tex_index[0];\n"
259         "}\n";
260     char const *fsSource_frag =
261         "#version 450\n"
262         "\n"
263         "layout(set = 0, binding = 1) uniform sampler2D tex[6];\n"
264         "layout(location = 0) out vec4 uFragColor;\n"
265         "layout(location = 0) in flat uint index;\n"
266         "void main(){\n"
267         "   uFragColor = texture(tex[index], vec2(0, 0));\n"
268         "}\n";
269     char const *fsSource_frag_runtime =
270         "#version 450\n"
271         "#extension GL_EXT_nonuniform_qualifier : enable\n"
272         "\n"
273         "layout(set = 0, binding = 1) uniform sampler2D tex[];\n"
274         "layout(location = 0) out vec4 uFragColor;\n"
275         "layout(location = 0) in flat uint index;\n"
276         "void main(){\n"
277         "   uFragColor = texture(tex[index], vec2(0, 0));\n"
278         "}\n";
279     char const *fsSource_buffer =
280         "#version 450\n"
281         "#extension GL_EXT_nonuniform_qualifier : enable\n "
282         "\n"
283         "layout(set = 0, binding = 1) buffer foo { vec4 val; } colors[];\n"
284         "layout(location = 0) out vec4 uFragColor;\n"
285         "layout(location = 0) in flat uint index;\n"
286         "void main(){\n"
287         "   uFragColor = colors[index].val;\n"
288         "}\n";
289     char const *gsSource =
290         "#version 450\n"
291         "#extension GL_EXT_nonuniform_qualifier : enable\n "
292         "layout(triangles) in;\n"
293         "layout(triangle_strip, max_vertices=3) out;\n"
294         "layout(location=0) in VertexData { vec4 x; } gs_in[];\n"
295         "layout(std140, set = 0, binding = 0) uniform ufoo { uint index; } uniform_index_buffer;\n"
296         "layout(set = 0, binding = 1) buffer bfoo { vec4 val; } adds[];\n"
297         "void main() {\n"
298         "   gl_Position = gs_in[0].x + adds[uniform_index_buffer.index].val.x;\n"
299         "   EmitVertex();\n"
300         "}\n";
301     static const char *tesSource =
302         "#version 450\n"
303         "#extension GL_EXT_nonuniform_qualifier : enable\n "
304         "layout(std140, set = 0, binding = 0) uniform ufoo { uint index; } uniform_index_buffer;\n"
305         "layout(set = 0, binding = 1) buffer bfoo { vec4 val; } adds[];\n"
306         "layout(triangles, equal_spacing, cw) in;\n"
307         "void main() {\n"
308         "    gl_Position = adds[uniform_index_buffer.index].val;\n"
309         "}\n";
310 
311     struct TestCase {
312         char const *vertex_source;
313         char const *fragment_source;
314         char const *geometry_source;
315         char const *tess_ctrl_source;
316         char const *tess_eval_source;
317         bool debug;
318         const VkPipelineLayoutObj *pipeline_layout;
319         const OneOffDescriptorSet *descriptor_set;
320         uint32_t index;
321         char const *expected_error;
322     };
323 
324     std::vector<TestCase> tests;
325     tests.push_back({vsSource_vert, fsSource_vert, nullptr, nullptr, nullptr, false, &pipeline_layout, &descriptor_set, 25,
326                      "Index of 25 used to index descriptor array of length 6."});
327     tests.push_back({vsSource_frag, fsSource_frag, nullptr, nullptr, nullptr, false, &pipeline_layout, &descriptor_set, 25,
328                      "Index of 25 used to index descriptor array of length 6."});
329 #if !defined(ANDROID)
330     // The Android test framework uses shaderc for online compilations.  Even when configured to compile with debug info,
331     // shaderc seems to drop the OpLine instructions from the shader binary.  This causes the following two tests to fail
332     // on Android platforms.  Skip these tests until the shaderc issue is understood/resolved.
333     tests.push_back({vsSource_vert, fsSource_vert, nullptr, nullptr, nullptr, true, &pipeline_layout, &descriptor_set, 25,
334                      "gl_Position += 1e-30 * texture(tex[uniform_index_buffer.tex_index[0]], vec2(0, 0));"});
335     tests.push_back({vsSource_frag, fsSource_frag, nullptr, nullptr, nullptr, true, &pipeline_layout, &descriptor_set, 25,
336                      "uFragColor = texture(tex[index], vec2(0, 0));"});
337 #endif
338     if (descriptor_indexing) {
339         tests.push_back({vsSource_frag, fsSource_frag_runtime, nullptr, nullptr, nullptr, false, &pipeline_layout, &descriptor_set,
340                          25, "Index of 25 used to index descriptor array of length 6."});
341         tests.push_back({vsSource_frag, fsSource_frag_runtime, nullptr, nullptr, nullptr, false, &pipeline_layout, &descriptor_set,
342                          5, "Descriptor index 5 is uninitialized"});
343         // Pick 6 below because it is less than the maximum specified, but more than the actual specified
344         tests.push_back({vsSource_frag, fsSource_frag_runtime, nullptr, nullptr, nullptr, false, &pipeline_layout_variable,
345                          &descriptor_set_variable, 6, "Index of 6 used to index descriptor array of length 6."});
346         tests.push_back({vsSource_frag, fsSource_frag_runtime, nullptr, nullptr, nullptr, false, &pipeline_layout_variable,
347                          &descriptor_set_variable, 5, "Descriptor index 5 is uninitialized"});
348         tests.push_back({vsSource_frag, fsSource_buffer, nullptr, nullptr, nullptr, false, &pipeline_layout_buffer,
349                          &descriptor_set_buffer, 25, "Index of 25 used to index descriptor array of length 6."});
350         tests.push_back({vsSource_frag, fsSource_buffer, nullptr, nullptr, nullptr, false, &pipeline_layout_buffer,
351                          &descriptor_set_buffer, 5, "Descriptor index 5 is uninitialized"});
352         if (m_device->phy().features().geometryShader) {
353             // OOB Geometry
354             tests.push_back({bindStateVertShaderText, bindStateFragShaderText, gsSource, nullptr, nullptr, false,
355                              &pipeline_layout_buffer, &descriptor_set_buffer, 25, "Stage = Geometry"});
356             // Uninitialized Geometry
357             tests.push_back({bindStateVertShaderText, bindStateFragShaderText, gsSource, nullptr, nullptr, false,
358                              &pipeline_layout_buffer, &descriptor_set_buffer, 5, "Stage = Geometry"});
359         }
360         if (m_device->phy().features().tessellationShader) {
361             tests.push_back({bindStateVertShaderText, bindStateFragShaderText, nullptr, bindStateTscShaderText, tesSource, false,
362                              &pipeline_layout_buffer, &descriptor_set_buffer, 25, "Stage = Tessellation Eval"});
363             tests.push_back({bindStateVertShaderText, bindStateFragShaderText, nullptr, bindStateTscShaderText, tesSource, false,
364                              &pipeline_layout_buffer, &descriptor_set_buffer, 5, "Stage = Tessellation Eval"});
365         }
366     }
367 
368     VkViewport viewport = m_viewports[0];
369     VkRect2D scissors = m_scissors[0];
370 
371     VkSubmitInfo submit_info = {};
372     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
373     submit_info.commandBufferCount = 1;
374     submit_info.pCommandBuffers = &m_commandBuffer->handle();
375 
376     for (const auto &iter : tests) {
377         VkResult err;
378         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, iter.expected_error);
379         VkShaderObj vs(m_device, iter.vertex_source, VK_SHADER_STAGE_VERTEX_BIT, this, "main", iter.debug);
380         VkShaderObj fs(m_device, iter.fragment_source, VK_SHADER_STAGE_FRAGMENT_BIT, this, "main", iter.debug);
381         VkShaderObj *gs = nullptr;
382         VkShaderObj *tcs = nullptr;
383         VkShaderObj *tes = nullptr;
384         VkPipelineObj pipe(m_device);
385         pipe.AddShader(&vs);
386         pipe.AddShader(&fs);
387         if (iter.geometry_source) {
388             gs = new VkShaderObj(m_device, iter.geometry_source, VK_SHADER_STAGE_GEOMETRY_BIT, this, "main", iter.debug);
389             pipe.AddShader(gs);
390         }
391         if (iter.tess_ctrl_source && iter.tess_eval_source) {
392             tcs = new VkShaderObj(m_device, iter.tess_ctrl_source, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, this, "main",
393                                   iter.debug);
394             tes = new VkShaderObj(m_device, iter.tess_eval_source, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, this, "main",
395                                   iter.debug);
396             pipe.AddShader(tcs);
397             pipe.AddShader(tes);
398             VkPipelineInputAssemblyStateCreateInfo iasci{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, nullptr, 0,
399                                                          VK_PRIMITIVE_TOPOLOGY_PATCH_LIST, VK_FALSE};
400             VkPipelineTessellationDomainOriginStateCreateInfo tessellationDomainOriginStateInfo = {
401                 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO, VK_NULL_HANDLE,
402                 VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT};
403 
404             VkPipelineTessellationStateCreateInfo tsci{VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
405                                                        &tessellationDomainOriginStateInfo, 0, 3};
406             pipe.SetTessellation(&tsci);
407             pipe.SetInputAssembly(&iasci);
408         }
409         pipe.AddDefaultColorAttachment();
410         err = pipe.CreateVKPipeline(iter.pipeline_layout->handle(), renderPass());
411         ASSERT_VK_SUCCESS(err);
412         m_commandBuffer->begin();
413         m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
414         vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
415         vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, iter.pipeline_layout->handle(), 0, 1,
416                                 &iter.descriptor_set->set_, 0, nullptr);
417         vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
418         vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissors);
419         vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
420         vkCmdEndRenderPass(m_commandBuffer->handle());
421         m_commandBuffer->end();
422         uint32_t *data = (uint32_t *)buffer0.memory().map();
423         data[0] = iter.index;
424         buffer0.memory().unmap();
425         vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
426         vkQueueWaitIdle(m_device->m_queue);
427         m_errorMonitor->VerifyFound();
428         if (gs) {
429             delete gs;
430         }
431         if (tcs && tes) {
432             delete tcs;
433             delete tes;
434         }
435     }
436     auto c_queue = m_device->GetDefaultComputeQueue();
437     if (c_queue && descriptor_indexing) {
438         char const *csSource =
439             "#version 450\n"
440             "#extension GL_EXT_nonuniform_qualifier : enable\n "
441             "layout(set = 0, binding = 0) uniform ufoo { uint index; } u_index;"
442             "layout(set = 0, binding = 1) buffer StorageBuffer {\n"
443             "    uint data;\n"
444             "} Data[];\n"
445             "void main() {\n"
446             "   Data[(u_index.index - 1)].data = Data[u_index.index].data;\n"
447             "}\n";
448 
449         auto shader_module = new VkShaderObj(m_device, csSource, VK_SHADER_STAGE_COMPUTE_BIT, this);
450 
451         VkPipelineShaderStageCreateInfo stage;
452         stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
453         stage.pNext = nullptr;
454         stage.flags = 0;
455         stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
456         stage.module = shader_module->handle();
457         stage.pName = "main";
458         stage.pSpecializationInfo = nullptr;
459 
460         // CreateComputePipelines
461         VkComputePipelineCreateInfo pipeline_info = {};
462         pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
463         pipeline_info.pNext = nullptr;
464         pipeline_info.flags = 0;
465         pipeline_info.layout = pipeline_layout_buffer.handle();
466         pipeline_info.basePipelineHandle = VK_NULL_HANDLE;
467         pipeline_info.basePipelineIndex = -1;
468         pipeline_info.stage = stage;
469 
470         VkPipeline c_pipeline;
471         vkCreateComputePipelines(device(), VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &c_pipeline);
472         VkCommandBufferBeginInfo begin_info = {};
473         VkCommandBufferInheritanceInfo hinfo = {};
474         hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
475         begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
476         begin_info.pInheritanceInfo = &hinfo;
477 
478         m_commandBuffer->begin(&begin_info);
479         vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, c_pipeline);
480         vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout_buffer.handle(), 0, 1,
481                                 &descriptor_set_buffer.set_, 0, nullptr);
482         vkCmdDispatch(m_commandBuffer->handle(), 1, 1, 1);
483         m_commandBuffer->end();
484 
485         // Uninitialized
486         uint32_t *data = (uint32_t *)buffer0.memory().map();
487         data[0] = 5;
488         buffer0.memory().unmap();
489         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Stage = Compute");
490         vkQueueSubmit(c_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
491         vkQueueWaitIdle(m_device->m_queue);
492         m_errorMonitor->VerifyFound();
493         // Out of Bounds
494         data = (uint32_t *)buffer0.memory().map();
495         data[0] = 25;
496         buffer0.memory().unmap();
497         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "Stage = Compute");
498         vkQueueSubmit(c_queue->handle(), 1, &submit_info, VK_NULL_HANDLE);
499         vkQueueWaitIdle(m_device->m_queue);
500         m_errorMonitor->VerifyFound();
501         vkDestroyPipeline(m_device->handle(), c_pipeline, NULL);
502         vkDestroyShaderModule(m_device->handle(), shader_module->handle(), NULL);
503     }
504     return;
505 }
506 
TEST_F(VkLayerTest,GpuValidationArrayOOBRayTracingShaders)507 TEST_F(VkLayerTest, GpuValidationArrayOOBRayTracingShaders) {
508     TEST_DESCRIPTION(
509         "GPU validation: Verify detection of out-of-bounds descriptor array indexing and use of uninitialized descriptors for "
510         "ray tracing shaders.");
511 
512     std::array<const char *, 1> required_instance_extensions = {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME};
513     for (auto instance_extension : required_instance_extensions) {
514         if (InstanceExtensionSupported(instance_extension)) {
515             m_instance_extension_names.push_back(instance_extension);
516         } else {
517             printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix, instance_extension);
518             return;
519         }
520     }
521 
522     VkValidationFeatureEnableEXT validation_feature_enables[] = {VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT};
523     VkValidationFeaturesEXT validation_features = {};
524     validation_features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
525     validation_features.enabledValidationFeatureCount = 1;
526     validation_features.pEnabledValidationFeatures = validation_feature_enables;
527     bool descriptor_indexing = CheckDescriptorIndexingSupportAndInitFramework(
528         this, m_instance_extension_names, m_device_extension_names, &validation_features, m_errorMonitor);
529 
530     if (DeviceIsMockICD() || DeviceSimulation()) {
531         printf("%s Test not supported by MockICD, skipping tests\n", kSkipPrefix);
532         return;
533     }
534 
535     std::array<const char *, 2> required_device_extensions = {VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME,
536                                                               VK_NV_RAY_TRACING_EXTENSION_NAME};
537     for (auto device_extension : required_device_extensions) {
538         if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) {
539             m_device_extension_names.push_back(device_extension);
540         } else {
541             printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension);
542             return;
543         }
544     }
545 
546     VkPhysicalDeviceFeatures2KHR features2 = {};
547     auto indexing_features = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>();
548     if (descriptor_indexing) {
549         PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR =
550             (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR");
551         ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr);
552 
553         features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&indexing_features);
554         vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2);
555 
556         if (!indexing_features.runtimeDescriptorArray || !indexing_features.descriptorBindingPartiallyBound ||
557             !indexing_features.descriptorBindingSampledImageUpdateAfterBind ||
558             !indexing_features.descriptorBindingVariableDescriptorCount) {
559             printf("Not all descriptor indexing features supported, skipping descriptor indexing tests\n");
560             descriptor_indexing = false;
561         }
562     }
563     VkCommandPoolCreateFlags pool_flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
564     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2, pool_flags));
565 
566     PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR =
567         (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceProperties2KHR");
568     ASSERT_TRUE(vkGetPhysicalDeviceProperties2KHR != nullptr);
569 
570     auto ray_tracing_properties = lvl_init_struct<VkPhysicalDeviceRayTracingPropertiesNV>();
571     auto properties2 = lvl_init_struct<VkPhysicalDeviceProperties2KHR>(&ray_tracing_properties);
572     vkGetPhysicalDeviceProperties2KHR(gpu(), &properties2);
573     if (ray_tracing_properties.maxTriangleCount == 0) {
574         printf("%s Did not find required ray tracing properties; skipped.\n", kSkipPrefix);
575         return;
576     }
577 
578     VkQueue ray_tracing_queue = m_device->m_queue;
579     uint32_t ray_tracing_queue_family_index = 0;
580 
581     // If supported, run on the compute only queue.
582     uint32_t compute_only_queue_family_index = m_device->QueueFamilyMatching(VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT);
583     if (compute_only_queue_family_index != UINT32_MAX) {
584         const auto &compute_only_queues = m_device->queue_family_queues(compute_only_queue_family_index);
585         if (!compute_only_queues.empty()) {
586             ray_tracing_queue = compute_only_queues[0]->handle();
587             ray_tracing_queue_family_index = compute_only_queue_family_index;
588         }
589     }
590 
591     VkCommandPoolObj ray_tracing_command_pool(m_device, ray_tracing_queue_family_index,
592                                               VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
593     VkCommandBufferObj ray_tracing_command_buffer(m_device, &ray_tracing_command_pool);
594 
595     struct AABB {
596         float min_x;
597         float min_y;
598         float min_z;
599         float max_x;
600         float max_y;
601         float max_z;
602     };
603 
604     const std::vector<AABB> aabbs = {{-1.0f, -1.0f, -1.0f, +1.0f, +1.0f, +1.0f}};
605 
606     struct VkGeometryInstanceNV {
607         float transform[12];
608         uint32_t instanceCustomIndex : 24;
609         uint32_t mask : 8;
610         uint32_t instanceOffset : 24;
611         uint32_t flags : 8;
612         uint64_t accelerationStructureHandle;
613     };
614 
615     VkDeviceSize aabb_buffer_size = sizeof(AABB) * aabbs.size();
616     VkBufferObj aabb_buffer;
617     aabb_buffer.init(*m_device, aabb_buffer_size, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
618                      VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, {ray_tracing_queue_family_index});
619 
620     uint8_t *mapped_aabb_buffer_data = (uint8_t *)aabb_buffer.memory().map();
621     std::memcpy(mapped_aabb_buffer_data, (uint8_t *)aabbs.data(), static_cast<std::size_t>(aabb_buffer_size));
622     aabb_buffer.memory().unmap();
623 
624     VkGeometryNV geometry = {};
625     geometry.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
626     geometry.geometryType = VK_GEOMETRY_TYPE_AABBS_NV;
627     geometry.geometry.triangles = {};
628     geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
629     geometry.geometry.aabbs = {};
630     geometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
631     geometry.geometry.aabbs.aabbData = aabb_buffer.handle();
632     geometry.geometry.aabbs.numAABBs = static_cast<uint32_t>(aabbs.size());
633     geometry.geometry.aabbs.offset = 0;
634     geometry.geometry.aabbs.stride = static_cast<VkDeviceSize>(sizeof(AABB));
635     geometry.flags = 0;
636 
637     VkAccelerationStructureInfoNV bot_level_as_info = {};
638     bot_level_as_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
639     bot_level_as_info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV;
640     bot_level_as_info.instanceCount = 0;
641     bot_level_as_info.geometryCount = 1;
642     bot_level_as_info.pGeometries = &geometry;
643 
644     VkAccelerationStructureCreateInfoNV bot_level_as_create_info = {};
645     bot_level_as_create_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
646     bot_level_as_create_info.info = bot_level_as_info;
647 
648     VkAccelerationStructureObj bot_level_as(*m_device, bot_level_as_create_info);
649 
650     const std::vector<VkGeometryInstanceNV> instances = {
651         VkGeometryInstanceNV{
652             {
653                 // clang-format off
654                 1.0f, 0.0f, 0.0f, 0.0f,
655                 0.0f, 1.0f, 0.0f, 0.0f,
656                 0.0f, 0.0f, 1.0f, 0.0f,
657                 // clang-format on
658             },
659             0,
660             0xFF,
661             0,
662             VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV,
663             bot_level_as.opaque_handle(),
664         },
665     };
666 
667     VkDeviceSize instance_buffer_size = sizeof(VkGeometryInstanceNV) * instances.size();
668     VkBufferObj instance_buffer;
669     instance_buffer.init(*m_device, instance_buffer_size,
670                          VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
671                          VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, {ray_tracing_queue_family_index});
672 
673     uint8_t *mapped_instance_buffer_data = (uint8_t *)instance_buffer.memory().map();
674     std::memcpy(mapped_instance_buffer_data, (uint8_t *)instances.data(), static_cast<std::size_t>(instance_buffer_size));
675     instance_buffer.memory().unmap();
676 
677     VkAccelerationStructureInfoNV top_level_as_info = {};
678     top_level_as_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
679     top_level_as_info.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV;
680     top_level_as_info.instanceCount = 1;
681     top_level_as_info.geometryCount = 0;
682 
683     VkAccelerationStructureCreateInfoNV top_level_as_create_info = {};
684     top_level_as_create_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
685     top_level_as_create_info.info = top_level_as_info;
686 
687     VkAccelerationStructureObj top_level_as(*m_device, top_level_as_create_info);
688 
689     VkDeviceSize scratch_buffer_size = std::max(bot_level_as.build_scratch_memory_requirements().memoryRequirements.size,
690                                                 top_level_as.build_scratch_memory_requirements().memoryRequirements.size);
691     VkBufferObj scratch_buffer;
692     scratch_buffer.init(*m_device, scratch_buffer_size, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_BUFFER_USAGE_RAY_TRACING_BIT_NV);
693 
694     ray_tracing_command_buffer.begin();
695 
696     // Build bot level acceleration structure
697     ray_tracing_command_buffer.BuildAccelerationStructure(&bot_level_as, scratch_buffer.handle());
698 
699     // Barrier to prevent using scratch buffer for top level build before bottom level build finishes
700     VkMemoryBarrier memory_barrier = {};
701     memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
702     memory_barrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV;
703     memory_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_NV;
704     ray_tracing_command_buffer.PipelineBarrier(VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV,
705                                                VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 1, &memory_barrier, 0,
706                                                nullptr, 0, nullptr);
707 
708     // Build top level acceleration structure
709     ray_tracing_command_buffer.BuildAccelerationStructure(&top_level_as, scratch_buffer.handle(), instance_buffer.handle());
710 
711     ray_tracing_command_buffer.end();
712 
713     VkSubmitInfo submit_info = {};
714     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
715     submit_info.commandBufferCount = 1;
716     submit_info.pCommandBuffers = &ray_tracing_command_buffer.handle();
717     vkQueueSubmit(ray_tracing_queue, 1, &submit_info, VK_NULL_HANDLE);
718     vkQueueWaitIdle(ray_tracing_queue);
719     m_errorMonitor->VerifyNotFound();
720 
721     VkTextureObj texture(m_device, nullptr);
722     VkSamplerObj sampler(m_device);
723 
724     VkDeviceSize storage_buffer_size = 1024;
725     VkBufferObj storage_buffer;
726     storage_buffer.init(*m_device, storage_buffer_size, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
727                         VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, {ray_tracing_queue_family_index});
728 
729     VkDeviceSize shader_binding_table_buffer_size = ray_tracing_properties.shaderGroupHandleSize * 4ull;
730     VkBufferObj shader_binding_table_buffer;
731     shader_binding_table_buffer.init(*m_device, shader_binding_table_buffer_size,
732                                      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
733                                      VK_BUFFER_USAGE_RAY_TRACING_BIT_NV, {ray_tracing_queue_family_index});
734 
735     // Setup descriptors!
736     const VkShaderStageFlags kAllRayTracingStages = VK_SHADER_STAGE_RAYGEN_BIT_NV | VK_SHADER_STAGE_ANY_HIT_BIT_NV |
737                                                     VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV |
738                                                     VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV;
739 
740     void *layout_pnext = nullptr;
741     void *allocate_pnext = nullptr;
742     VkDescriptorPoolCreateFlags pool_create_flags = 0;
743     VkDescriptorSetLayoutCreateFlags layout_create_flags = 0;
744     VkDescriptorBindingFlagsEXT ds_binding_flags[3] = {};
745     VkDescriptorSetLayoutBindingFlagsCreateInfoEXT layout_createinfo_binding_flags[1] = {};
746     if (descriptor_indexing) {
747         ds_binding_flags[0] = 0;
748         ds_binding_flags[1] = 0;
749         ds_binding_flags[2] = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT;
750 
751         layout_createinfo_binding_flags[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT;
752         layout_createinfo_binding_flags[0].pNext = NULL;
753         layout_createinfo_binding_flags[0].bindingCount = 3;
754         layout_createinfo_binding_flags[0].pBindingFlags = ds_binding_flags;
755         layout_create_flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
756         pool_create_flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
757         layout_pnext = layout_createinfo_binding_flags;
758     }
759 
760     // Prepare descriptors
761     OneOffDescriptorSet ds(m_device,
762                            {
763                                {0, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV, 1, kAllRayTracingStages, nullptr},
764                                {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, kAllRayTracingStages, nullptr},
765                                {2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 6, kAllRayTracingStages, nullptr},
766                            },
767                            layout_create_flags, layout_pnext, pool_create_flags);
768 
769     VkDescriptorSetVariableDescriptorCountAllocateInfoEXT variable_count = {};
770     uint32_t desc_counts;
771     if (descriptor_indexing) {
772         layout_create_flags = 0;
773         pool_create_flags = 0;
774         ds_binding_flags[2] =
775             VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT;
776         desc_counts = 6;  // We'll reserve 8 spaces in the layout, but the descriptor will only use 6
777         variable_count.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT;
778         variable_count.descriptorSetCount = 1;
779         variable_count.pDescriptorCounts = &desc_counts;
780         allocate_pnext = &variable_count;
781     }
782 
783     OneOffDescriptorSet ds_variable(m_device,
784                                     {
785                                         {0, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV, 1, kAllRayTracingStages, nullptr},
786                                         {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, kAllRayTracingStages, nullptr},
787                                         {2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 8, kAllRayTracingStages, nullptr},
788                                     },
789                                     layout_create_flags, layout_pnext, pool_create_flags, allocate_pnext);
790 
791     VkAccelerationStructureNV top_level_as_handle = top_level_as.handle();
792     VkWriteDescriptorSetAccelerationStructureNV write_descript_set_as = {};
793     write_descript_set_as.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_NV;
794     write_descript_set_as.accelerationStructureCount = 1;
795     write_descript_set_as.pAccelerationStructures = &top_level_as_handle;
796 
797     VkDescriptorBufferInfo descriptor_buffer_info = {};
798     descriptor_buffer_info.buffer = storage_buffer.handle();
799     descriptor_buffer_info.offset = 0;
800     descriptor_buffer_info.range = storage_buffer_size;
801 
802     VkDescriptorImageInfo descriptor_image_infos[6] = {};
803     for (int i = 0; i < 6; i++) {
804         descriptor_image_infos[i] = texture.DescriptorImageInfo();
805         descriptor_image_infos[i].sampler = sampler.handle();
806         descriptor_image_infos[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
807     }
808 
809     VkWriteDescriptorSet descriptor_writes[3] = {};
810     descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
811     descriptor_writes[0].dstSet = ds.set_;
812     descriptor_writes[0].dstBinding = 0;
813     descriptor_writes[0].descriptorCount = 1;
814     descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV;
815     descriptor_writes[0].pNext = &write_descript_set_as;
816 
817     descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
818     descriptor_writes[1].dstSet = ds.set_;
819     descriptor_writes[1].dstBinding = 1;
820     descriptor_writes[1].descriptorCount = 1;
821     descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
822     descriptor_writes[1].pBufferInfo = &descriptor_buffer_info;
823 
824     descriptor_writes[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
825     descriptor_writes[2].dstSet = ds.set_;
826     descriptor_writes[2].dstBinding = 2;
827     if (descriptor_indexing) {
828         descriptor_writes[2].descriptorCount = 5;  // Intentionally don't write index 5
829     } else {
830         descriptor_writes[2].descriptorCount = 6;
831     }
832     descriptor_writes[2].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
833     descriptor_writes[2].pImageInfo = descriptor_image_infos;
834     vkUpdateDescriptorSets(m_device->device(), 3, descriptor_writes, 0, NULL);
835     if (descriptor_indexing) {
836         descriptor_writes[0].dstSet = ds_variable.set_;
837         descriptor_writes[1].dstSet = ds_variable.set_;
838         descriptor_writes[2].dstSet = ds_variable.set_;
839         vkUpdateDescriptorSets(m_device->device(), 3, descriptor_writes, 0, NULL);
840     }
841 
842     const VkPipelineLayoutObj pipeline_layout(m_device, {&ds.layout_});
843     const VkPipelineLayoutObj pipeline_layout_variable(m_device, {&ds_variable.layout_});
844 
845     const auto SetImagesArrayLength = [](const std::string &shader_template, const std::string &length_str) {
846         const std::string to_replace = "IMAGES_ARRAY_LENGTH";
847 
848         std::string result = shader_template;
849         auto position = result.find(to_replace);
850         assert(position != std::string::npos);
851         result.replace(position, to_replace.length(), length_str);
852         return result;
853     };
854 
855     const std::string rgen_source_template = R"(#version 460
856         #extension GL_EXT_nonuniform_qualifier : require
857         #extension GL_EXT_samplerless_texture_functions : require
858         #extension GL_NV_ray_tracing : require
859 
860         layout(set = 0, binding = 0) uniform accelerationStructureNV topLevelAS;
861         layout(set = 0, binding = 1, std430) buffer RayTracingSbo {
862 	        uint rgen_index;
863 	        uint ahit_index;
864 	        uint chit_index;
865 	        uint miss_index;
866 	        uint intr_index;
867 	        uint call_index;
868 
869 	        uint rgen_ran;
870 	        uint ahit_ran;
871 	        uint chit_ran;
872 	        uint miss_ran;
873 	        uint intr_ran;
874 	        uint call_ran;
875 
876 	        float result1;
877 	        float result2;
878 	        float result3;
879         } sbo;
880         layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH];
881 
882         layout(location = 0) rayPayloadNV vec3 payload;
883         layout(location = 3) callableDataNV vec3 callableData;
884 
885         void main() {
886             sbo.rgen_ran = 1;
887 
888 	        executeCallableNV(0, 3);
889 	        sbo.result1 = callableData.x;
890 
891 	        vec3 origin = vec3(0.0f, 0.0f, -2.0f);
892 	        vec3 direction = vec3(0.0f, 0.0f, 1.0f);
893 
894 	        traceNV(topLevelAS, gl_RayFlagsNoneNV, 0xFF, 0, 1, 0, origin, 0.001, direction, 10000.0, 0);
895 	        sbo.result2 = payload.x;
896 
897 	        traceNV(topLevelAS, gl_RayFlagsNoneNV, 0xFF, 0, 1, 0, origin, 0.001, -direction, 10000.0, 0);
898 	        sbo.result3 = payload.x;
899 
900             if (sbo.rgen_index > 0) {
901                 // OOB here:
902                 sbo.result3 = texelFetch(textures[sbo.rgen_index], ivec2(0, 0), 0).x;
903             }
904         }
905         )";
906 
907     const std::string rgen_source = SetImagesArrayLength(rgen_source_template, "6");
908     const std::string rgen_source_runtime = SetImagesArrayLength(rgen_source_template, "");
909 
910     const std::string ahit_source_template = R"(#version 460
911         #extension GL_EXT_nonuniform_qualifier : require
912         #extension GL_EXT_samplerless_texture_functions : require
913         #extension GL_NV_ray_tracing : require
914 
915         layout(set = 0, binding = 1, std430) buffer StorageBuffer {
916 	        uint rgen_index;
917 	        uint ahit_index;
918 	        uint chit_index;
919 	        uint miss_index;
920 	        uint intr_index;
921 	        uint call_index;
922 
923 	        uint rgen_ran;
924 	        uint ahit_ran;
925 	        uint chit_ran;
926 	        uint miss_ran;
927 	        uint intr_ran;
928 	        uint call_ran;
929 
930 	        float result1;
931 	        float result2;
932 	        float result3;
933         } sbo;
934         layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH];
935 
936         hitAttributeNV vec3 hitValue;
937 
938         layout(location = 0) rayPayloadInNV vec3 payload;
939 
940         void main() {
941 	        sbo.ahit_ran = 2;
942 
943 	        payload = vec3(0.1234f);
944 
945             if (sbo.ahit_index > 0) {
946                 // OOB here:
947                 payload.x = texelFetch(textures[sbo.ahit_index], ivec2(0, 0), 0).x;
948             }
949         }
950     )";
951     const std::string ahit_source = SetImagesArrayLength(ahit_source_template, "6");
952     const std::string ahit_source_runtime = SetImagesArrayLength(ahit_source_template, "");
953 
954     const std::string chit_source_template = R"(#version 460
955         #extension GL_EXT_nonuniform_qualifier : require
956         #extension GL_EXT_samplerless_texture_functions : require
957         #extension GL_NV_ray_tracing : require
958 
959         layout(set = 0, binding = 1, std430) buffer RayTracingSbo {
960 	        uint rgen_index;
961 	        uint ahit_index;
962 	        uint chit_index;
963 	        uint miss_index;
964 	        uint intr_index;
965 	        uint call_index;
966 
967 	        uint rgen_ran;
968 	        uint ahit_ran;
969 	        uint chit_ran;
970 	        uint miss_ran;
971 	        uint intr_ran;
972 	        uint call_ran;
973 
974 	        float result1;
975 	        float result2;
976 	        float result3;
977         } sbo;
978         layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH];
979 
980         layout(location = 0) rayPayloadInNV vec3 payload;
981 
982         hitAttributeNV vec3 attribs;
983 
984         void main() {
985             sbo.chit_ran = 3;
986 
987             payload = attribs;
988             if (sbo.chit_index > 0) {
989                 // OOB here:
990                 payload.x = texelFetch(textures[sbo.chit_index], ivec2(0, 0), 0).x;
991             }
992         }
993         )";
994     const std::string chit_source = SetImagesArrayLength(chit_source_template, "6");
995     const std::string chit_source_runtime = SetImagesArrayLength(chit_source_template, "");
996 
997     const std::string miss_source_template = R"(#version 460
998         #extension GL_EXT_nonuniform_qualifier : enable
999         #extension GL_EXT_samplerless_texture_functions : require
1000         #extension GL_NV_ray_tracing : require
1001 
1002         layout(set = 0, binding = 1, std430) buffer RayTracingSbo {
1003 	        uint rgen_index;
1004 	        uint ahit_index;
1005 	        uint chit_index;
1006 	        uint miss_index;
1007 	        uint intr_index;
1008 	        uint call_index;
1009 
1010 	        uint rgen_ran;
1011 	        uint ahit_ran;
1012 	        uint chit_ran;
1013 	        uint miss_ran;
1014 	        uint intr_ran;
1015 	        uint call_ran;
1016 
1017 	        float result1;
1018 	        float result2;
1019 	        float result3;
1020         } sbo;
1021         layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH];
1022 
1023         layout(location = 0) rayPayloadInNV vec3 payload;
1024 
1025         void main() {
1026             sbo.miss_ran = 4;
1027 
1028             payload = vec3(1.0, 0.0, 0.0);
1029 
1030             if (sbo.miss_index > 0) {
1031                 // OOB here:
1032                 payload.x = texelFetch(textures[sbo.miss_index], ivec2(0, 0), 0).x;
1033             }
1034         }
1035     )";
1036     const std::string miss_source = SetImagesArrayLength(miss_source_template, "6");
1037     const std::string miss_source_runtime = SetImagesArrayLength(miss_source_template, "");
1038 
1039     const std::string intr_source_template = R"(#version 460
1040         #extension GL_EXT_nonuniform_qualifier : require
1041         #extension GL_EXT_samplerless_texture_functions : require
1042         #extension GL_NV_ray_tracing : require
1043 
1044         layout(set = 0, binding = 1, std430) buffer StorageBuffer {
1045 	        uint rgen_index;
1046 	        uint ahit_index;
1047 	        uint chit_index;
1048 	        uint miss_index;
1049 	        uint intr_index;
1050 	        uint call_index;
1051 
1052 	        uint rgen_ran;
1053 	        uint ahit_ran;
1054 	        uint chit_ran;
1055 	        uint miss_ran;
1056 	        uint intr_ran;
1057 	        uint call_ran;
1058 
1059 	        float result1;
1060 	        float result2;
1061 	        float result3;
1062         } sbo;
1063         layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH];
1064 
1065         hitAttributeNV vec3 hitValue;
1066 
1067         void main() {
1068 	        sbo.intr_ran = 5;
1069 
1070 	        hitValue = vec3(0.0f, 0.5f, 0.0f);
1071 
1072 	        reportIntersectionNV(1.0f, 0);
1073 
1074             if (sbo.intr_index > 0) {
1075                 // OOB here:
1076                 hitValue.x = texelFetch(textures[sbo.intr_index], ivec2(0, 0), 0).x;
1077             }
1078         }
1079     )";
1080     const std::string intr_source = SetImagesArrayLength(intr_source_template, "6");
1081     const std::string intr_source_runtime = SetImagesArrayLength(intr_source_template, "");
1082 
1083     const std::string call_source_template = R"(#version 460
1084         #extension GL_EXT_nonuniform_qualifier : require
1085         #extension GL_EXT_samplerless_texture_functions : require
1086         #extension GL_NV_ray_tracing : require
1087 
1088         layout(set = 0, binding = 1, std430) buffer StorageBuffer {
1089 	        uint rgen_index;
1090 	        uint ahit_index;
1091 	        uint chit_index;
1092 	        uint miss_index;
1093 	        uint intr_index;
1094 	        uint call_index;
1095 
1096 	        uint rgen_ran;
1097 	        uint ahit_ran;
1098 	        uint chit_ran;
1099 	        uint miss_ran;
1100 	        uint intr_ran;
1101 	        uint call_ran;
1102 
1103 	        float result1;
1104 	        float result2;
1105 	        float result3;
1106         } sbo;
1107         layout(set = 0, binding = 2) uniform texture2D textures[IMAGES_ARRAY_LENGTH];
1108 
1109         layout(location = 3) callableDataInNV vec3 callableData;
1110 
1111         void main() {
1112 	        sbo.call_ran = 6;
1113 
1114 	        callableData = vec3(0.1234f);
1115 
1116             if (sbo.call_index > 0) {
1117                 // OOB here:
1118                 callableData.x = texelFetch(textures[sbo.call_index], ivec2(0, 0), 0).x;
1119             }
1120         }
1121     )";
1122     const std::string call_source = SetImagesArrayLength(call_source_template, "6");
1123     const std::string call_source_runtime = SetImagesArrayLength(call_source_template, "");
1124 
1125     struct TestCase {
1126         const std::string &rgen_shader_source;
1127         const std::string &ahit_shader_source;
1128         const std::string &chit_shader_source;
1129         const std::string &miss_shader_source;
1130         const std::string &intr_shader_source;
1131         const std::string &call_shader_source;
1132         bool variable_length;
1133         uint32_t rgen_index;
1134         uint32_t ahit_index;
1135         uint32_t chit_index;
1136         uint32_t miss_index;
1137         uint32_t intr_index;
1138         uint32_t call_index;
1139         const char *expected_error;
1140     };
1141 
1142     std::vector<TestCase> tests;
1143     tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 25, 0, 0, 0, 0, 0,
1144                      "Index of 25 used to index descriptor array of length 6."});
1145     tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 0, 25, 0, 0, 0, 0,
1146                      "Index of 25 used to index descriptor array of length 6."});
1147     tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 0, 0, 25, 0, 0, 0,
1148                      "Index of 25 used to index descriptor array of length 6."});
1149     tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 0, 0, 0, 25, 0, 0,
1150                      "Index of 25 used to index descriptor array of length 6."});
1151     tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 0, 0, 0, 0, 25, 0,
1152                      "Index of 25 used to index descriptor array of length 6."});
1153     tests.push_back({rgen_source, ahit_source, chit_source, miss_source, intr_source, call_source, false, 0, 0, 0, 0, 0, 25,
1154                      "Index of 25 used to index descriptor array of length 6."});
1155 
1156     if (descriptor_indexing) {
1157         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1158                          call_source_runtime, true, 25, 0, 0, 0, 0, 0, "Index of 25 used to index descriptor array of length 6."});
1159         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1160                          call_source_runtime, true, 0, 25, 0, 0, 0, 0, "Index of 25 used to index descriptor array of length 6."});
1161         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1162                          call_source_runtime, true, 0, 0, 25, 0, 0, 0, "Index of 25 used to index descriptor array of length 6."});
1163         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1164                          call_source_runtime, true, 0, 0, 0, 25, 0, 0, "Index of 25 used to index descriptor array of length 6."});
1165         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1166                          call_source_runtime, true, 0, 0, 0, 0, 25, 0, "Index of 25 used to index descriptor array of length 6."});
1167         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1168                          call_source_runtime, true, 0, 0, 0, 0, 0, 25, "Index of 25 used to index descriptor array of length 6."});
1169 
1170         // For this group, 6 is less than max specified (max specified is 8) but more than actual specified (actual specified is 5)
1171         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1172                          call_source_runtime, true, 6, 0, 0, 0, 0, 0, "Index of 6 used to index descriptor array of length 6."});
1173         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1174                          call_source_runtime, true, 0, 6, 0, 0, 0, 0, "Index of 6 used to index descriptor array of length 6."});
1175         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1176                          call_source_runtime, true, 0, 0, 6, 0, 0, 0, "Index of 6 used to index descriptor array of length 6."});
1177         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1178                          call_source_runtime, true, 0, 0, 0, 6, 0, 0, "Index of 6 used to index descriptor array of length 6."});
1179         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1180                          call_source_runtime, true, 0, 0, 0, 0, 6, 0, "Index of 6 used to index descriptor array of length 6."});
1181         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1182                          call_source_runtime, true, 0, 0, 0, 0, 0, 6, "Index of 6 used to index descriptor array of length 6."});
1183 
1184         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1185                          call_source_runtime, true, 5, 0, 0, 0, 0, 0, "Descriptor index 5 is uninitialized."});
1186         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1187                          call_source_runtime, true, 0, 5, 0, 0, 0, 0, "Descriptor index 5 is uninitialized."});
1188         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1189                          call_source_runtime, true, 0, 0, 5, 0, 0, 0, "Descriptor index 5 is uninitialized."});
1190         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1191                          call_source_runtime, true, 0, 0, 0, 5, 0, 0, "Descriptor index 5 is uninitialized."});
1192         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1193                          call_source_runtime, true, 0, 0, 0, 0, 5, 0, "Descriptor index 5 is uninitialized."});
1194         tests.push_back({rgen_source_runtime, ahit_source_runtime, chit_source_runtime, miss_source_runtime, intr_source_runtime,
1195                          call_source_runtime, true, 0, 0, 0, 0, 0, 5, "Descriptor index 5 is uninitialized."});
1196     }
1197 
1198     PFN_vkCreateRayTracingPipelinesNV vkCreateRayTracingPipelinesNV = reinterpret_cast<PFN_vkCreateRayTracingPipelinesNV>(
1199         vkGetDeviceProcAddr(m_device->handle(), "vkCreateRayTracingPipelinesNV"));
1200     ASSERT_TRUE(vkCreateRayTracingPipelinesNV != nullptr);
1201 
1202     PFN_vkGetRayTracingShaderGroupHandlesNV vkGetRayTracingShaderGroupHandlesNV =
1203         reinterpret_cast<PFN_vkGetRayTracingShaderGroupHandlesNV>(
1204             vkGetDeviceProcAddr(m_device->handle(), "vkGetRayTracingShaderGroupHandlesNV"));
1205     ASSERT_TRUE(vkGetRayTracingShaderGroupHandlesNV != nullptr);
1206 
1207     PFN_vkCmdTraceRaysNV vkCmdTraceRaysNV =
1208         reinterpret_cast<PFN_vkCmdTraceRaysNV>(vkGetDeviceProcAddr(m_device->handle(), "vkCmdTraceRaysNV"));
1209     ASSERT_TRUE(vkCmdTraceRaysNV != nullptr);
1210 
1211     for (const auto &test : tests) {
1212         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, test.expected_error);
1213 
1214         VkShaderObj rgen_shader(m_device, test.rgen_shader_source.c_str(), VK_SHADER_STAGE_RAYGEN_BIT_NV, this, "main");
1215         VkShaderObj ahit_shader(m_device, test.ahit_shader_source.c_str(), VK_SHADER_STAGE_ANY_HIT_BIT_NV, this, "main");
1216         VkShaderObj chit_shader(m_device, test.chit_shader_source.c_str(), VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV, this, "main");
1217         VkShaderObj miss_shader(m_device, test.miss_shader_source.c_str(), VK_SHADER_STAGE_MISS_BIT_NV, this, "main");
1218         VkShaderObj intr_shader(m_device, test.intr_shader_source.c_str(), VK_SHADER_STAGE_INTERSECTION_BIT_NV, this, "main");
1219         VkShaderObj call_shader(m_device, test.call_shader_source.c_str(), VK_SHADER_STAGE_CALLABLE_BIT_NV, this, "main");
1220 
1221         VkPipelineShaderStageCreateInfo stage_create_infos[6] = {};
1222         stage_create_infos[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1223         stage_create_infos[0].stage = VK_SHADER_STAGE_RAYGEN_BIT_NV;
1224         stage_create_infos[0].module = rgen_shader.handle();
1225         stage_create_infos[0].pName = "main";
1226 
1227         stage_create_infos[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1228         stage_create_infos[1].stage = VK_SHADER_STAGE_ANY_HIT_BIT_NV;
1229         stage_create_infos[1].module = ahit_shader.handle();
1230         stage_create_infos[1].pName = "main";
1231 
1232         stage_create_infos[2].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1233         stage_create_infos[2].stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV;
1234         stage_create_infos[2].module = chit_shader.handle();
1235         stage_create_infos[2].pName = "main";
1236 
1237         stage_create_infos[3].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1238         stage_create_infos[3].stage = VK_SHADER_STAGE_MISS_BIT_NV;
1239         stage_create_infos[3].module = miss_shader.handle();
1240         stage_create_infos[3].pName = "main";
1241 
1242         stage_create_infos[4].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1243         stage_create_infos[4].stage = VK_SHADER_STAGE_INTERSECTION_BIT_NV;
1244         stage_create_infos[4].module = intr_shader.handle();
1245         stage_create_infos[4].pName = "main";
1246 
1247         stage_create_infos[5].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1248         stage_create_infos[5].stage = VK_SHADER_STAGE_CALLABLE_BIT_NV;
1249         stage_create_infos[5].module = call_shader.handle();
1250         stage_create_infos[5].pName = "main";
1251 
1252         VkRayTracingShaderGroupCreateInfoNV group_create_infos[4] = {};
1253         group_create_infos[0].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV;
1254         group_create_infos[0].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV;
1255         group_create_infos[0].generalShader = 0;  // rgen
1256         group_create_infos[0].closestHitShader = VK_SHADER_UNUSED_NV;
1257         group_create_infos[0].anyHitShader = VK_SHADER_UNUSED_NV;
1258         group_create_infos[0].intersectionShader = VK_SHADER_UNUSED_NV;
1259 
1260         group_create_infos[1].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV;
1261         group_create_infos[1].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV;
1262         group_create_infos[1].generalShader = 3;  // miss
1263         group_create_infos[1].closestHitShader = VK_SHADER_UNUSED_NV;
1264         group_create_infos[1].anyHitShader = VK_SHADER_UNUSED_NV;
1265         group_create_infos[1].intersectionShader = VK_SHADER_UNUSED_NV;
1266 
1267         group_create_infos[2].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV;
1268         group_create_infos[2].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_NV;
1269         group_create_infos[2].generalShader = VK_SHADER_UNUSED_NV;
1270         group_create_infos[2].closestHitShader = 2;
1271         group_create_infos[2].anyHitShader = 1;
1272         group_create_infos[2].intersectionShader = 4;
1273 
1274         group_create_infos[3].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_NV;
1275         group_create_infos[3].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_NV;
1276         group_create_infos[3].generalShader = 5;  // call
1277         group_create_infos[3].closestHitShader = VK_SHADER_UNUSED_NV;
1278         group_create_infos[3].anyHitShader = VK_SHADER_UNUSED_NV;
1279         group_create_infos[3].intersectionShader = VK_SHADER_UNUSED_NV;
1280 
1281         VkRayTracingPipelineCreateInfoNV pipeline_ci = {};
1282         pipeline_ci.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_NV;
1283         pipeline_ci.stageCount = 6;
1284         pipeline_ci.pStages = stage_create_infos;
1285         pipeline_ci.groupCount = 4;
1286         pipeline_ci.pGroups = group_create_infos;
1287         pipeline_ci.maxRecursionDepth = 2;
1288         pipeline_ci.layout = test.variable_length ? pipeline_layout_variable.handle() : pipeline_layout.handle();
1289 
1290         VkPipeline pipeline = VK_NULL_HANDLE;
1291         ASSERT_VK_SUCCESS(vkCreateRayTracingPipelinesNV(m_device->handle(), VK_NULL_HANDLE, 1, &pipeline_ci, nullptr, &pipeline));
1292 
1293         std::vector<uint8_t> shader_binding_table_data;
1294         shader_binding_table_data.resize(static_cast<std::size_t>(shader_binding_table_buffer_size), 0);
1295         ASSERT_VK_SUCCESS(vkGetRayTracingShaderGroupHandlesNV(m_device->handle(), pipeline, 0, 4,
1296                                                               static_cast<std::size_t>(shader_binding_table_buffer_size),
1297                                                               shader_binding_table_data.data()));
1298 
1299         uint8_t *mapped_shader_binding_table_data = (uint8_t *)shader_binding_table_buffer.memory().map();
1300         std::memcpy(mapped_shader_binding_table_data, shader_binding_table_data.data(), shader_binding_table_data.size());
1301         shader_binding_table_buffer.memory().unmap();
1302 
1303         ray_tracing_command_buffer.begin();
1304 
1305         vkCmdBindPipeline(ray_tracing_command_buffer.handle(), VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, pipeline);
1306         vkCmdBindDescriptorSets(ray_tracing_command_buffer.handle(), VK_PIPELINE_BIND_POINT_RAY_TRACING_NV,
1307                                 test.variable_length ? pipeline_layout_variable.handle() : pipeline_layout.handle(), 0, 1,
1308                                 test.variable_length ? &ds_variable.set_ : &ds.set_, 0, nullptr);
1309 
1310         vkCmdTraceRaysNV(ray_tracing_command_buffer.handle(), shader_binding_table_buffer.handle(),
1311                          ray_tracing_properties.shaderGroupHandleSize * 0ull, shader_binding_table_buffer.handle(),
1312                          ray_tracing_properties.shaderGroupHandleSize * 1ull, ray_tracing_properties.shaderGroupHandleSize,
1313                          shader_binding_table_buffer.handle(), ray_tracing_properties.shaderGroupHandleSize * 2ull,
1314                          ray_tracing_properties.shaderGroupHandleSize, shader_binding_table_buffer.handle(),
1315                          ray_tracing_properties.shaderGroupHandleSize * 3ull, ray_tracing_properties.shaderGroupHandleSize,
1316                          /*width=*/1, /*height=*/1, /*depth=*/1);
1317 
1318         ray_tracing_command_buffer.end();
1319 
1320         // Update the index of the texture that the shaders should read
1321         uint32_t *mapped_storage_buffer_data = (uint32_t *)storage_buffer.memory().map();
1322         mapped_storage_buffer_data[0] = test.rgen_index;
1323         mapped_storage_buffer_data[1] = test.ahit_index;
1324         mapped_storage_buffer_data[2] = test.chit_index;
1325         mapped_storage_buffer_data[3] = test.miss_index;
1326         mapped_storage_buffer_data[4] = test.intr_index;
1327         mapped_storage_buffer_data[5] = test.call_index;
1328         mapped_storage_buffer_data[6] = 0;
1329         mapped_storage_buffer_data[7] = 0;
1330         mapped_storage_buffer_data[8] = 0;
1331         mapped_storage_buffer_data[9] = 0;
1332         mapped_storage_buffer_data[10] = 0;
1333         mapped_storage_buffer_data[11] = 0;
1334         storage_buffer.memory().unmap();
1335 
1336         vkQueueSubmit(ray_tracing_queue, 1, &submit_info, VK_NULL_HANDLE);
1337         vkQueueWaitIdle(ray_tracing_queue);
1338         m_errorMonitor->VerifyFound();
1339 
1340         mapped_storage_buffer_data = (uint32_t *)storage_buffer.memory().map();
1341         ASSERT_TRUE(mapped_storage_buffer_data[6] == 1);
1342         ASSERT_TRUE(mapped_storage_buffer_data[7] == 2);
1343         ASSERT_TRUE(mapped_storage_buffer_data[8] == 3);
1344         ASSERT_TRUE(mapped_storage_buffer_data[9] == 4);
1345         ASSERT_TRUE(mapped_storage_buffer_data[10] == 5);
1346         ASSERT_TRUE(mapped_storage_buffer_data[11] == 6);
1347         storage_buffer.memory().unmap();
1348 
1349         vkDestroyPipeline(m_device->handle(), pipeline, nullptr);
1350     }
1351 }
1352 
TEST_F(VkLayerTest,InvalidDescriptorPoolConsistency)1353 TEST_F(VkLayerTest, InvalidDescriptorPoolConsistency) {
1354     VkResult err;
1355 
1356     TEST_DESCRIPTION("Allocate descriptor sets from one DS pool and attempt to delete them from another.");
1357 
1358     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkFreeDescriptorSets-pDescriptorSets-parent");
1359 
1360     ASSERT_NO_FATAL_FAILURE(Init());
1361     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
1362 
1363     VkDescriptorPoolSize ds_type_count = {};
1364     ds_type_count.type = VK_DESCRIPTOR_TYPE_SAMPLER;
1365     ds_type_count.descriptorCount = 1;
1366 
1367     VkDescriptorPoolCreateInfo ds_pool_ci = {};
1368     ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
1369     ds_pool_ci.pNext = NULL;
1370     ds_pool_ci.flags = 0;
1371     ds_pool_ci.maxSets = 1;
1372     ds_pool_ci.poolSizeCount = 1;
1373     ds_pool_ci.pPoolSizes = &ds_type_count;
1374 
1375     VkDescriptorPool bad_pool;
1376     err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &bad_pool);
1377     ASSERT_VK_SUCCESS(err);
1378 
1379     OneOffDescriptorSet descriptor_set(m_device, {
1380                                                      {0, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr},
1381                                                  });
1382 
1383     err = vkFreeDescriptorSets(m_device->device(), bad_pool, 1, &descriptor_set.set_);
1384 
1385     m_errorMonitor->VerifyFound();
1386 
1387     vkDestroyDescriptorPool(m_device->device(), bad_pool, NULL);
1388 }
1389 
TEST_F(VkLayerTest,DrawWithPipelineIncompatibleWithSubpass)1390 TEST_F(VkLayerTest, DrawWithPipelineIncompatibleWithSubpass) {
1391     TEST_DESCRIPTION("Use a pipeline for the wrong subpass in a render pass instance");
1392 
1393     ASSERT_NO_FATAL_FAILURE(Init());
1394 
1395     // A renderpass with two subpasses, both writing the same attachment.
1396     VkAttachmentDescription attach[] = {
1397         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
1398          VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED,
1399          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1400     };
1401     VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
1402     VkSubpassDescription subpasses[] = {
1403         {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr},
1404         {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr},
1405     };
1406     VkSubpassDependency dep = {0,
1407                                1,
1408                                VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1409                                VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1410                                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1411                                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1412                                VK_DEPENDENCY_BY_REGION_BIT};
1413     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 2, subpasses, 1, &dep};
1414     VkRenderPass rp;
1415     VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp);
1416     ASSERT_VK_SUCCESS(err);
1417 
1418     VkImageObj image(m_device);
1419     image.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
1420     VkImageView imageView = image.targetView(VK_FORMAT_R8G8B8A8_UNORM);
1421 
1422     VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &imageView, 32, 32, 1};
1423     VkFramebuffer fb;
1424     err = vkCreateFramebuffer(m_device->device(), &fbci, nullptr, &fb);
1425     ASSERT_VK_SUCCESS(err);
1426 
1427     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
1428     VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
1429     VkPipelineObj pipe(m_device);
1430     pipe.AddDefaultColorAttachment();
1431     pipe.AddShader(&vs);
1432     pipe.AddShader(&fs);
1433     VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f};
1434     m_viewports.push_back(viewport);
1435     pipe.SetViewport(m_viewports);
1436     VkRect2D rect = {};
1437     m_scissors.push_back(rect);
1438     pipe.SetScissor(m_scissors);
1439 
1440     const VkPipelineLayoutObj pl(m_device);
1441     pipe.CreateVKPipeline(pl.handle(), rp);
1442 
1443     m_commandBuffer->begin();
1444 
1445     VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1446                                   nullptr,
1447                                   rp,
1448                                   fb,
1449                                   {{
1450                                        0,
1451                                        0,
1452                                    },
1453                                    {32, 32}},
1454                                   0,
1455                                   nullptr};
1456 
1457     // subtest 1: bind in the wrong subpass
1458     vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE);
1459     vkCmdNextSubpass(m_commandBuffer->handle(), VK_SUBPASS_CONTENTS_INLINE);
1460     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "built for subpass 0 but used in subpass 1");
1461     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
1462     vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
1463     m_errorMonitor->VerifyFound();
1464 
1465     vkCmdEndRenderPass(m_commandBuffer->handle());
1466 
1467     // subtest 2: bind in correct subpass, then transition to next subpass
1468     vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE);
1469     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
1470     vkCmdNextSubpass(m_commandBuffer->handle(), VK_SUBPASS_CONTENTS_INLINE);
1471     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "built for subpass 0 but used in subpass 1");
1472     vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
1473     m_errorMonitor->VerifyFound();
1474 
1475     vkCmdEndRenderPass(m_commandBuffer->handle());
1476 
1477     m_commandBuffer->end();
1478 
1479     vkDestroyFramebuffer(m_device->device(), fb, nullptr);
1480     vkDestroyRenderPass(m_device->device(), rp, nullptr);
1481 }
1482 
TEST_F(VkLayerTest,ImageBarrierSubpassConflict)1483 TEST_F(VkLayerTest, ImageBarrierSubpassConflict) {
1484     TEST_DESCRIPTION("Check case where subpass index references different image from image barrier");
1485     ASSERT_NO_FATAL_FAILURE(Init());
1486 
1487     // Create RP/FB combo where subpass has incorrect index attachment, this is 2nd half of "VUID-vkCmdPipelineBarrier-image-02635"
1488     VkAttachmentDescription attach[] = {
1489         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
1490          VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED,
1491          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1492         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
1493          VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED,
1494          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1495     };
1496     // ref attachment points to wrong attachment index compared to img_barrier below
1497     VkAttachmentReference ref = {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
1498     VkSubpassDescription subpasses[] = {
1499         {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr},
1500     };
1501     VkSubpassDependency dep = {0,
1502                                0,
1503                                VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1504                                VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1505                                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1506                                VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1507                                VK_DEPENDENCY_BY_REGION_BIT};
1508 
1509     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 2, attach, 1, subpasses, 1, &dep};
1510     VkRenderPass rp;
1511 
1512     VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp);
1513     ASSERT_VK_SUCCESS(err);
1514 
1515     VkImageObj image(m_device);
1516     image.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
1517     VkImageView imageView = image.targetView(VK_FORMAT_R8G8B8A8_UNORM);
1518     VkImageObj image2(m_device);
1519     image2.InitNoLayout(32, 32, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
1520     VkImageView imageView2 = image2.targetView(VK_FORMAT_R8G8B8A8_UNORM);
1521     // re-use imageView from start of test
1522     VkImageView iv_array[2] = {imageView, imageView2};
1523 
1524     VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 2, iv_array, 32, 32, 1};
1525     VkFramebuffer fb;
1526     err = vkCreateFramebuffer(m_device->device(), &fbci, nullptr, &fb);
1527     ASSERT_VK_SUCCESS(err);
1528 
1529     VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1530                                   nullptr,
1531                                   rp,
1532                                   fb,
1533                                   {{
1534                                        0,
1535                                        0,
1536                                    },
1537                                    {32, 32}},
1538                                   0,
1539                                   nullptr};
1540 
1541     VkImageMemoryBarrier img_barrier = {};
1542     img_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1543     img_barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1544     img_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1545     img_barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1546     img_barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1547     img_barrier.image = image.handle(); /* barrier references image from attachment index 0 */
1548     img_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1549     img_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1550     img_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1551     img_barrier.subresourceRange.baseArrayLayer = 0;
1552     img_barrier.subresourceRange.baseMipLevel = 0;
1553     img_barrier.subresourceRange.layerCount = 1;
1554     img_barrier.subresourceRange.levelCount = 1;
1555     m_commandBuffer->begin();
1556     vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE);
1557     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdPipelineBarrier-image-02635");
1558     vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1559                          VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1,
1560                          &img_barrier);
1561     m_errorMonitor->VerifyFound();
1562 
1563     vkDestroyFramebuffer(m_device->device(), fb, nullptr);
1564     vkDestroyRenderPass(m_device->device(), rp, nullptr);
1565 }
1566 
TEST_F(VkLayerTest,RenderPassCreateAttachmentIndexOutOfRange)1567 TEST_F(VkLayerTest, RenderPassCreateAttachmentIndexOutOfRange) {
1568     // Check for VK_KHR_get_physical_device_properties2
1569     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
1570         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1571     }
1572 
1573     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1574     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
1575     ASSERT_NO_FATAL_FAILURE(InitState());
1576 
1577     // There are no attachments, but refer to attachment 0.
1578     VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
1579     VkSubpassDescription subpasses[] = {
1580         {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &ref, nullptr, nullptr, 0, nullptr},
1581     };
1582 
1583     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 1, subpasses, 0, nullptr};
1584 
1585     // "... must be less than the total number of attachments ..."
1586     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-attachment-00834",
1587                          "VUID-VkRenderPassCreateInfo2KHR-attachment-03051");
1588 }
1589 
TEST_F(VkLayerTest,RenderPassCreateAttachmentReadOnlyButCleared)1590 TEST_F(VkLayerTest, RenderPassCreateAttachmentReadOnlyButCleared) {
1591     // Check for VK_KHR_get_physical_device_properties2
1592     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
1593         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1594     }
1595 
1596     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1597 
1598     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
1599     bool maintenance2Supported = rp2Supported;
1600 
1601     // Check for VK_KHR_maintenance2
1602     if (!rp2Supported && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE2_EXTENSION_NAME)) {
1603         m_device_extension_names.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME);
1604         maintenance2Supported = true;
1605     }
1606 
1607     ASSERT_NO_FATAL_FAILURE(InitState());
1608 
1609     if (m_device->props.apiVersion < VK_API_VERSION_1_1) {
1610         maintenance2Supported = true;
1611     }
1612 
1613     VkAttachmentDescription description = {0,
1614                                            VK_FORMAT_D32_SFLOAT_S8_UINT,
1615                                            VK_SAMPLE_COUNT_1_BIT,
1616                                            VK_ATTACHMENT_LOAD_OP_CLEAR,
1617                                            VK_ATTACHMENT_STORE_OP_DONT_CARE,
1618                                            VK_ATTACHMENT_LOAD_OP_CLEAR,
1619                                            VK_ATTACHMENT_STORE_OP_DONT_CARE,
1620                                            VK_IMAGE_LAYOUT_GENERAL,
1621                                            VK_IMAGE_LAYOUT_GENERAL};
1622 
1623     VkAttachmentReference depth_stencil_ref = {0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL};
1624 
1625     VkSubpassDescription subpass = {0,      VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, &depth_stencil_ref, 0,
1626                                     nullptr};
1627 
1628     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &description, 1, &subpass, 0, nullptr};
1629 
1630     // VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL but depth cleared
1631     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-pAttachments-00836",
1632                          "VUID-VkRenderPassCreateInfo2KHR-pAttachments-02522");
1633 
1634     if (maintenance2Supported) {
1635         // VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL but depth cleared
1636         depth_stencil_ref.layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
1637 
1638         TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1639                              "VUID-VkRenderPassCreateInfo-pAttachments-01566", nullptr);
1640 
1641         // VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL but depth cleared
1642         depth_stencil_ref.layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
1643 
1644         TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1645                              "VUID-VkRenderPassCreateInfo-pAttachments-01567", nullptr);
1646     }
1647 }
1648 
TEST_F(VkLayerTest,RenderPassCreateAttachmentMismatchingLayoutsColor)1649 TEST_F(VkLayerTest, RenderPassCreateAttachmentMismatchingLayoutsColor) {
1650     TEST_DESCRIPTION("Attachment is used simultaneously as two color attachments with different layouts.");
1651 
1652     // Check for VK_KHR_get_physical_device_properties2
1653     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
1654         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1655     }
1656 
1657     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1658     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
1659     ASSERT_NO_FATAL_FAILURE(InitState());
1660 
1661     VkAttachmentDescription attach[] = {
1662         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
1663          VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED,
1664          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1665     };
1666     VkAttachmentReference refs[] = {
1667         {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1668         {0, VK_IMAGE_LAYOUT_GENERAL},
1669     };
1670     VkSubpassDescription subpasses[] = {
1671         {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 2, refs, nullptr, nullptr, 0, nullptr},
1672     };
1673 
1674     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 1, subpasses, 0, nullptr};
1675 
1676     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1677                          "subpass 0 already uses attachment 0 with a different image layout",
1678                          "subpass 0 already uses attachment 0 with a different image layout");
1679 }
1680 
TEST_F(VkLayerTest,RenderPassCreateAttachmentDescriptionInvalidFinalLayout)1681 TEST_F(VkLayerTest, RenderPassCreateAttachmentDescriptionInvalidFinalLayout) {
1682     TEST_DESCRIPTION("VkAttachmentDescription's finalLayout must not be UNDEFINED or PREINITIALIZED");
1683 
1684     // Check for VK_KHR_get_physical_device_properties2
1685     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
1686         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1687     }
1688 
1689     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1690     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
1691     ASSERT_NO_FATAL_FAILURE(InitState());
1692 
1693     VkAttachmentDescription attach_desc = {};
1694     attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM;
1695     attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
1696     attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1697     attach_desc.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1698     attach_desc.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1699     attach_desc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1700     attach_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1701     attach_desc.finalLayout = VK_IMAGE_LAYOUT_UNDEFINED;
1702     VkAttachmentReference attach_ref = {};
1703     attach_ref.attachment = 0;
1704     attach_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1705     VkSubpassDescription subpass = {};
1706     subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
1707     subpass.colorAttachmentCount = 1;
1708     subpass.pColorAttachments = &attach_ref;
1709     VkRenderPassCreateInfo rpci = {};
1710     rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1711     rpci.attachmentCount = 1;
1712     rpci.pAttachments = &attach_desc;
1713     rpci.subpassCount = 1;
1714     rpci.pSubpasses = &subpass;
1715 
1716     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843",
1717                          "VUID-VkAttachmentDescription2KHR-finalLayout-03061");
1718 
1719     attach_desc.finalLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
1720     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentDescription-finalLayout-00843",
1721                          "VUID-VkAttachmentDescription2KHR-finalLayout-03061");
1722 }
1723 
TEST_F(VkLayerTest,RenderPassCreateAttachmentsMisc)1724 TEST_F(VkLayerTest, RenderPassCreateAttachmentsMisc) {
1725     TEST_DESCRIPTION(
1726         "Ensure that CreateRenderPass produces the expected validation errors when a subpass's attachments violate the valid usage "
1727         "conditions.");
1728 
1729     // Check for VK_KHR_get_physical_device_properties2
1730     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
1731         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1732     }
1733 
1734     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1735     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
1736     ASSERT_NO_FATAL_FAILURE(InitState());
1737 
1738     std::vector<VkAttachmentDescription> attachments = {
1739         // input attachments
1740         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
1741          VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL},
1742         // color attachments
1743         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
1744          VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1745          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1746         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
1747          VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1748          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1749         // depth attachment
1750         {0, VK_FORMAT_D24_UNORM_S8_UINT, VK_SAMPLE_COUNT_4_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
1751          VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1752          VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL},
1753         // resolve attachment
1754         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
1755          VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1756          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1757         // preserve attachments
1758         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_4_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
1759          VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1760          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1761     };
1762 
1763     std::vector<VkAttachmentReference> input = {
1764         {0, VK_IMAGE_LAYOUT_GENERAL},
1765     };
1766     std::vector<VkAttachmentReference> color = {
1767         {1, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1768         {2, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1769     };
1770     VkAttachmentReference depth = {3, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
1771     std::vector<VkAttachmentReference> resolve = {
1772         {4, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1773         {VK_ATTACHMENT_UNUSED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1774     };
1775     std::vector<uint32_t> preserve = {5};
1776 
1777     VkSubpassDescription subpass = {0,
1778                                     VK_PIPELINE_BIND_POINT_GRAPHICS,
1779                                     (uint32_t)input.size(),
1780                                     input.data(),
1781                                     (uint32_t)color.size(),
1782                                     color.data(),
1783                                     resolve.data(),
1784                                     &depth,
1785                                     (uint32_t)preserve.size(),
1786                                     preserve.data()};
1787 
1788     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
1789                                    nullptr,
1790                                    0,
1791                                    (uint32_t)attachments.size(),
1792                                    attachments.data(),
1793                                    1,
1794                                    &subpass,
1795                                    0,
1796                                    nullptr};
1797 
1798     // Test too many color attachments
1799     {
1800         std::vector<VkAttachmentReference> too_many_colors(m_device->props.limits.maxColorAttachments + 1, color[0]);
1801         subpass.colorAttachmentCount = (uint32_t)too_many_colors.size();
1802         subpass.pColorAttachments = too_many_colors.data();
1803         subpass.pResolveAttachments = NULL;
1804 
1805         TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1806                              "VUID-VkSubpassDescription-colorAttachmentCount-00845",
1807                              "VUID-VkSubpassDescription2KHR-colorAttachmentCount-03063");
1808 
1809         subpass.colorAttachmentCount = (uint32_t)color.size();
1810         subpass.pColorAttachments = color.data();
1811         subpass.pResolveAttachments = resolve.data();
1812     }
1813 
1814     // Test sample count mismatch between color buffers
1815     attachments[subpass.pColorAttachments[1].attachment].samples = VK_SAMPLE_COUNT_8_BIT;
1816     depth.attachment = VK_ATTACHMENT_UNUSED;  // Avoids triggering 01418
1817 
1818     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1819                          "VUID-VkSubpassDescription-pColorAttachments-01417",
1820                          "VUID-VkSubpassDescription2KHR-pColorAttachments-03069");
1821 
1822     depth.attachment = 3;
1823     attachments[subpass.pColorAttachments[1].attachment].samples = attachments[subpass.pColorAttachments[0].attachment].samples;
1824 
1825     // Test sample count mismatch between color buffers and depth buffer
1826     attachments[subpass.pDepthStencilAttachment->attachment].samples = VK_SAMPLE_COUNT_8_BIT;
1827     subpass.colorAttachmentCount = 1;
1828 
1829     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1830                          "VUID-VkSubpassDescription-pDepthStencilAttachment-01418",
1831                          "VUID-VkSubpassDescription2KHR-pDepthStencilAttachment-03071");
1832 
1833     attachments[subpass.pDepthStencilAttachment->attachment].samples = attachments[subpass.pColorAttachments[0].attachment].samples;
1834     subpass.colorAttachmentCount = (uint32_t)color.size();
1835 
1836     // Test resolve attachment with UNUSED color attachment
1837     color[0].attachment = VK_ATTACHMENT_UNUSED;
1838 
1839     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1840                          "VUID-VkSubpassDescription-pResolveAttachments-00847",
1841                          "VUID-VkSubpassDescription2KHR-pResolveAttachments-03065");
1842 
1843     color[0].attachment = 1;
1844 
1845     // Test resolve from a single-sampled color attachment
1846     attachments[subpass.pColorAttachments[0].attachment].samples = VK_SAMPLE_COUNT_1_BIT;
1847     subpass.colorAttachmentCount = 1;           // avoid mismatch (00337), and avoid double report
1848     subpass.pDepthStencilAttachment = nullptr;  // avoid mismatch (01418)
1849 
1850     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1851                          "VUID-VkSubpassDescription-pResolveAttachments-00848",
1852                          "VUID-VkSubpassDescription2KHR-pResolveAttachments-03066");
1853 
1854     attachments[subpass.pColorAttachments[0].attachment].samples = VK_SAMPLE_COUNT_4_BIT;
1855     subpass.colorAttachmentCount = (uint32_t)color.size();
1856     subpass.pDepthStencilAttachment = &depth;
1857 
1858     // Test resolve to a multi-sampled resolve attachment
1859     attachments[subpass.pResolveAttachments[0].attachment].samples = VK_SAMPLE_COUNT_4_BIT;
1860 
1861     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1862                          "VUID-VkSubpassDescription-pResolveAttachments-00849",
1863                          "VUID-VkSubpassDescription2KHR-pResolveAttachments-03067");
1864 
1865     attachments[subpass.pResolveAttachments[0].attachment].samples = VK_SAMPLE_COUNT_1_BIT;
1866 
1867     // Test with color/resolve format mismatch
1868     attachments[subpass.pColorAttachments[0].attachment].format = VK_FORMAT_R8G8B8A8_SRGB;
1869 
1870     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1871                          "VUID-VkSubpassDescription-pResolveAttachments-00850",
1872                          "VUID-VkSubpassDescription2KHR-pResolveAttachments-03068");
1873 
1874     attachments[subpass.pColorAttachments[0].attachment].format = attachments[subpass.pResolveAttachments[0].attachment].format;
1875 
1876     // Test for UNUSED preserve attachments
1877     preserve[0] = VK_ATTACHMENT_UNUSED;
1878 
1879     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDescription-attachment-00853",
1880                          "VUID-VkSubpassDescription2KHR-attachment-03073");
1881 
1882     preserve[0] = 5;
1883     // Test for preserve attachments used elsewhere in the subpass
1884     color[0].attachment = preserve[0];
1885 
1886     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1887                          "VUID-VkSubpassDescription-pPreserveAttachments-00854",
1888                          "VUID-VkSubpassDescription2KHR-pPreserveAttachments-03074");
1889 
1890     color[0].attachment = 1;
1891     input[0].attachment = 0;
1892     input[0].layout = VK_IMAGE_LAYOUT_GENERAL;
1893 
1894     // Test for attachment used first as input with loadOp=CLEAR
1895     {
1896         std::vector<VkSubpassDescription> subpasses = {subpass, subpass, subpass};
1897         subpasses[0].inputAttachmentCount = 0;
1898         subpasses[1].inputAttachmentCount = 0;
1899         attachments[input[0].attachment].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1900         VkRenderPassCreateInfo rpci_multipass = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
1901                                                  nullptr,
1902                                                  0,
1903                                                  (uint32_t)attachments.size(),
1904                                                  attachments.data(),
1905                                                  (uint32_t)subpasses.size(),
1906                                                  subpasses.data(),
1907                                                  0,
1908                                                  nullptr};
1909 
1910         TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci_multipass, rp2Supported,
1911                              "VUID-VkSubpassDescription-loadOp-00846", "VUID-VkSubpassDescription2KHR-loadOp-03064");
1912 
1913         attachments[input[0].attachment].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1914     }
1915 }
1916 
TEST_F(VkLayerTest,RenderPassCreateAttachmentReferenceInvalidLayout)1917 TEST_F(VkLayerTest, RenderPassCreateAttachmentReferenceInvalidLayout) {
1918     TEST_DESCRIPTION("Attachment reference uses PREINITIALIZED or UNDEFINED layouts");
1919 
1920     // Check for VK_KHR_get_physical_device_properties2
1921     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
1922         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1923     }
1924 
1925     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1926     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
1927     ASSERT_NO_FATAL_FAILURE(InitState());
1928 
1929     VkAttachmentDescription attach[] = {
1930         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
1931          VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_UNDEFINED,
1932          VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL},
1933     };
1934     VkAttachmentReference refs[] = {
1935         {0, VK_IMAGE_LAYOUT_UNDEFINED},
1936     };
1937     VkSubpassDescription subpasses[] = {
1938         {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, refs, nullptr, nullptr, 0, nullptr},
1939     };
1940 
1941     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, attach, 1, subpasses, 0, nullptr};
1942 
1943     // Use UNDEFINED layout
1944     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentReference-layout-00857",
1945                          "VUID-VkAttachmentReference2KHR-layout-03077");
1946 
1947     // Use PREINITIALIZED layout
1948     refs[0].layout = VK_IMAGE_LAYOUT_PREINITIALIZED;
1949     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkAttachmentReference-layout-00857",
1950                          "VUID-VkAttachmentReference2KHR-layout-03077");
1951 }
1952 
TEST_F(VkLayerTest,RenderPassCreateOverlappingCorrelationMasks)1953 TEST_F(VkLayerTest, RenderPassCreateOverlappingCorrelationMasks) {
1954     TEST_DESCRIPTION("Create a subpass with overlapping correlation masks");
1955 
1956     // Check for VK_KHR_get_physical_device_properties2
1957     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
1958         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
1959     }
1960 
1961     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
1962     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
1963 
1964     if (!rp2Supported) {
1965         if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
1966             m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME);
1967         } else {
1968             printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_MULTIVIEW_EXTENSION_NAME);
1969             return;
1970         }
1971     }
1972 
1973     ASSERT_NO_FATAL_FAILURE(InitState());
1974 
1975     VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr};
1976     uint32_t viewMasks[] = {0x3u};
1977     uint32_t correlationMasks[] = {0x1u, 0x3u};
1978     VkRenderPassMultiviewCreateInfo rpmvci = {
1979         VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, nullptr, 1, viewMasks, 0, nullptr, 2, correlationMasks};
1980 
1981     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpmvci, 0, 0, nullptr, 1, &subpass, 0, nullptr};
1982 
1983     // Correlation masks must not overlap
1984     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
1985                          "VUID-VkRenderPassMultiviewCreateInfo-pCorrelationMasks-00841",
1986                          "VUID-VkRenderPassCreateInfo2KHR-pCorrelatedViewMasks-03056");
1987 
1988     // Check for more specific "don't set any correlation masks when multiview is not enabled"
1989     if (rp2Supported) {
1990         viewMasks[0] = 0;
1991         correlationMasks[0] = 0;
1992         correlationMasks[1] = 0;
1993         safe_VkRenderPassCreateInfo2KHR safe_rpci2;
1994         ConvertVkRenderPassCreateInfoToV2KHR(&rpci, &safe_rpci2);
1995 
1996         TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), safe_rpci2.ptr(),
1997                                  "VUID-VkRenderPassCreateInfo2KHR-viewMask-03057");
1998     }
1999 }
2000 
TEST_F(VkLayerTest,RenderPassCreateInvalidViewMasks)2001 TEST_F(VkLayerTest, RenderPassCreateInvalidViewMasks) {
2002     TEST_DESCRIPTION("Create a subpass with the wrong number of view masks, or inconsistent setting of view masks");
2003 
2004     // Check for VK_KHR_get_physical_device_properties2
2005     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2006         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2007     }
2008 
2009     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2010     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
2011 
2012     if (!rp2Supported) {
2013         if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
2014             m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME);
2015         } else {
2016             printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_MULTIVIEW_EXTENSION_NAME);
2017             return;
2018         }
2019     }
2020 
2021     ASSERT_NO_FATAL_FAILURE(InitState());
2022 
2023     VkSubpassDescription subpasses[] = {
2024         {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr},
2025         {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr},
2026     };
2027     uint32_t viewMasks[] = {0x3u, 0u};
2028     VkRenderPassMultiviewCreateInfo rpmvci = {
2029         VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, nullptr, 1, viewMasks, 0, nullptr, 0, nullptr};
2030 
2031     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpmvci, 0, 0, nullptr, 2, subpasses, 0, nullptr};
2032 
2033     // Not enough view masks
2034     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkRenderPassCreateInfo-pNext-01928",
2035                          "VUID-VkRenderPassCreateInfo2KHR-viewMask-03058");
2036 }
2037 
TEST_F(VkLayerTest,RenderPassCreateInvalidInputAttachmentReferences)2038 TEST_F(VkLayerTest, RenderPassCreateInvalidInputAttachmentReferences) {
2039     TEST_DESCRIPTION("Create a subpass with the meta data aspect mask set for an input attachment");
2040 
2041     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2042 
2043     if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE2_EXTENSION_NAME)) {
2044         m_device_extension_names.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME);
2045     } else {
2046         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_MAINTENANCE2_EXTENSION_NAME);
2047         return;
2048     }
2049 
2050     ASSERT_NO_FATAL_FAILURE(InitState());
2051 
2052     VkAttachmentDescription attach = {0,
2053                                       VK_FORMAT_R8G8B8A8_UNORM,
2054                                       VK_SAMPLE_COUNT_1_BIT,
2055                                       VK_ATTACHMENT_LOAD_OP_DONT_CARE,
2056                                       VK_ATTACHMENT_STORE_OP_DONT_CARE,
2057                                       VK_ATTACHMENT_LOAD_OP_DONT_CARE,
2058                                       VK_ATTACHMENT_STORE_OP_DONT_CARE,
2059                                       VK_IMAGE_LAYOUT_UNDEFINED,
2060                                       VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
2061     VkAttachmentReference ref = {0, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL};
2062 
2063     VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 0, nullptr, nullptr, nullptr, 0, nullptr};
2064     VkInputAttachmentAspectReference iaar = {0, 0, VK_IMAGE_ASPECT_METADATA_BIT};
2065     VkRenderPassInputAttachmentAspectCreateInfo rpiaaci = {VK_STRUCTURE_TYPE_RENDER_PASS_INPUT_ATTACHMENT_ASPECT_CREATE_INFO,
2066                                                            nullptr, 1, &iaar};
2067 
2068     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpiaaci, 0, 1, &attach, 1, &subpass, 0, nullptr};
2069 
2070     // Invalid meta data aspect
2071     m_errorMonitor->SetDesiredFailureMsg(
2072         VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkRenderPassCreateInfo-pNext-01963");  // Cannot/should not avoid getting this one too
2073     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkInputAttachmentAspectReference-aspectMask-01964",
2074                          nullptr);
2075 
2076     // Aspect not present
2077     iaar.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
2078     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01963", nullptr);
2079 
2080     // Invalid subpass index
2081     iaar.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
2082     iaar.subpass = 1;
2083     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01926", nullptr);
2084     iaar.subpass = 0;
2085 
2086     // Invalid input attachment index
2087     iaar.inputAttachmentIndex = 1;
2088     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01927", nullptr);
2089 }
2090 
TEST_F(VkLayerTest,RenderPassCreateInvalidFragmentDensityMapReferences)2091 TEST_F(VkLayerTest, RenderPassCreateInvalidFragmentDensityMapReferences) {
2092     TEST_DESCRIPTION("Create a subpass with the wrong attachment information for a fragment density map ");
2093 
2094     // Check for VK_KHR_get_physical_device_properties2
2095     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2096         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2097     } else {
2098         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME);
2099         return;
2100     }
2101 
2102     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2103 
2104     if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME)) {
2105         m_device_extension_names.push_back(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME);
2106     } else {
2107         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME);
2108         return;
2109     }
2110 
2111     ASSERT_NO_FATAL_FAILURE(InitState());
2112 
2113     VkAttachmentDescription attach = {0,
2114                                       VK_FORMAT_R8G8_UNORM,
2115                                       VK_SAMPLE_COUNT_1_BIT,
2116                                       VK_ATTACHMENT_LOAD_OP_LOAD,
2117                                       VK_ATTACHMENT_STORE_OP_DONT_CARE,
2118                                       VK_ATTACHMENT_LOAD_OP_DONT_CARE,
2119                                       VK_ATTACHMENT_STORE_OP_DONT_CARE,
2120                                       VK_IMAGE_LAYOUT_UNDEFINED,
2121                                       VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
2122     // Set 1 instead of 0
2123     VkAttachmentReference ref = {1, VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
2124     VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 0, nullptr, nullptr, nullptr, 0, nullptr};
2125     VkRenderPassFragmentDensityMapCreateInfoEXT rpfdmi = {VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT,
2126                                                           nullptr, ref};
2127 
2128     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpfdmi, 0, 1, &attach, 1, &subpass, 0, nullptr};
2129 
2130     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false,
2131                          "VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-fragmentDensityMapAttachment-02547", nullptr);
2132 
2133     // Set wrong VkImageLayout
2134     ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
2135     subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 0, nullptr, nullptr, nullptr, 0, nullptr};
2136     rpfdmi = {VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT, nullptr, ref};
2137     rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpfdmi, 0, 1, &attach, 1, &subpass, 0, nullptr};
2138 
2139     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false,
2140                          "VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-fragmentDensityMapAttachment-02549", nullptr);
2141 
2142     // Set wrong load operation
2143     attach = {0,
2144               VK_FORMAT_R8G8_UNORM,
2145               VK_SAMPLE_COUNT_1_BIT,
2146               VK_ATTACHMENT_LOAD_OP_CLEAR,
2147               VK_ATTACHMENT_STORE_OP_DONT_CARE,
2148               VK_ATTACHMENT_LOAD_OP_DONT_CARE,
2149               VK_ATTACHMENT_STORE_OP_DONT_CARE,
2150               VK_IMAGE_LAYOUT_UNDEFINED,
2151               VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
2152 
2153     ref = {0, VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
2154     subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 0, nullptr, nullptr, nullptr, 0, nullptr};
2155     rpfdmi = {VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT, nullptr, ref};
2156     rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpfdmi, 0, 1, &attach, 1, &subpass, 0, nullptr};
2157 
2158     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false,
2159                          "VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-fragmentDensityMapAttachment-02550", nullptr);
2160 
2161     // Set wrong store operation
2162     attach = {0,
2163               VK_FORMAT_R8G8_UNORM,
2164               VK_SAMPLE_COUNT_1_BIT,
2165               VK_ATTACHMENT_LOAD_OP_LOAD,
2166               VK_ATTACHMENT_STORE_OP_STORE,
2167               VK_ATTACHMENT_LOAD_OP_DONT_CARE,
2168               VK_ATTACHMENT_STORE_OP_DONT_CARE,
2169               VK_IMAGE_LAYOUT_UNDEFINED,
2170               VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
2171 
2172     ref = {0, VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT};
2173     subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &ref, 0, nullptr, nullptr, nullptr, 0, nullptr};
2174     rpfdmi = {VK_STRUCTURE_TYPE_RENDER_PASS_FRAGMENT_DENSITY_MAP_CREATE_INFO_EXT, nullptr, ref};
2175     rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, &rpfdmi, 0, 1, &attach, 1, &subpass, 0, nullptr};
2176 
2177     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false,
2178                          "VUID-VkRenderPassFragmentDensityMapCreateInfoEXT-fragmentDensityMapAttachment-02551", nullptr);
2179 }
2180 
TEST_F(VkLayerTest,RenderPassCreateSubpassNonGraphicsPipeline)2181 TEST_F(VkLayerTest, RenderPassCreateSubpassNonGraphicsPipeline) {
2182     TEST_DESCRIPTION("Create a subpass with the compute pipeline bind point");
2183     // Check for VK_KHR_get_physical_device_properties2
2184     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2185         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2186     }
2187 
2188     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2189     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
2190     ASSERT_NO_FATAL_FAILURE(InitState());
2191 
2192     VkSubpassDescription subpasses[] = {
2193         {0, VK_PIPELINE_BIND_POINT_COMPUTE, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr},
2194     };
2195 
2196     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 1, subpasses, 0, nullptr};
2197 
2198     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
2199                          "VUID-VkSubpassDescription-pipelineBindPoint-00844",
2200                          "VUID-VkSubpassDescription2KHR-pipelineBindPoint-03062");
2201 }
2202 
TEST_F(VkLayerTest,RenderPassCreateSubpassMissingAttributesBitMultiviewNVX)2203 TEST_F(VkLayerTest, RenderPassCreateSubpassMissingAttributesBitMultiviewNVX) {
2204     TEST_DESCRIPTION("Create a subpass with the VK_SUBPASS_DESCRIPTION_PER_VIEW_ATTRIBUTES_BIT_NVX flag missing");
2205 
2206     // Check for VK_KHR_get_physical_device_properties2
2207     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2208         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2209     } else {
2210         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME);
2211         return;
2212     }
2213 
2214     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2215 
2216     if (DeviceExtensionSupported(gpu(), nullptr, VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME) &&
2217         DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
2218         m_device_extension_names.push_back(VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME);
2219         m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME);
2220     } else {
2221         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_NVX_MULTIVIEW_PER_VIEW_ATTRIBUTES_EXTENSION_NAME);
2222         return;
2223     }
2224 
2225     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
2226     ASSERT_NO_FATAL_FAILURE(InitState());
2227 
2228     VkSubpassDescription subpasses[] = {
2229         {VK_SUBPASS_DESCRIPTION_PER_VIEW_POSITION_X_ONLY_BIT_NVX, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr,
2230          nullptr, 0, nullptr},
2231     };
2232 
2233     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 1, subpasses, 0, nullptr};
2234 
2235     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported, "VUID-VkSubpassDescription-flags-00856",
2236                          "VUID-VkSubpassDescription2KHR-flags-03076");
2237 }
2238 
TEST_F(VkLayerTest,RenderPassCreate2SubpassInvalidInputAttachmentParameters)2239 TEST_F(VkLayerTest, RenderPassCreate2SubpassInvalidInputAttachmentParameters) {
2240     TEST_DESCRIPTION("Create a subpass with parameters in the input attachment ref which are invalid");
2241 
2242     // Check for VK_KHR_get_physical_device_properties2
2243     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2244         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2245     } else {
2246         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
2247         return;
2248     }
2249 
2250     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2251 
2252     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
2253 
2254     if (!rp2Supported) {
2255         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME);
2256         return;
2257     }
2258 
2259     ASSERT_NO_FATAL_FAILURE(InitState());
2260 
2261     VkAttachmentReference2KHR reference = {VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR, nullptr, VK_ATTACHMENT_UNUSED,
2262                                            VK_IMAGE_LAYOUT_UNDEFINED, 0};
2263     VkSubpassDescription2KHR subpass = {VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR,
2264                                         nullptr,
2265                                         0,
2266                                         VK_PIPELINE_BIND_POINT_GRAPHICS,
2267                                         0,
2268                                         1,
2269                                         &reference,
2270                                         0,
2271                                         nullptr,
2272                                         nullptr,
2273                                         nullptr,
2274                                         0,
2275                                         nullptr};
2276 
2277     VkRenderPassCreateInfo2KHR rpci2 = {
2278         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR, nullptr, 0, 0, nullptr, 1, &subpass, 0, nullptr, 0, nullptr};
2279 
2280     // Test for aspect mask of 0
2281     TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), &rpci2, "VUID-VkSubpassDescription2KHR-aspectMask-03176");
2282 
2283     // Test for invalid aspect mask bits
2284     reference.aspectMask |= VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM;
2285     TestRenderPass2KHRCreate(m_errorMonitor, m_device->device(), &rpci2, "VUID-VkSubpassDescription2KHR-aspectMask-03175");
2286 }
2287 
TEST_F(VkLayerTest,RenderPassCreateInvalidSubpassDependencies)2288 TEST_F(VkLayerTest, RenderPassCreateInvalidSubpassDependencies) {
2289     // Check for VK_KHR_get_physical_device_properties2
2290     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2291         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2292     }
2293 
2294     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2295 
2296     bool rp2_supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
2297     bool multiviewSupported = rp2_supported;
2298 
2299     if (!rp2_supported && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
2300         m_device_extension_names.push_back(VK_KHR_MULTIVIEW_EXTENSION_NAME);
2301         multiviewSupported = true;
2302     }
2303 
2304     // Add a device features struct enabling NO features
2305     VkPhysicalDeviceFeatures features = {0};
2306     ASSERT_NO_FATAL_FAILURE(InitState(&features));
2307 
2308     if (m_device->props.apiVersion >= VK_API_VERSION_1_1) {
2309         multiviewSupported = true;
2310     }
2311 
2312     // Create two dummy subpasses
2313     VkSubpassDescription subpasses[] = {
2314         {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr},
2315         {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr},
2316     };
2317 
2318     VkSubpassDependency dependency;
2319     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 2, subpasses, 1, &dependency};
2320 
2321     // Non graphics stages in subpass dependency
2322     dependency = {0, 1, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT,
2323                   VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
2324     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
2325                          "VUID-VkRenderPassCreateInfo-pDependencies-00837", "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03054");
2326 
2327     dependency = {0, 1, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, 0};
2328     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
2329                          "VUID-VkRenderPassCreateInfo-pDependencies-00837", "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03054");
2330 
2331     dependency = {0, 1, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, 0};
2332     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
2333                          "VUID-VkRenderPassCreateInfo-pDependencies-00837", "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03054");
2334 
2335     dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
2336                   VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT};
2337     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
2338                          "VUID-VkRenderPassCreateInfo-pDependencies-00838", "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03055");
2339 
2340     dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 0, 0};
2341     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
2342                          "VUID-VkRenderPassCreateInfo-pDependencies-00838", "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03055");
2343 
2344     dependency = {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, 0};
2345     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
2346                          "VUID-VkRenderPassCreateInfo-pDependencies-00837", "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03054");
2347 
2348     dependency = {VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, 0};
2349     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
2350                          "VUID-VkRenderPassCreateInfo-pDependencies-00838", "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03055");
2351 
2352     dependency = {0, 0, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
2353     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
2354                          "VUID-VkRenderPassCreateInfo-pDependencies-00837", "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03054");
2355 
2356     // Geometry shaders not enabled source
2357     dependency = {0, 1, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
2358 
2359     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcStageMask-00860",
2360                          "VUID-VkSubpassDependency2KHR-srcStageMask-03080");
2361 
2362     // Geometry shaders not enabled destination
2363     dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT, 0, 0, 0};
2364 
2365     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-dstStageMask-00861",
2366                          "VUID-VkSubpassDependency2KHR-dstStageMask-03081");
2367 
2368     // Tessellation not enabled source
2369     dependency = {0, 1, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
2370 
2371     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcStageMask-00862",
2372                          "VUID-VkSubpassDependency2KHR-srcStageMask-03082");
2373 
2374     // Tessellation not enabled destination
2375     dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT, 0, 0, 0};
2376 
2377     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-dstStageMask-00863",
2378                          "VUID-VkSubpassDependency2KHR-dstStageMask-03083");
2379 
2380     // Potential cyclical dependency
2381     dependency = {1, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
2382 
2383     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcSubpass-00864",
2384                          "VUID-VkSubpassDependency2KHR-srcSubpass-03084");
2385 
2386     // EXTERNAL to EXTERNAL dependency
2387     dependency = {
2388         VK_SUBPASS_EXTERNAL, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
2389 
2390     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcSubpass-00865",
2391                          "VUID-VkSubpassDependency2KHR-srcSubpass-03085");
2392 
2393     // Logically later source stages in self dependency
2394     dependency = {0, 0, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, 0, 0};
2395 
2396     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcSubpass-00867",
2397                          "VUID-VkSubpassDependency2KHR-srcSubpass-03087");
2398 
2399     // Source access mask mismatch with source stage mask
2400     dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_ACCESS_UNIFORM_READ_BIT, 0, 0};
2401 
2402     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcAccessMask-00868",
2403                          "VUID-VkSubpassDependency2KHR-srcAccessMask-03088");
2404 
2405     // Destination access mask mismatch with destination stage mask
2406     dependency = {
2407         0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 0};
2408 
2409     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-dstAccessMask-00869",
2410                          "VUID-VkSubpassDependency2KHR-dstAccessMask-03089");
2411 
2412     if (multiviewSupported) {
2413         // VIEW_LOCAL_BIT but multiview is not enabled
2414         dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
2415                       0, 0, VK_DEPENDENCY_VIEW_LOCAL_BIT};
2416 
2417         TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, nullptr,
2418                              "VUID-VkRenderPassCreateInfo2KHR-viewMask-03059");
2419 
2420         // Enable multiview
2421         uint32_t pViewMasks[2] = {0x3u, 0x3u};
2422         int32_t pViewOffsets[2] = {0, 0};
2423         VkRenderPassMultiviewCreateInfo rpmvci = {
2424             VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, nullptr, 2, pViewMasks, 0, nullptr, 0, nullptr};
2425         rpci.pNext = &rpmvci;
2426 
2427         // Excessive view offsets
2428         dependency = {0, 1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
2429                       0, 0, VK_DEPENDENCY_VIEW_LOCAL_BIT};
2430         rpmvci.pViewOffsets = pViewOffsets;
2431         rpmvci.dependencyCount = 2;
2432 
2433         TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01929", nullptr);
2434 
2435         rpmvci.dependencyCount = 0;
2436 
2437         // View offset with subpass self dependency
2438         dependency = {0, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
2439                       0, 0, VK_DEPENDENCY_VIEW_LOCAL_BIT};
2440         rpmvci.pViewOffsets = pViewOffsets;
2441         pViewOffsets[0] = 1;
2442         rpmvci.dependencyCount = 1;
2443 
2444         TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, false, "VUID-VkRenderPassCreateInfo-pNext-01930", nullptr);
2445 
2446         rpmvci.dependencyCount = 0;
2447 
2448         // View offset with no view local bit
2449         if (rp2_supported) {
2450             dependency = {0, VK_SUBPASS_EXTERNAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
2451             rpmvci.pViewOffsets = pViewOffsets;
2452             pViewOffsets[0] = 1;
2453             rpmvci.dependencyCount = 1;
2454 
2455             TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, nullptr,
2456                                  "VUID-VkSubpassDependency2KHR-dependencyFlags-03092");
2457 
2458             rpmvci.dependencyCount = 0;
2459         }
2460 
2461         // EXTERNAL subpass with VIEW_LOCAL_BIT - source subpass
2462         dependency = {VK_SUBPASS_EXTERNAL,         1, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0,
2463                       VK_DEPENDENCY_VIEW_LOCAL_BIT};
2464 
2465         TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
2466                              "VUID-VkSubpassDependency-dependencyFlags-02520",
2467                              "VUID-VkSubpassDependency2KHR-dependencyFlags-03090");
2468 
2469         // EXTERNAL subpass with VIEW_LOCAL_BIT - destination subpass
2470         dependency = {0, VK_SUBPASS_EXTERNAL,         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0,
2471                       0, VK_DEPENDENCY_VIEW_LOCAL_BIT};
2472 
2473         TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported,
2474                              "VUID-VkSubpassDependency-dependencyFlags-02521",
2475                              "VUID-VkSubpassDependency2KHR-dependencyFlags-03091");
2476 
2477         // Multiple views but no view local bit in self-dependency
2478         dependency = {0, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0};
2479 
2480         TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2_supported, "VUID-VkSubpassDependency-srcSubpass-00872",
2481                              "VUID-VkRenderPassCreateInfo2KHR-pDependencies-03060");
2482     }
2483 }
2484 
TEST_F(VkLayerTest,RenderPassCreateInvalidMixedAttachmentSamplesAMD)2485 TEST_F(VkLayerTest, RenderPassCreateInvalidMixedAttachmentSamplesAMD) {
2486     TEST_DESCRIPTION("Verify error messages for supported and unsupported sample counts in render pass attachments.");
2487 
2488     // Check for VK_KHR_get_physical_device_properties2
2489     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2490         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2491     }
2492 
2493     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2494 
2495     if (DeviceExtensionSupported(gpu(), nullptr, VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME)) {
2496         m_device_extension_names.push_back(VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME);
2497     } else {
2498         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_AMD_MIXED_ATTACHMENT_SAMPLES_EXTENSION_NAME);
2499         return;
2500     }
2501 
2502     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
2503 
2504     ASSERT_NO_FATAL_FAILURE(InitState());
2505 
2506     std::vector<VkAttachmentDescription> attachments;
2507 
2508     {
2509         VkAttachmentDescription att = {};
2510         att.format = VK_FORMAT_R8G8B8A8_UNORM;
2511         att.samples = VK_SAMPLE_COUNT_1_BIT;
2512         att.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
2513         att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
2514         att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
2515         att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
2516         att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
2517         att.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2518 
2519         attachments.push_back(att);
2520 
2521         att.format = VK_FORMAT_D16_UNORM;
2522         att.samples = VK_SAMPLE_COUNT_4_BIT;
2523         att.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
2524         att.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
2525         att.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
2526         att.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
2527         att.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
2528         att.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
2529 
2530         attachments.push_back(att);
2531     }
2532 
2533     VkAttachmentReference color_ref = {};
2534     color_ref.attachment = 0;
2535     color_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2536 
2537     VkAttachmentReference depth_ref = {};
2538     depth_ref.attachment = 1;
2539     depth_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
2540 
2541     VkSubpassDescription subpass = {};
2542     subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
2543     subpass.colorAttachmentCount = 1;
2544     subpass.pColorAttachments = &color_ref;
2545     subpass.pDepthStencilAttachment = &depth_ref;
2546 
2547     VkRenderPassCreateInfo rpci = {};
2548     rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
2549     rpci.attachmentCount = attachments.size();
2550     rpci.pAttachments = attachments.data();
2551     rpci.subpassCount = 1;
2552     rpci.pSubpasses = &subpass;
2553 
2554     m_errorMonitor->ExpectSuccess();
2555 
2556     VkRenderPass rp;
2557     VkResult err;
2558 
2559     err = vkCreateRenderPass(device(), &rpci, NULL, &rp);
2560     m_errorMonitor->VerifyNotFound();
2561     if (err == VK_SUCCESS) vkDestroyRenderPass(m_device->device(), rp, nullptr);
2562 
2563     // Expect an error message for invalid sample counts
2564     attachments[0].samples = VK_SAMPLE_COUNT_4_BIT;
2565     attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
2566 
2567     TestRenderPassCreate(m_errorMonitor, m_device->device(), &rpci, rp2Supported,
2568                          "VUID-VkSubpassDescription-pColorAttachments-01506",
2569                          "VUID-VkSubpassDescription2KHR-pColorAttachments-03070");
2570 }
2571 
TEST_F(VkLayerTest,RenderPassBeginInvalidRenderArea)2572 TEST_F(VkLayerTest, RenderPassBeginInvalidRenderArea) {
2573     TEST_DESCRIPTION("Generate INVALID_RENDER_AREA error by beginning renderpass with extent outside of framebuffer");
2574     // Check for VK_KHR_get_physical_device_properties2
2575     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2576         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2577     }
2578 
2579     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2580     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
2581     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
2582 
2583     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2584 
2585     // Framebuffer for render target is 256x256, exceed that for INVALID_RENDER_AREA
2586     m_renderPassBeginInfo.renderArea.extent.width = 257;
2587     m_renderPassBeginInfo.renderArea.extent.height = 257;
2588 
2589     TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &m_renderPassBeginInfo, rp2Supported,
2590                         "Cannot execute a render pass with renderArea not within the bound of the framebuffer.",
2591                         "Cannot execute a render pass with renderArea not within the bound of the framebuffer.");
2592 }
2593 
TEST_F(VkLayerTest,RenderPassBeginWithinRenderPass)2594 TEST_F(VkLayerTest, RenderPassBeginWithinRenderPass) {
2595     // Check for VK_KHR_get_physical_device_properties2
2596     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2597         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2598     }
2599 
2600     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2601     PFN_vkCmdBeginRenderPass2KHR vkCmdBeginRenderPass2KHR = nullptr;
2602     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
2603     ASSERT_NO_FATAL_FAILURE(InitState());
2604 
2605     if (rp2Supported) {
2606         vkCmdBeginRenderPass2KHR =
2607             (PFN_vkCmdBeginRenderPass2KHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdBeginRenderPass2KHR");
2608     }
2609 
2610     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2611 
2612     // Bind a BeginRenderPass within an active RenderPass
2613     m_commandBuffer->begin();
2614     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
2615 
2616     // Just use a dummy Renderpass
2617     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBeginRenderPass-renderpass");
2618     vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2619 
2620     m_errorMonitor->VerifyFound();
2621 
2622     if (rp2Supported) {
2623         VkSubpassBeginInfoKHR subpassBeginInfo = {VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR, nullptr, VK_SUBPASS_CONTENTS_INLINE};
2624 
2625         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBeginRenderPass2KHR-renderpass");
2626         vkCmdBeginRenderPass2KHR(m_commandBuffer->handle(), &m_renderPassBeginInfo, &subpassBeginInfo);
2627         m_errorMonitor->VerifyFound();
2628     }
2629 }
2630 
TEST_F(VkLayerTest,RenderPassBeginIncompatibleFramebufferRenderPass)2631 TEST_F(VkLayerTest, RenderPassBeginIncompatibleFramebufferRenderPass) {
2632     TEST_DESCRIPTION("Test that renderpass begin is compatible with the framebuffer renderpass ");
2633 
2634     ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
2635 
2636     // Create a depth stencil image view
2637     VkImageObj image(m_device);
2638 
2639     image.Init(128, 128, 1, VK_FORMAT_D16_UNORM, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL);
2640     ASSERT_TRUE(image.initialized());
2641 
2642     VkImageView dsv;
2643     VkImageViewCreateInfo dsvci = {};
2644     dsvci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
2645     dsvci.pNext = nullptr;
2646     dsvci.image = image.handle();
2647     dsvci.viewType = VK_IMAGE_VIEW_TYPE_2D;
2648     dsvci.format = VK_FORMAT_D16_UNORM;
2649     dsvci.subresourceRange.layerCount = 1;
2650     dsvci.subresourceRange.baseMipLevel = 0;
2651     dsvci.subresourceRange.levelCount = 1;
2652     dsvci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
2653     vkCreateImageView(m_device->device(), &dsvci, NULL, &dsv);
2654 
2655     // Create a renderPass with a single attachment that uses loadOp CLEAR
2656     VkAttachmentDescription description = {0,
2657                                            VK_FORMAT_D16_UNORM,
2658                                            VK_SAMPLE_COUNT_1_BIT,
2659                                            VK_ATTACHMENT_LOAD_OP_LOAD,
2660                                            VK_ATTACHMENT_STORE_OP_DONT_CARE,
2661                                            VK_ATTACHMENT_LOAD_OP_CLEAR,
2662                                            VK_ATTACHMENT_STORE_OP_DONT_CARE,
2663                                            VK_IMAGE_LAYOUT_GENERAL,
2664                                            VK_IMAGE_LAYOUT_GENERAL};
2665 
2666     VkAttachmentReference depth_stencil_ref = {0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
2667 
2668     VkSubpassDescription subpass = {0,      VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, &depth_stencil_ref, 0,
2669                                     nullptr};
2670 
2671     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &description, 1, &subpass, 0, nullptr};
2672     VkRenderPass rp1, rp2;
2673 
2674     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp1);
2675     subpass.pDepthStencilAttachment = nullptr;
2676     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp2);
2677 
2678     // Create a framebuffer
2679 
2680     VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp1, 1, &dsv, 128, 128, 1};
2681     VkFramebuffer fb;
2682 
2683     vkCreateFramebuffer(m_device->handle(), &fbci, nullptr, &fb);
2684 
2685     VkRenderPassBeginInfo rp_begin = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp2, fb, {{0, 0}, {128, 128}}, 0, nullptr};
2686 
2687     TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, false,
2688                         "VUID-VkRenderPassBeginInfo-renderPass-00904", nullptr);
2689 
2690     vkDestroyRenderPass(m_device->device(), rp1, nullptr);
2691     vkDestroyRenderPass(m_device->device(), rp2, nullptr);
2692     vkDestroyFramebuffer(m_device->device(), fb, nullptr);
2693     vkDestroyImageView(m_device->device(), dsv, nullptr);
2694 }
2695 
TEST_F(VkLayerTest,RenderPassBeginLayoutsFramebufferImageUsageMismatches)2696 TEST_F(VkLayerTest, RenderPassBeginLayoutsFramebufferImageUsageMismatches) {
2697     TEST_DESCRIPTION(
2698         "Test that renderpass initial/final layouts match up with the usage bits set for each attachment of the framebuffer");
2699 
2700     // Check for VK_KHR_get_physical_device_properties2
2701     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2702         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2703     }
2704 
2705     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2706     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
2707     bool maintenance2Supported = rp2Supported;
2708 
2709     // Check for VK_KHR_maintenance2
2710     if (!rp2Supported && DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE2_EXTENSION_NAME)) {
2711         m_device_extension_names.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME);
2712         maintenance2Supported = true;
2713     }
2714 
2715     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
2716 
2717     if (m_device->props.apiVersion >= VK_API_VERSION_1_1) {
2718         maintenance2Supported = true;
2719     }
2720 
2721     // Create an input attachment view
2722     VkImageObj iai(m_device);
2723 
2724     iai.InitNoLayout(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL);
2725     ASSERT_TRUE(iai.initialized());
2726 
2727     VkImageView iav;
2728     VkImageViewCreateInfo iavci = {};
2729     iavci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
2730     iavci.pNext = nullptr;
2731     iavci.image = iai.handle();
2732     iavci.viewType = VK_IMAGE_VIEW_TYPE_2D;
2733     iavci.format = VK_FORMAT_R8G8B8A8_UNORM;
2734     iavci.subresourceRange.layerCount = 1;
2735     iavci.subresourceRange.baseMipLevel = 0;
2736     iavci.subresourceRange.levelCount = 1;
2737     iavci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
2738     vkCreateImageView(m_device->device(), &iavci, NULL, &iav);
2739 
2740     // Create a color attachment view
2741     VkImageObj cai(m_device);
2742 
2743     cai.InitNoLayout(128, 128, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL);
2744     ASSERT_TRUE(cai.initialized());
2745 
2746     VkImageView cav;
2747     VkImageViewCreateInfo cavci = {};
2748     cavci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
2749     cavci.pNext = nullptr;
2750     cavci.image = cai.handle();
2751     cavci.viewType = VK_IMAGE_VIEW_TYPE_2D;
2752     cavci.format = VK_FORMAT_R8G8B8A8_UNORM;
2753     cavci.subresourceRange.layerCount = 1;
2754     cavci.subresourceRange.baseMipLevel = 0;
2755     cavci.subresourceRange.levelCount = 1;
2756     cavci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
2757     vkCreateImageView(m_device->device(), &cavci, NULL, &cav);
2758 
2759     // Create a renderPass with those attachments
2760     VkAttachmentDescription descriptions[] = {
2761         {0, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
2762          VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL},
2763         {1, VK_FORMAT_R8G8B8A8_UNORM, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
2764          VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_DONT_CARE, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL}};
2765 
2766     VkAttachmentReference input_ref = {0, VK_IMAGE_LAYOUT_GENERAL};
2767     VkAttachmentReference color_ref = {1, VK_IMAGE_LAYOUT_GENERAL};
2768 
2769     VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 1, &input_ref, 1, &color_ref, nullptr, nullptr, 0, nullptr};
2770 
2771     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 2, descriptions, 1, &subpass, 0, nullptr};
2772 
2773     VkRenderPass rp;
2774 
2775     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp);
2776 
2777     // Create a framebuffer
2778 
2779     VkImageView views[] = {iav, cav};
2780 
2781     VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 2, views, 128, 128, 1};
2782     VkFramebuffer fb;
2783 
2784     vkCreateFramebuffer(m_device->handle(), &fbci, nullptr, &fb);
2785 
2786     VkRenderPassBeginInfo rp_begin = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp, fb, {{0, 0}, {128, 128}}, 0, nullptr};
2787 
2788     VkRenderPass rp_invalid;
2789 
2790     // Initial layout is VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but attachment doesn't support IMAGE_USAGE_COLOR_ATTACHMENT_BIT
2791     descriptions[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
2792     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid);
2793     rp_begin.renderPass = rp_invalid;
2794     TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported,
2795                         "VUID-vkCmdBeginRenderPass-initialLayout-00895", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03094");
2796 
2797     vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr);
2798 
2799     // Initial layout is VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL but attachment doesn't support VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
2800     // / VK_IMAGE_USAGE_SAMPLED_BIT
2801     descriptions[0].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
2802     descriptions[1].initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
2803     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid);
2804     rp_begin.renderPass = rp_invalid;
2805 
2806     TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported,
2807                         "VUID-vkCmdBeginRenderPass-initialLayout-00897", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03097");
2808 
2809     vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr);
2810     descriptions[1].initialLayout = VK_IMAGE_LAYOUT_GENERAL;
2811 
2812     // Initial layout is VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL but attachment doesn't support VK_IMAGE_USAGE_TRANSFER_SRC_BIT
2813     descriptions[0].initialLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
2814     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid);
2815     rp_begin.renderPass = rp_invalid;
2816 
2817     TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported,
2818                         "VUID-vkCmdBeginRenderPass-initialLayout-00898", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03098");
2819 
2820     vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr);
2821 
2822     // Initial layout is VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL but attachment doesn't support VK_IMAGE_USAGE_TRANSFER_DST_BIT
2823     descriptions[0].initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
2824     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid);
2825     rp_begin.renderPass = rp_invalid;
2826 
2827     TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported,
2828                         "VUID-vkCmdBeginRenderPass-initialLayout-00899", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03099");
2829 
2830     vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr);
2831 
2832     // Initial layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL but attachment doesn't support
2833     // VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
2834     descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
2835     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid);
2836     rp_begin.renderPass = rp_invalid;
2837     const char *initial_layout_vuid_rp1 =
2838         maintenance2Supported ? "VUID-vkCmdBeginRenderPass-initialLayout-01758" : "VUID-vkCmdBeginRenderPass-initialLayout-00896";
2839 
2840     TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported,
2841                         initial_layout_vuid_rp1, "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03096");
2842 
2843     vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr);
2844 
2845     // Initial layout is VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL but attachment doesn't support
2846     // VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
2847     descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
2848     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid);
2849     rp_begin.renderPass = rp_invalid;
2850 
2851     TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported,
2852                         initial_layout_vuid_rp1, "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03096");
2853 
2854     vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr);
2855 
2856     if (maintenance2Supported || rp2Supported) {
2857         // Initial layout is VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL but attachment doesn't support
2858         // VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
2859         descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
2860         vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid);
2861         rp_begin.renderPass = rp_invalid;
2862 
2863         TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported,
2864                             "VUID-vkCmdBeginRenderPass-initialLayout-01758", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03096");
2865 
2866         vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr);
2867 
2868         // Initial layout is VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL but attachment doesn't support
2869         // VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
2870         descriptions[0].initialLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
2871         vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_invalid);
2872         rp_begin.renderPass = rp_invalid;
2873 
2874         TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported,
2875                             "VUID-vkCmdBeginRenderPass-initialLayout-01758", "VUID-vkCmdBeginRenderPass2KHR-initialLayout-03096");
2876 
2877         vkDestroyRenderPass(m_device->handle(), rp_invalid, nullptr);
2878     }
2879 
2880     vkDestroyRenderPass(m_device->device(), rp, nullptr);
2881     vkDestroyFramebuffer(m_device->device(), fb, nullptr);
2882     vkDestroyImageView(m_device->device(), iav, nullptr);
2883     vkDestroyImageView(m_device->device(), cav, nullptr);
2884 }
2885 
TEST_F(VkLayerTest,RenderPassBeginClearOpMismatch)2886 TEST_F(VkLayerTest, RenderPassBeginClearOpMismatch) {
2887     TEST_DESCRIPTION(
2888         "Begin a renderPass where clearValueCount is less than the number of renderPass attachments that use "
2889         "loadOp VK_ATTACHMENT_LOAD_OP_CLEAR.");
2890 
2891     // Check for VK_KHR_get_physical_device_properties2
2892     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2893         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2894     }
2895 
2896     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2897     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
2898     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
2899 
2900     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
2901 
2902     // Create a renderPass with a single attachment that uses loadOp CLEAR
2903     VkAttachmentReference attach = {};
2904     attach.layout = VK_IMAGE_LAYOUT_GENERAL;
2905     VkSubpassDescription subpass = {};
2906     subpass.colorAttachmentCount = 1;
2907     subpass.pColorAttachments = &attach;
2908     VkRenderPassCreateInfo rpci = {};
2909     rpci.subpassCount = 1;
2910     rpci.pSubpasses = &subpass;
2911     rpci.attachmentCount = 1;
2912     VkAttachmentDescription attach_desc = {};
2913     attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
2914     // Set loadOp to CLEAR
2915     attach_desc.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
2916     attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
2917     attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
2918     rpci.pAttachments = &attach_desc;
2919     rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
2920     VkRenderPass rp;
2921     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp);
2922 
2923     VkRenderPassBeginInfo rp_begin = {};
2924     rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2925     rp_begin.pNext = NULL;
2926     rp_begin.renderPass = renderPass();
2927     rp_begin.framebuffer = framebuffer();
2928     rp_begin.clearValueCount = 0;  // Should be 1
2929 
2930     TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, rp2Supported,
2931                         "VUID-VkRenderPassBeginInfo-clearValueCount-00902", "VUID-VkRenderPassBeginInfo-clearValueCount-00902");
2932 
2933     vkDestroyRenderPass(m_device->device(), rp, NULL);
2934 }
2935 
TEST_F(VkLayerTest,RenderPassBeginSampleLocationsInvalidIndicesEXT)2936 TEST_F(VkLayerTest, RenderPassBeginSampleLocationsInvalidIndicesEXT) {
2937     TEST_DESCRIPTION("Test that attachment indices and subpass indices specifed by sample locations structures are valid");
2938 
2939     // Check for VK_KHR_get_physical_device_properties2
2940     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
2941         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
2942     }
2943     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
2944     if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME)) {
2945         m_device_extension_names.push_back(VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
2946     } else {
2947         printf("%s Extension %s is not supported.\n", kSkipPrefix, VK_EXT_SAMPLE_LOCATIONS_EXTENSION_NAME);
2948         return;
2949     }
2950 
2951     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
2952 
2953     // Create a depth stencil image view
2954     VkImageObj image(m_device);
2955 
2956     image.Init(128, 128, 1, VK_FORMAT_D16_UNORM, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL);
2957     ASSERT_TRUE(image.initialized());
2958 
2959     VkImageView dsv;
2960     VkImageViewCreateInfo dsvci = {};
2961     dsvci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
2962     dsvci.pNext = nullptr;
2963     dsvci.image = image.handle();
2964     dsvci.viewType = VK_IMAGE_VIEW_TYPE_2D;
2965     dsvci.format = VK_FORMAT_D16_UNORM;
2966     dsvci.subresourceRange.layerCount = 1;
2967     dsvci.subresourceRange.baseMipLevel = 0;
2968     dsvci.subresourceRange.levelCount = 1;
2969     dsvci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
2970     vkCreateImageView(m_device->device(), &dsvci, NULL, &dsv);
2971 
2972     // Create a renderPass with a single attachment that uses loadOp CLEAR
2973     VkAttachmentDescription description = {0,
2974                                            VK_FORMAT_D16_UNORM,
2975                                            VK_SAMPLE_COUNT_1_BIT,
2976                                            VK_ATTACHMENT_LOAD_OP_LOAD,
2977                                            VK_ATTACHMENT_STORE_OP_DONT_CARE,
2978                                            VK_ATTACHMENT_LOAD_OP_CLEAR,
2979                                            VK_ATTACHMENT_STORE_OP_DONT_CARE,
2980                                            VK_IMAGE_LAYOUT_GENERAL,
2981                                            VK_IMAGE_LAYOUT_GENERAL};
2982 
2983     VkAttachmentReference depth_stencil_ref = {0, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
2984 
2985     VkSubpassDescription subpass = {0,      VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, &depth_stencil_ref, 0,
2986                                     nullptr};
2987 
2988     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &description, 1, &subpass, 0, nullptr};
2989     VkRenderPass rp;
2990 
2991     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp);
2992 
2993     // Create a framebuffer
2994 
2995     VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &dsv, 128, 128, 1};
2996     VkFramebuffer fb;
2997 
2998     vkCreateFramebuffer(m_device->handle(), &fbci, nullptr, &fb);
2999 
3000     VkSampleLocationEXT sample_location = {0.5, 0.5};
3001 
3002     VkSampleLocationsInfoEXT sample_locations_info = {
3003         VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT, nullptr, VK_SAMPLE_COUNT_1_BIT, {1, 1}, 1, &sample_location};
3004 
3005     VkAttachmentSampleLocationsEXT attachment_sample_locations = {0, sample_locations_info};
3006     VkSubpassSampleLocationsEXT subpass_sample_locations = {0, sample_locations_info};
3007 
3008     VkRenderPassSampleLocationsBeginInfoEXT rp_sl_begin = {VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT,
3009                                                            nullptr,
3010                                                            1,
3011                                                            &attachment_sample_locations,
3012                                                            1,
3013                                                            &subpass_sample_locations};
3014 
3015     VkRenderPassBeginInfo rp_begin = {
3016         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, &rp_sl_begin, rp, fb, {{0, 0}, {128, 128}}, 0, nullptr};
3017 
3018     attachment_sample_locations.attachmentIndex = 1;
3019     TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, false,
3020                         "VUID-VkAttachmentSampleLocationsEXT-attachmentIndex-01531", nullptr);
3021     attachment_sample_locations.attachmentIndex = 0;
3022 
3023     subpass_sample_locations.subpassIndex = 1;
3024     TestRenderPassBegin(m_errorMonitor, m_device->device(), m_commandBuffer->handle(), &rp_begin, false,
3025                         "VUID-VkSubpassSampleLocationsEXT-subpassIndex-01532", nullptr);
3026     subpass_sample_locations.subpassIndex = 0;
3027 
3028     vkDestroyRenderPass(m_device->device(), rp, nullptr);
3029     vkDestroyFramebuffer(m_device->device(), fb, nullptr);
3030     vkDestroyImageView(m_device->device(), dsv, nullptr);
3031 }
3032 
TEST_F(VkLayerTest,RenderPassNextSubpassExcessive)3033 TEST_F(VkLayerTest, RenderPassNextSubpassExcessive) {
3034     TEST_DESCRIPTION("Test that an error is produced when CmdNextSubpass is called too many times in a renderpass instance");
3035 
3036     // Check for VK_KHR_get_physical_device_properties2
3037     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
3038         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
3039     }
3040 
3041     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
3042     PFN_vkCmdNextSubpass2KHR vkCmdNextSubpass2KHR = nullptr;
3043     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
3044     ASSERT_NO_FATAL_FAILURE(InitState());
3045 
3046     if (rp2Supported) {
3047         vkCmdNextSubpass2KHR = (PFN_vkCmdNextSubpass2KHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdNextSubpass2KHR");
3048     }
3049 
3050     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3051 
3052     m_commandBuffer->begin();
3053     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
3054 
3055     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdNextSubpass-None-00909");
3056     vkCmdNextSubpass(m_commandBuffer->handle(), VK_SUBPASS_CONTENTS_INLINE);
3057     m_errorMonitor->VerifyFound();
3058 
3059     if (rp2Supported) {
3060         VkSubpassBeginInfoKHR subpassBeginInfo = {VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO_KHR, nullptr, VK_SUBPASS_CONTENTS_INLINE};
3061         VkSubpassEndInfoKHR subpassEndInfo = {VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR, nullptr};
3062 
3063         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdNextSubpass2KHR-None-03102");
3064 
3065         vkCmdNextSubpass2KHR(m_commandBuffer->handle(), &subpassBeginInfo, &subpassEndInfo);
3066         m_errorMonitor->VerifyFound();
3067     }
3068 
3069     m_commandBuffer->EndRenderPass();
3070     m_commandBuffer->end();
3071 }
3072 
TEST_F(VkLayerTest,RenderPassEndBeforeFinalSubpass)3073 TEST_F(VkLayerTest, RenderPassEndBeforeFinalSubpass) {
3074     TEST_DESCRIPTION("Test that an error is produced when CmdEndRenderPass is called before the final subpass has been reached");
3075 
3076     // Check for VK_KHR_get_physical_device_properties2
3077     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
3078         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
3079     }
3080 
3081     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
3082     PFN_vkCmdEndRenderPass2KHR vkCmdEndRenderPass2KHR = nullptr;
3083     bool rp2Supported = CheckCreateRenderPass2Support(this, m_device_extension_names);
3084     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
3085 
3086     if (rp2Supported) {
3087         vkCmdEndRenderPass2KHR = (PFN_vkCmdEndRenderPass2KHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdEndRenderPass2KHR");
3088     }
3089 
3090     VkSubpassDescription sd[2] = {{0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr},
3091                                   {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr}};
3092 
3093     VkRenderPassCreateInfo rcpi = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 0, nullptr, 2, sd, 0, nullptr};
3094 
3095     VkRenderPass rp;
3096     VkResult err = vkCreateRenderPass(m_device->device(), &rcpi, nullptr, &rp);
3097     ASSERT_VK_SUCCESS(err);
3098 
3099     VkFramebufferCreateInfo fbci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 0, nullptr, 16, 16, 1};
3100 
3101     VkFramebuffer fb;
3102     err = vkCreateFramebuffer(m_device->device(), &fbci, nullptr, &fb);
3103     ASSERT_VK_SUCCESS(err);
3104 
3105     m_commandBuffer->begin();
3106 
3107     VkRenderPassBeginInfo rpbi = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, nullptr, rp, fb, {{0, 0}, {16, 16}}, 0, nullptr};
3108 
3109     vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE);
3110 
3111     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdEndRenderPass-None-00910");
3112     vkCmdEndRenderPass(m_commandBuffer->handle());
3113     m_errorMonitor->VerifyFound();
3114 
3115     if (rp2Supported) {
3116         VkSubpassEndInfoKHR subpassEndInfo = {VK_STRUCTURE_TYPE_SUBPASS_END_INFO_KHR, nullptr};
3117 
3118         m_commandBuffer->reset();
3119         m_commandBuffer->begin();
3120         vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE);
3121 
3122         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdEndRenderPass2KHR-None-03103");
3123         vkCmdEndRenderPass2KHR(m_commandBuffer->handle(), &subpassEndInfo);
3124         m_errorMonitor->VerifyFound();
3125     }
3126 
3127     // Clean up.
3128     vkDestroyFramebuffer(m_device->device(), fb, nullptr);
3129     vkDestroyRenderPass(m_device->device(), rp, nullptr);
3130 }
3131 
TEST_F(VkLayerTest,RenderPassDestroyWhileInUse)3132 TEST_F(VkLayerTest, RenderPassDestroyWhileInUse) {
3133     TEST_DESCRIPTION("Delete in-use renderPass.");
3134 
3135     ASSERT_NO_FATAL_FAILURE(Init());
3136     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3137 
3138     // Create simple renderpass
3139     VkAttachmentReference attach = {};
3140     attach.layout = VK_IMAGE_LAYOUT_GENERAL;
3141     VkSubpassDescription subpass = {};
3142     subpass.colorAttachmentCount = 1;
3143     subpass.pColorAttachments = &attach;
3144     VkRenderPassCreateInfo rpci = {};
3145     rpci.subpassCount = 1;
3146     rpci.pSubpasses = &subpass;
3147     rpci.attachmentCount = 1;
3148     VkAttachmentDescription attach_desc = {};
3149     attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
3150     attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
3151     attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
3152     rpci.pAttachments = &attach_desc;
3153     rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
3154     VkRenderPass rp;
3155     VkResult err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp);
3156     ASSERT_VK_SUCCESS(err);
3157 
3158     m_errorMonitor->ExpectSuccess();
3159 
3160     m_commandBuffer->begin();
3161     VkRenderPassBeginInfo rpbi = {};
3162     rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
3163     rpbi.framebuffer = m_framebuffer;
3164     rpbi.renderPass = rp;
3165     m_commandBuffer->BeginRenderPass(rpbi);
3166     m_commandBuffer->EndRenderPass();
3167     m_commandBuffer->end();
3168 
3169     VkSubmitInfo submit_info = {};
3170     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
3171     submit_info.commandBufferCount = 1;
3172     submit_info.pCommandBuffers = &m_commandBuffer->handle();
3173     vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
3174     m_errorMonitor->VerifyNotFound();
3175 
3176     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkDestroyRenderPass-renderPass-00873");
3177     vkDestroyRenderPass(m_device->device(), rp, nullptr);
3178     m_errorMonitor->VerifyFound();
3179 
3180     // Wait for queue to complete so we can safely destroy rp
3181     vkQueueWaitIdle(m_device->m_queue);
3182     m_errorMonitor->SetUnexpectedError("If renderPass is not VK_NULL_HANDLE, renderPass must be a valid VkRenderPass handle");
3183     m_errorMonitor->SetUnexpectedError("Was it created? Has it already been destroyed?");
3184     vkDestroyRenderPass(m_device->device(), rp, nullptr);
3185 }
3186 
TEST_F(VkLayerTest,FramebufferCreateErrors)3187 TEST_F(VkLayerTest, FramebufferCreateErrors) {
3188     TEST_DESCRIPTION(
3189         "Hit errors when attempting to create a framebuffer :\n"
3190         " 1. Mismatch between framebuffer & renderPass attachmentCount\n"
3191         " 2. Use a color image as depthStencil attachment\n"
3192         " 3. Mismatch framebuffer & renderPass attachment formats\n"
3193         " 4. Mismatch framebuffer & renderPass attachment #samples\n"
3194         " 5. Framebuffer attachment w/ non-1 mip-levels\n"
3195         " 6. Framebuffer attachment where dimensions don't match\n"
3196         " 7. Framebuffer attachment where dimensions don't match\n"
3197         " 8. Framebuffer attachment w/o identity swizzle\n"
3198         " 9. framebuffer dimensions exceed physical device limits\n"
3199         "10. null pAttachments\n");
3200 
3201     // Check for VK_KHR_get_physical_device_properties2
3202     bool push_physical_device_properties_2_support =
3203         InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
3204     if (push_physical_device_properties_2_support) {
3205         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
3206     }
3207 
3208     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
3209 
3210     bool push_fragment_density_support = false;
3211 
3212     if (push_physical_device_properties_2_support) {
3213         push_fragment_density_support = DeviceExtensionSupported(gpu(), nullptr, VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME);
3214         if (push_fragment_density_support) m_device_extension_names.push_back(VK_EXT_FRAGMENT_DENSITY_MAP_EXTENSION_NAME);
3215     }
3216 
3217     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, 0));
3218     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3219 
3220     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-attachmentCount-00876");
3221 
3222     // Create a renderPass with a single color attachment
3223     VkAttachmentReference attach = {};
3224     attach.layout = VK_IMAGE_LAYOUT_GENERAL;
3225     VkSubpassDescription subpass = {};
3226     subpass.pColorAttachments = &attach;
3227     VkRenderPassCreateInfo rpci = {};
3228     rpci.subpassCount = 1;
3229     rpci.pSubpasses = &subpass;
3230     rpci.attachmentCount = 1;
3231     VkAttachmentDescription attach_desc = {};
3232     attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
3233     attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
3234     attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
3235     rpci.pAttachments = &attach_desc;
3236     rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
3237     VkRenderPass rp;
3238     VkResult err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp);
3239     ASSERT_VK_SUCCESS(err);
3240 
3241     VkImageView ivs[2];
3242     ivs[0] = m_renderTargets[0]->targetView(VK_FORMAT_B8G8R8A8_UNORM);
3243     ivs[1] = m_renderTargets[0]->targetView(VK_FORMAT_B8G8R8A8_UNORM);
3244     VkFramebufferCreateInfo fb_info = {};
3245     fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
3246     fb_info.pNext = NULL;
3247     fb_info.renderPass = rp;
3248     // Set mis-matching attachmentCount
3249     fb_info.attachmentCount = 2;
3250     fb_info.pAttachments = ivs;
3251     fb_info.width = 100;
3252     fb_info.height = 100;
3253     fb_info.layers = 1;
3254 
3255     VkFramebuffer fb;
3256     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3257 
3258     m_errorMonitor->VerifyFound();
3259     if (err == VK_SUCCESS) {
3260         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3261     }
3262     vkDestroyRenderPass(m_device->device(), rp, NULL);
3263 
3264     // Create a renderPass with a depth-stencil attachment created with
3265     // IMAGE_USAGE_COLOR_ATTACHMENT
3266     // Add our color attachment to pDepthStencilAttachment
3267     subpass.pDepthStencilAttachment = &attach;
3268     subpass.pColorAttachments = NULL;
3269     VkRenderPass rp_ds;
3270     err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp_ds);
3271     ASSERT_VK_SUCCESS(err);
3272     // Set correct attachment count, but attachment has COLOR usage bit set
3273     fb_info.attachmentCount = 1;
3274     fb_info.renderPass = rp_ds;
3275 
3276     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-02633");
3277     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3278 
3279     m_errorMonitor->VerifyFound();
3280     if (err == VK_SUCCESS) {
3281         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3282     }
3283     vkDestroyRenderPass(m_device->device(), rp_ds, NULL);
3284 
3285     // Create new renderpass with alternate attachment format from fb
3286     attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM;
3287     subpass.pDepthStencilAttachment = NULL;
3288     subpass.pColorAttachments = &attach;
3289     err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp);
3290     ASSERT_VK_SUCCESS(err);
3291 
3292     // Cause error due to mis-matched formats between rp & fb
3293     //  rp attachment 0 now has RGBA8 but corresponding fb attach is BGRA8
3294     fb_info.renderPass = rp;
3295     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00880");
3296     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3297 
3298     m_errorMonitor->VerifyFound();
3299     if (err == VK_SUCCESS) {
3300         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3301     }
3302     vkDestroyRenderPass(m_device->device(), rp, NULL);
3303 
3304     // Create new renderpass with alternate sample count from fb
3305     attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
3306     attach_desc.samples = VK_SAMPLE_COUNT_4_BIT;
3307     err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp);
3308     ASSERT_VK_SUCCESS(err);
3309 
3310     // Cause error due to mis-matched sample count between rp & fb
3311     fb_info.renderPass = rp;
3312     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00881");
3313     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3314 
3315     m_errorMonitor->VerifyFound();
3316     if (err == VK_SUCCESS) {
3317         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3318     }
3319 
3320     vkDestroyRenderPass(m_device->device(), rp, NULL);
3321 
3322     {
3323         // Create an image with 2 mip levels.
3324         VkImageObj image(m_device);
3325         image.Init(128, 128, 2, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
3326         ASSERT_TRUE(image.initialized());
3327 
3328         // Create a image view with two mip levels.
3329         VkImageView view;
3330         VkImageViewCreateInfo ivci = {};
3331         ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
3332         ivci.image = image.handle();
3333         ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
3334         ivci.format = VK_FORMAT_B8G8R8A8_UNORM;
3335         ivci.subresourceRange.layerCount = 1;
3336         ivci.subresourceRange.baseMipLevel = 0;
3337         // Set level count to 2 (only 1 is allowed for FB attachment)
3338         ivci.subresourceRange.levelCount = 2;
3339         ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3340         err = vkCreateImageView(m_device->device(), &ivci, NULL, &view);
3341         ASSERT_VK_SUCCESS(err);
3342 
3343         // Re-create renderpass to have matching sample count
3344         attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
3345         err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp);
3346         ASSERT_VK_SUCCESS(err);
3347 
3348         fb_info.renderPass = rp;
3349         fb_info.pAttachments = &view;
3350         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00883");
3351         err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3352 
3353         m_errorMonitor->VerifyFound();
3354         if (err == VK_SUCCESS) {
3355             vkDestroyFramebuffer(m_device->device(), fb, NULL);
3356         }
3357         vkDestroyImageView(m_device->device(), view, NULL);
3358     }
3359 
3360     // Update view to original color buffer and grow FB dimensions too big
3361     fb_info.pAttachments = ivs;
3362     fb_info.height = 1024;
3363     fb_info.width = 1024;
3364     fb_info.layers = 2;
3365     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00882");
3366     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3367 
3368     m_errorMonitor->VerifyFound();
3369     if (err == VK_SUCCESS) {
3370         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3371     }
3372 
3373     {
3374         if (!push_fragment_density_support) {
3375             printf("%s VK_EXT_fragment_density_map Extension not supported, skipping tests\n", kSkipPrefix);
3376         } else {
3377             uint32_t attachment_width = 512;
3378             uint32_t attachment_height = 512;
3379             VkFormat attachment_format = VK_FORMAT_R8G8_UNORM;
3380             uint32_t frame_width = 512;
3381             uint32_t frame_height = 512;
3382 
3383             // Create a renderPass with a single color attachment for fragment density map
3384             VkAttachmentReference attach_fragment_density_map = {};
3385             attach_fragment_density_map.layout = VK_IMAGE_LAYOUT_GENERAL;
3386             VkSubpassDescription subpass_fragment_density_map = {};
3387             subpass_fragment_density_map.pColorAttachments = &attach_fragment_density_map;
3388             VkRenderPassCreateInfo rpci_fragment_density_map = {};
3389             rpci_fragment_density_map.subpassCount = 1;
3390             rpci_fragment_density_map.pSubpasses = &subpass_fragment_density_map;
3391             rpci_fragment_density_map.attachmentCount = 1;
3392             VkAttachmentDescription attach_desc_fragment_density_map = {};
3393             attach_desc_fragment_density_map.format = attachment_format;
3394             attach_desc_fragment_density_map.samples = VK_SAMPLE_COUNT_1_BIT;
3395             attach_desc_fragment_density_map.finalLayout = VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT;
3396             rpci_fragment_density_map.pAttachments = &attach_desc_fragment_density_map;
3397             rpci_fragment_density_map.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
3398             VkRenderPass rp_fragment_density_map;
3399 
3400             err = vkCreateRenderPass(m_device->device(), &rpci_fragment_density_map, NULL, &rp_fragment_density_map);
3401             ASSERT_VK_SUCCESS(err);
3402 
3403             // Create view attachment
3404             VkImageView view_fragment_density_map;
3405             VkImageViewCreateInfo ivci = {};
3406             ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
3407             ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
3408             ivci.format = attachment_format;
3409             ivci.flags = 0;
3410             ivci.subresourceRange.layerCount = 1;
3411             ivci.subresourceRange.baseMipLevel = 0;
3412             ivci.subresourceRange.levelCount = 1;
3413             ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3414 
3415             VkFramebufferAttachmentImageInfoKHR fb_fdm = {};
3416             fb_fdm.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO_KHR;
3417             fb_fdm.usage = VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT;
3418             fb_fdm.width = frame_width;
3419             fb_fdm.height = frame_height;
3420             fb_fdm.layerCount = 1;
3421             fb_fdm.viewFormatCount = 1;
3422             fb_fdm.pViewFormats = &attachment_format;
3423             VkFramebufferAttachmentsCreateInfoKHR fb_aci_fdm = {};
3424             fb_aci_fdm.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO_KHR;
3425             fb_aci_fdm.attachmentImageInfoCount = 1;
3426             fb_aci_fdm.pAttachmentImageInfos = &fb_fdm;
3427 
3428             VkFramebufferCreateInfo fbci = {};
3429             fbci.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
3430             fbci.pNext = &fb_aci_fdm;
3431             fbci.flags = 0;
3432             fbci.width = frame_width;
3433             fbci.height = frame_height;
3434             fbci.layers = 1;
3435             fbci.renderPass = rp_fragment_density_map;
3436             fbci.attachmentCount = 1;
3437             fbci.pAttachments = &view_fragment_density_map;
3438 
3439             // Set small width
3440             VkImageObj image2(m_device);
3441             image2.Init(16, attachment_height, 1, attachment_format, VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT,
3442                         VK_IMAGE_TILING_LINEAR, 0);
3443             ASSERT_TRUE(image2.initialized());
3444 
3445             ivci.image = image2.handle();
3446             err = vkCreateImageView(m_device->device(), &ivci, NULL, &view_fragment_density_map);
3447             ASSERT_VK_SUCCESS(err);
3448 
3449             fbci.pAttachments = &view_fragment_density_map;
3450 
3451             m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-02555");
3452             err = vkCreateFramebuffer(device(), &fbci, NULL, &fb);
3453 
3454             m_errorMonitor->VerifyFound();
3455             if (err == VK_SUCCESS) {
3456                 vkDestroyFramebuffer(m_device->device(), fb, NULL);
3457             }
3458 
3459             vkDestroyImageView(m_device->device(), view_fragment_density_map, NULL);
3460 
3461             // Set small height
3462             VkImageObj image3(m_device);
3463             image3.Init(attachment_width, 16, 1, attachment_format, VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT,
3464                         VK_IMAGE_TILING_LINEAR, 0);
3465             ASSERT_TRUE(image3.initialized());
3466 
3467             ivci.image = image3.handle();
3468             err = vkCreateImageView(m_device->device(), &ivci, NULL, &view_fragment_density_map);
3469             ASSERT_VK_SUCCESS(err);
3470 
3471             fbci.pAttachments = &view_fragment_density_map;
3472 
3473             m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-02556");
3474             err = vkCreateFramebuffer(device(), &fbci, NULL, &fb);
3475 
3476             m_errorMonitor->VerifyFound();
3477             if (err == VK_SUCCESS) {
3478                 vkDestroyFramebuffer(m_device->device(), fb, NULL);
3479             }
3480 
3481             vkDestroyImageView(m_device->device(), view_fragment_density_map, NULL);
3482 
3483             vkDestroyRenderPass(m_device->device(), rp_fragment_density_map, NULL);
3484         }
3485     }
3486 
3487     {
3488         // Create an image with one mip level.
3489         VkImageObj image(m_device);
3490         image.Init(128, 128, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
3491         ASSERT_TRUE(image.initialized());
3492 
3493         // Create view attachment with non-identity swizzle
3494         VkImageView view;
3495         VkImageViewCreateInfo ivci = {};
3496         ivci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
3497         ivci.image = image.handle();
3498         ivci.viewType = VK_IMAGE_VIEW_TYPE_2D;
3499         ivci.format = VK_FORMAT_B8G8R8A8_UNORM;
3500         ivci.subresourceRange.layerCount = 1;
3501         ivci.subresourceRange.baseMipLevel = 0;
3502         ivci.subresourceRange.levelCount = 1;
3503         ivci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3504         ivci.components.r = VK_COMPONENT_SWIZZLE_G;
3505         ivci.components.g = VK_COMPONENT_SWIZZLE_R;
3506         ivci.components.b = VK_COMPONENT_SWIZZLE_A;
3507         ivci.components.a = VK_COMPONENT_SWIZZLE_B;
3508         err = vkCreateImageView(m_device->device(), &ivci, NULL, &view);
3509         ASSERT_VK_SUCCESS(err);
3510 
3511         fb_info.pAttachments = &view;
3512         fb_info.height = 100;
3513         fb_info.width = 100;
3514         fb_info.layers = 1;
3515 
3516         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00884");
3517         err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3518 
3519         m_errorMonitor->VerifyFound();
3520         if (err == VK_SUCCESS) {
3521             vkDestroyFramebuffer(m_device->device(), fb, NULL);
3522         }
3523         vkDestroyImageView(m_device->device(), view, NULL);
3524     }
3525 
3526     // reset attachment to color attachment
3527     fb_info.pAttachments = ivs;
3528 
3529     // Request fb that exceeds max width
3530     fb_info.width = m_device->props.limits.maxFramebufferWidth + 1;
3531     fb_info.height = 100;
3532     fb_info.layers = 1;
3533     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-width-00886");
3534     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00882");
3535     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3536     m_errorMonitor->VerifyFound();
3537     if (err == VK_SUCCESS) {
3538         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3539     }
3540     // and width=0
3541     fb_info.width = 0;
3542     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-width-00885");
3543     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3544     m_errorMonitor->VerifyFound();
3545     if (err == VK_SUCCESS) {
3546         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3547     }
3548 
3549     // Request fb that exceeds max height
3550     fb_info.width = 100;
3551     fb_info.height = m_device->props.limits.maxFramebufferHeight + 1;
3552     fb_info.layers = 1;
3553     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-height-00888");
3554     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00882");
3555     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3556     m_errorMonitor->VerifyFound();
3557     if (err == VK_SUCCESS) {
3558         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3559     }
3560     // and height=0
3561     fb_info.height = 0;
3562     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-height-00887");
3563     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3564     m_errorMonitor->VerifyFound();
3565     if (err == VK_SUCCESS) {
3566         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3567     }
3568 
3569     // Request fb that exceeds max layers
3570     fb_info.width = 100;
3571     fb_info.height = 100;
3572     fb_info.layers = m_device->props.limits.maxFramebufferLayers + 1;
3573     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-layers-00890");
3574     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-pAttachments-00882");
3575     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3576     m_errorMonitor->VerifyFound();
3577     if (err == VK_SUCCESS) {
3578         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3579     }
3580     // and layers=0
3581     fb_info.layers = 0;
3582     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkFramebufferCreateInfo-layers-00889");
3583     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3584     m_errorMonitor->VerifyFound();
3585     if (err == VK_SUCCESS) {
3586         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3587     }
3588 
3589     // Try to create with pAttachments = NULL
3590     fb_info.layers = 1;
3591     fb_info.pAttachments = NULL;
3592     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID_Undefined");
3593     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
3594     m_errorMonitor->VerifyFound();
3595     if (err == VK_SUCCESS) {
3596         vkDestroyFramebuffer(m_device->device(), fb, NULL);
3597     }
3598 
3599     vkDestroyRenderPass(m_device->device(), rp, NULL);
3600 }
3601 
TEST_F(VkLayerTest,AllocDescriptorFromEmptyPool)3602 TEST_F(VkLayerTest, AllocDescriptorFromEmptyPool) {
3603     TEST_DESCRIPTION("Attempt to allocate more sets and descriptors than descriptor pool has available.");
3604     VkResult err;
3605 
3606     ASSERT_NO_FATAL_FAILURE(Init());
3607     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3608 
3609     // This test is valid for Vulkan 1.0 only -- skip if device has an API version greater than 1.0.
3610     if (m_device->props.apiVersion >= VK_API_VERSION_1_1) {
3611         printf("%s Device has apiVersion greater than 1.0 -- skipping Descriptor Set checks.\n", kSkipPrefix);
3612         return;
3613     }
3614 
3615     // Create Pool w/ 1 Sampler descriptor, but try to alloc Uniform Buffer
3616     // descriptor from it
3617     VkDescriptorPoolSize ds_type_count = {};
3618     ds_type_count.type = VK_DESCRIPTOR_TYPE_SAMPLER;
3619     ds_type_count.descriptorCount = 2;
3620 
3621     VkDescriptorPoolCreateInfo ds_pool_ci = {};
3622     ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
3623     ds_pool_ci.pNext = NULL;
3624     ds_pool_ci.flags = 0;
3625     ds_pool_ci.maxSets = 1;
3626     ds_pool_ci.poolSizeCount = 1;
3627     ds_pool_ci.pPoolSizes = &ds_type_count;
3628 
3629     VkDescriptorPool ds_pool;
3630     err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
3631     ASSERT_VK_SUCCESS(err);
3632 
3633     VkDescriptorSetLayoutBinding dsl_binding_samp = {};
3634     dsl_binding_samp.binding = 0;
3635     dsl_binding_samp.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
3636     dsl_binding_samp.descriptorCount = 1;
3637     dsl_binding_samp.stageFlags = VK_SHADER_STAGE_ALL;
3638     dsl_binding_samp.pImmutableSamplers = NULL;
3639 
3640     const VkDescriptorSetLayoutObj ds_layout_samp(m_device, {dsl_binding_samp});
3641 
3642     // Try to allocate 2 sets when pool only has 1 set
3643     VkDescriptorSet descriptor_sets[2];
3644     VkDescriptorSetLayout set_layouts[2] = {ds_layout_samp.handle(), ds_layout_samp.handle()};
3645     VkDescriptorSetAllocateInfo alloc_info = {};
3646     alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
3647     alloc_info.descriptorSetCount = 2;
3648     alloc_info.descriptorPool = ds_pool;
3649     alloc_info.pSetLayouts = set_layouts;
3650     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
3651                                          "VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-00306");
3652     err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, descriptor_sets);
3653     m_errorMonitor->VerifyFound();
3654 
3655     alloc_info.descriptorSetCount = 1;
3656     // Create layout w/ descriptor type not available in pool
3657     VkDescriptorSetLayoutBinding dsl_binding = {};
3658     dsl_binding.binding = 0;
3659     dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
3660     dsl_binding.descriptorCount = 1;
3661     dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
3662     dsl_binding.pImmutableSamplers = NULL;
3663 
3664     const VkDescriptorSetLayoutObj ds_layout_ub(m_device, {dsl_binding});
3665 
3666     VkDescriptorSet descriptor_set;
3667     alloc_info.descriptorSetCount = 1;
3668     alloc_info.pSetLayouts = &ds_layout_ub.handle();
3669     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307");
3670     err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptor_set);
3671 
3672     m_errorMonitor->VerifyFound();
3673 
3674     vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL);
3675 }
3676 
TEST_F(VkLayerTest,FreeDescriptorFromOneShotPool)3677 TEST_F(VkLayerTest, FreeDescriptorFromOneShotPool) {
3678     VkResult err;
3679 
3680     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkFreeDescriptorSets-descriptorPool-00312");
3681 
3682     ASSERT_NO_FATAL_FAILURE(Init());
3683     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3684 
3685     VkDescriptorPoolSize ds_type_count = {};
3686     ds_type_count.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
3687     ds_type_count.descriptorCount = 1;
3688 
3689     VkDescriptorPoolCreateInfo ds_pool_ci = {};
3690     ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
3691     ds_pool_ci.pNext = NULL;
3692     ds_pool_ci.maxSets = 1;
3693     ds_pool_ci.poolSizeCount = 1;
3694     ds_pool_ci.flags = 0;
3695     // Not specifying VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT means
3696     // app can only call vkResetDescriptorPool on this pool.;
3697     ds_pool_ci.pPoolSizes = &ds_type_count;
3698 
3699     VkDescriptorPool ds_pool;
3700     err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
3701     ASSERT_VK_SUCCESS(err);
3702 
3703     VkDescriptorSetLayoutBinding dsl_binding = {};
3704     dsl_binding.binding = 0;
3705     dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
3706     dsl_binding.descriptorCount = 1;
3707     dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
3708     dsl_binding.pImmutableSamplers = NULL;
3709 
3710     const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding});
3711 
3712     VkDescriptorSet descriptorSet;
3713     VkDescriptorSetAllocateInfo alloc_info = {};
3714     alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
3715     alloc_info.descriptorSetCount = 1;
3716     alloc_info.descriptorPool = ds_pool;
3717     alloc_info.pSetLayouts = &ds_layout.handle();
3718     err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet);
3719     ASSERT_VK_SUCCESS(err);
3720 
3721     err = vkFreeDescriptorSets(m_device->device(), ds_pool, 1, &descriptorSet);
3722     m_errorMonitor->VerifyFound();
3723 
3724     vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL);
3725 }
3726 
TEST_F(VkLayerTest,InvalidDescriptorPool)3727 TEST_F(VkLayerTest, InvalidDescriptorPool) {
3728     // Attempt to clear Descriptor Pool with bad object.
3729     // ObjectTracker should catch this.
3730 
3731     ASSERT_NO_FATAL_FAILURE(Init());
3732     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkResetDescriptorPool-descriptorPool-parameter");
3733     uint64_t fake_pool_handle = 0xbaad6001;
3734     VkDescriptorPool bad_pool = reinterpret_cast<VkDescriptorPool &>(fake_pool_handle);
3735     vkResetDescriptorPool(device(), bad_pool, 0);
3736     m_errorMonitor->VerifyFound();
3737 }
3738 
TEST_F(VkLayerTest,InvalidDescriptorSet)3739 TEST_F(VkLayerTest, InvalidDescriptorSet) {
3740     // Attempt to bind an invalid Descriptor Set to a valid Command Buffer
3741     // ObjectTracker should catch this.
3742     // Create a valid cmd buffer
3743     // call vkCmdBindDescriptorSets w/ false Descriptor Set
3744 
3745     uint64_t fake_set_handle = 0xbaad6001;
3746     VkDescriptorSet bad_set = reinterpret_cast<VkDescriptorSet &>(fake_set_handle);
3747 
3748     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindDescriptorSets-pDescriptorSets-parameter");
3749 
3750     ASSERT_NO_FATAL_FAILURE(Init());
3751 
3752     VkDescriptorSetLayoutBinding layout_binding = {};
3753     layout_binding.binding = 0;
3754     layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
3755     layout_binding.descriptorCount = 1;
3756     layout_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
3757     layout_binding.pImmutableSamplers = NULL;
3758 
3759     const VkDescriptorSetLayoutObj descriptor_set_layout(m_device, {layout_binding});
3760 
3761     const VkPipelineLayoutObj pipeline_layout(DeviceObj(), {&descriptor_set_layout});
3762 
3763     m_commandBuffer->begin();
3764     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1, &bad_set, 0,
3765                             NULL);
3766     m_errorMonitor->VerifyFound();
3767     m_commandBuffer->end();
3768 }
3769 
TEST_F(VkLayerTest,InvalidDescriptorSetLayout)3770 TEST_F(VkLayerTest, InvalidDescriptorSetLayout) {
3771     // Attempt to create a Pipeline Layout with an invalid Descriptor Set Layout.
3772     // ObjectTracker should catch this.
3773     uint64_t fake_layout_handle = 0xbaad6001;
3774     VkDescriptorSetLayout bad_layout = reinterpret_cast<VkDescriptorSetLayout &>(fake_layout_handle);
3775     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-pSetLayouts-parameter");
3776     ASSERT_NO_FATAL_FAILURE(Init());
3777     VkPipelineLayout pipeline_layout;
3778     VkPipelineLayoutCreateInfo plci = {};
3779     plci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
3780     plci.pNext = NULL;
3781     plci.setLayoutCount = 1;
3782     plci.pSetLayouts = &bad_layout;
3783     vkCreatePipelineLayout(device(), &plci, NULL, &pipeline_layout);
3784 
3785     m_errorMonitor->VerifyFound();
3786 }
3787 
TEST_F(VkLayerTest,WriteDescriptorSetIntegrityCheck)3788 TEST_F(VkLayerTest, WriteDescriptorSetIntegrityCheck) {
3789     TEST_DESCRIPTION(
3790         "This test verifies some requirements of chapter 13.2.3 of the Vulkan Spec "
3791         "1) A uniform buffer update must have a valid buffer index. "
3792         "2) When using an array of descriptors in a single WriteDescriptor, the descriptor types and stageflags "
3793         "must all be the same. "
3794         "3) Immutable Sampler state must match across descriptors. "
3795         "4) That sampled image descriptors have required layouts. ");
3796 
3797     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-00324");
3798 
3799     ASSERT_NO_FATAL_FAILURE(Init());
3800 
3801     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
3802     VkSampler sampler;
3803     VkResult err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler);
3804     ASSERT_VK_SUCCESS(err);
3805 
3806     OneOffDescriptorSet::Bindings bindings = {
3807         {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, NULL},
3808         {1, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, NULL},
3809         {2, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, static_cast<VkSampler *>(&sampler)},
3810         {3, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, NULL}};
3811     OneOffDescriptorSet descriptor_set(m_device, bindings);
3812     ASSERT_TRUE(descriptor_set.Initialized());
3813 
3814     VkWriteDescriptorSet descriptor_write = {};
3815     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3816     descriptor_write.dstSet = descriptor_set.set_;
3817     descriptor_write.dstBinding = 0;
3818     descriptor_write.descriptorCount = 1;
3819     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
3820 
3821     // 1) The uniform buffer is intentionally invalid here
3822     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
3823     m_errorMonitor->VerifyFound();
3824 
3825     // Create a buffer to update the descriptor with
3826     uint32_t qfi = 0;
3827     VkBufferCreateInfo buffCI = {};
3828     buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
3829     buffCI.size = 1024;
3830     buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
3831     buffCI.queueFamilyIndexCount = 1;
3832     buffCI.pQueueFamilyIndices = &qfi;
3833 
3834     VkBufferObj dynamic_uniform_buffer;
3835     dynamic_uniform_buffer.init(*m_device, buffCI);
3836 
3837     VkDescriptorBufferInfo buffInfo[2] = {};
3838     buffInfo[0].buffer = dynamic_uniform_buffer.handle();
3839     buffInfo[0].offset = 0;
3840     buffInfo[0].range = 1024;
3841     buffInfo[1].buffer = dynamic_uniform_buffer.handle();
3842     buffInfo[1].offset = 0;
3843     buffInfo[1].range = 1024;
3844     descriptor_write.pBufferInfo = buffInfo;
3845     descriptor_write.descriptorCount = 2;
3846 
3847     // 2) The stateFlags don't match between the first and second descriptor
3848     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-dstArrayElement-00321");
3849     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
3850     m_errorMonitor->VerifyFound();
3851 
3852     // 3) The second descriptor has a null_ptr pImmutableSamplers and
3853     // the third descriptor contains an immutable sampler
3854     descriptor_write.dstBinding = 1;
3855     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
3856 
3857     // Make pImageInfo index non-null to avoid complaints of it missing
3858     VkDescriptorImageInfo imageInfo = {};
3859     imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
3860     descriptor_write.pImageInfo = &imageInfo;
3861     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-dstArrayElement-00321");
3862     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
3863     m_errorMonitor->VerifyFound();
3864 
3865     // 4) That sampled image descriptors have required layouts
3866     // Create images to update the descriptor with
3867     VkImageObj image(m_device);
3868     const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
3869     image.Init(32, 32, 1, tex_format, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
3870     ASSERT_TRUE(image.initialized());
3871 
3872     // Attmept write with incorrect layout for sampled descriptor
3873     imageInfo.sampler = VK_NULL_HANDLE;
3874     imageInfo.imageView = image.targetView(tex_format);
3875     imageInfo.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
3876 
3877     descriptor_write.dstBinding = 3;
3878     descriptor_write.descriptorCount = 1;
3879     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3880     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-01403");
3881     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
3882     m_errorMonitor->VerifyFound();
3883 
3884     vkDestroySampler(m_device->device(), sampler, NULL);
3885 }
3886 
TEST_F(VkLayerTest,WriteDescriptorSetConsecutiveUpdates)3887 TEST_F(VkLayerTest, WriteDescriptorSetConsecutiveUpdates) {
3888     TEST_DESCRIPTION(
3889         "Verifies that updates rolling over to next descriptor work correctly by destroying buffer from consecutive update known "
3890         "to be used in descriptor set and verifying that error is flagged.");
3891 
3892     ASSERT_NO_FATAL_FAILURE(Init());
3893     ASSERT_NO_FATAL_FAILURE(InitViewport());
3894     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3895 
3896     OneOffDescriptorSet descriptor_set(m_device, {
3897                                                      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2, VK_SHADER_STAGE_ALL, nullptr},
3898                                                      {1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
3899                                                  });
3900 
3901     uint32_t qfi = 0;
3902     VkBufferCreateInfo bci = {};
3903     bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
3904     bci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
3905     bci.size = 2048;
3906     bci.queueFamilyIndexCount = 1;
3907     bci.pQueueFamilyIndices = &qfi;
3908     VkBufferObj buffer0;
3909     buffer0.init(*m_device, bci);
3910     CreatePipelineHelper pipe(*this);
3911     {  // Scope 2nd buffer to cause early destruction
3912         VkBufferObj buffer1;
3913         bci.size = 1024;
3914         buffer1.init(*m_device, bci);
3915 
3916         VkDescriptorBufferInfo buffer_info[3] = {};
3917         buffer_info[0].buffer = buffer0.handle();
3918         buffer_info[0].offset = 0;
3919         buffer_info[0].range = 1024;
3920         buffer_info[1].buffer = buffer0.handle();
3921         buffer_info[1].offset = 1024;
3922         buffer_info[1].range = 1024;
3923         buffer_info[2].buffer = buffer1.handle();
3924         buffer_info[2].offset = 0;
3925         buffer_info[2].range = 1024;
3926 
3927         VkWriteDescriptorSet descriptor_write = {};
3928         descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3929         descriptor_write.dstSet = descriptor_set.set_;  // descriptor_set;
3930         descriptor_write.dstBinding = 0;
3931         descriptor_write.descriptorCount = 3;
3932         descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
3933         descriptor_write.pBufferInfo = buffer_info;
3934 
3935         // Update descriptor
3936         vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
3937 
3938         // Create PSO that uses the uniform buffers
3939         char const *fsSource =
3940             "#version 450\n"
3941             "\n"
3942             "layout(location=0) out vec4 x;\n"
3943             "layout(set=0) layout(binding=0) uniform foo { int x; int y; } bar;\n"
3944             "layout(set=0) layout(binding=1) uniform blah { int x; } duh;\n"
3945             "void main(){\n"
3946             "   x = vec4(duh.x, bar.y, bar.x, 1);\n"
3947             "}\n";
3948         VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
3949 
3950         pipe.InitInfo();
3951         pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
3952         const VkDynamicState dyn_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
3953         VkPipelineDynamicStateCreateInfo dyn_state_ci = {};
3954         dyn_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
3955         dyn_state_ci.dynamicStateCount = size(dyn_states);
3956         dyn_state_ci.pDynamicStates = dyn_states;
3957         pipe.dyn_state_ci_ = dyn_state_ci;
3958         pipe.InitState();
3959         pipe.pipeline_layout_ = VkPipelineLayoutObj(m_device, {&descriptor_set.layout_});
3960         pipe.CreateGraphicsPipeline();
3961 
3962         m_commandBuffer->begin();
3963         m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
3964 
3965         vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
3966         vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_layout_.handle(), 0, 1,
3967                                 &descriptor_set.set_, 0, nullptr);
3968 
3969         VkViewport viewport = {0, 0, 16, 16, 0, 1};
3970         vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
3971         VkRect2D scissor = {{0, 0}, {16, 16}};
3972         vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
3973         vkCmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
3974         vkCmdEndRenderPass(m_commandBuffer->handle());
3975         m_commandBuffer->end();
3976     }
3977     // buffer2 just went out of scope and was destroyed along with its memory
3978     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
3979                                          "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkBuffer");
3980     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
3981                                          "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkDeviceMemory");
3982 
3983     VkSubmitInfo submit_info = {};
3984     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
3985     submit_info.commandBufferCount = 1;
3986     submit_info.pCommandBuffers = &m_commandBuffer->handle();
3987     vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
3988     m_errorMonitor->VerifyFound();
3989 }
3990 
TEST_F(VkLayerTest,InvalidCmdBufferDescriptorSetBufferDestroyed)3991 TEST_F(VkLayerTest, InvalidCmdBufferDescriptorSetBufferDestroyed) {
3992     TEST_DESCRIPTION(
3993         "Attempt to draw with a command buffer that is invalid due to a bound descriptor set with a buffer dependency being "
3994         "destroyed.");
3995     ASSERT_NO_FATAL_FAILURE(Init());
3996     ASSERT_NO_FATAL_FAILURE(InitViewport());
3997     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
3998 
3999     CreatePipelineHelper pipe(*this);
4000     {
4001         // Create a buffer to update the descriptor with
4002         uint32_t qfi = 0;
4003         VkBufferCreateInfo buffCI = {};
4004         buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
4005         buffCI.size = 1024;
4006         buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
4007         buffCI.queueFamilyIndexCount = 1;
4008         buffCI.pQueueFamilyIndices = &qfi;
4009 
4010         VkBufferObj buffer;
4011         buffer.init(*m_device, buffCI);
4012 
4013         // Create PSO to be used for draw-time errors below
4014         char const *fsSource =
4015             "#version 450\n"
4016             "\n"
4017             "layout(location=0) out vec4 x;\n"
4018             "layout(set=0) layout(binding=0) uniform foo { int x; int y; } bar;\n"
4019             "void main(){\n"
4020             "   x = vec4(bar.y);\n"
4021             "}\n";
4022         VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
4023         pipe.InitInfo();
4024         pipe.shader_stages_ = {pipe.vs_->GetStageCreateInfo(), fs.GetStageCreateInfo()};
4025         const VkDynamicState dyn_states[] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
4026         VkPipelineDynamicStateCreateInfo dyn_state_ci = {};
4027         dyn_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
4028         dyn_state_ci.dynamicStateCount = size(dyn_states);
4029         dyn_state_ci.pDynamicStates = dyn_states;
4030         pipe.dyn_state_ci_ = dyn_state_ci;
4031         pipe.InitState();
4032         pipe.CreateGraphicsPipeline();
4033 
4034         // Correctly update descriptor to avoid "NOT_UPDATED" error
4035         pipe.descriptor_set_->WriteDescriptorBufferInfo(0, buffer.handle(), 1024);
4036         pipe.descriptor_set_->UpdateDescriptorSets();
4037 
4038         m_commandBuffer->begin();
4039         m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
4040         vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_);
4041         vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.pipeline_layout_.handle(), 0, 1,
4042                                 &pipe.descriptor_set_->set_, 0, NULL);
4043 
4044         vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &m_viewports[0]);
4045         vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &m_scissors[0]);
4046 
4047         m_commandBuffer->Draw(1, 0, 0, 0);
4048         m_commandBuffer->EndRenderPass();
4049         m_commandBuffer->end();
4050     }
4051     // Destroy buffer should invalidate the cmd buffer, causing error on submit
4052 
4053     // Attempt to submit cmd buffer
4054     VkSubmitInfo submit_info = {};
4055     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
4056     submit_info.commandBufferCount = 1;
4057     submit_info.pCommandBuffers = &m_commandBuffer->handle();
4058     // Invalid VkBuffe
4059     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffe");
4060     // Invalid VkDeviceMemory
4061     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that is invalid because bound ");
4062     vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
4063     m_errorMonitor->VerifyFound();
4064 }
4065 
TEST_F(VkLayerTest,InvalidCmdBufferDescriptorSetImageSamplerDestroyed)4066 TEST_F(VkLayerTest, InvalidCmdBufferDescriptorSetImageSamplerDestroyed) {
4067     TEST_DESCRIPTION(
4068         "Attempt to draw with a command buffer that is invalid due to a bound descriptor sets with a combined image sampler having "
4069         "their image, sampler, and descriptor set each respectively destroyed and then attempting to submit associated cmd "
4070         "buffers. Attempt to destroy a DescriptorSet that is in use.");
4071     ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
4072     ASSERT_NO_FATAL_FAILURE(InitViewport());
4073     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4074 
4075     VkDescriptorPoolSize ds_type_count = {};
4076     ds_type_count.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
4077     ds_type_count.descriptorCount = 1;
4078 
4079     VkDescriptorPoolCreateInfo ds_pool_ci = {};
4080     ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
4081     ds_pool_ci.pNext = NULL;
4082     ds_pool_ci.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
4083     ds_pool_ci.maxSets = 1;
4084     ds_pool_ci.poolSizeCount = 1;
4085     ds_pool_ci.pPoolSizes = &ds_type_count;
4086 
4087     VkDescriptorPool ds_pool;
4088     VkResult err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
4089     ASSERT_VK_SUCCESS(err);
4090 
4091     VkDescriptorSetLayoutBinding dsl_binding = {};
4092     dsl_binding.binding = 0;
4093     dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
4094     dsl_binding.descriptorCount = 1;
4095     dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
4096     dsl_binding.pImmutableSamplers = NULL;
4097 
4098     const VkDescriptorSetLayoutObj ds_layout(m_device, {dsl_binding});
4099 
4100     VkDescriptorSet descriptorSet;
4101     VkDescriptorSetAllocateInfo alloc_info = {};
4102     alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
4103     alloc_info.descriptorSetCount = 1;
4104     alloc_info.descriptorPool = ds_pool;
4105     alloc_info.pSetLayouts = &ds_layout.handle();
4106     err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &descriptorSet);
4107     ASSERT_VK_SUCCESS(err);
4108 
4109     const VkPipelineLayoutObj pipeline_layout(m_device, {&ds_layout});
4110 
4111     // Create images to update the descriptor with
4112     VkImage image;
4113     VkImage image2;
4114     const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
4115     const int32_t tex_width = 32;
4116     const int32_t tex_height = 32;
4117     VkImageCreateInfo image_create_info = {};
4118     image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
4119     image_create_info.pNext = NULL;
4120     image_create_info.imageType = VK_IMAGE_TYPE_2D;
4121     image_create_info.format = tex_format;
4122     image_create_info.extent.width = tex_width;
4123     image_create_info.extent.height = tex_height;
4124     image_create_info.extent.depth = 1;
4125     image_create_info.mipLevels = 1;
4126     image_create_info.arrayLayers = 1;
4127     image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
4128     image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
4129     image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
4130     image_create_info.flags = 0;
4131     err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image);
4132     ASSERT_VK_SUCCESS(err);
4133     err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image2);
4134     ASSERT_VK_SUCCESS(err);
4135 
4136     VkMemoryRequirements memory_reqs;
4137     VkDeviceMemory image_memory;
4138     bool pass;
4139     VkMemoryAllocateInfo memory_info = {};
4140     memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
4141     memory_info.pNext = NULL;
4142     memory_info.allocationSize = 0;
4143     memory_info.memoryTypeIndex = 0;
4144     vkGetImageMemoryRequirements(m_device->device(), image, &memory_reqs);
4145     // Allocate enough memory for both images
4146     VkDeviceSize align_mod = memory_reqs.size % memory_reqs.alignment;
4147     VkDeviceSize aligned_size = ((align_mod == 0) ? memory_reqs.size : (memory_reqs.size + memory_reqs.alignment - align_mod));
4148     memory_info.allocationSize = aligned_size * 2;
4149     pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0);
4150     ASSERT_TRUE(pass);
4151     err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &image_memory);
4152     ASSERT_VK_SUCCESS(err);
4153     err = vkBindImageMemory(m_device->device(), image, image_memory, 0);
4154     ASSERT_VK_SUCCESS(err);
4155     // Bind second image to memory right after first image
4156     err = vkBindImageMemory(m_device->device(), image2, image_memory, aligned_size);
4157     ASSERT_VK_SUCCESS(err);
4158 
4159     VkImageViewCreateInfo image_view_create_info = {};
4160     image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
4161     image_view_create_info.image = image;
4162     image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
4163     image_view_create_info.format = tex_format;
4164     image_view_create_info.subresourceRange.layerCount = 1;
4165     image_view_create_info.subresourceRange.baseMipLevel = 0;
4166     image_view_create_info.subresourceRange.levelCount = 1;
4167     image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
4168 
4169     VkImageView tmp_view;  // First test deletes this view
4170     VkImageView view;
4171     VkImageView view2;
4172     err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &tmp_view);
4173     ASSERT_VK_SUCCESS(err);
4174     err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view);
4175     ASSERT_VK_SUCCESS(err);
4176     image_view_create_info.image = image2;
4177     err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view2);
4178     ASSERT_VK_SUCCESS(err);
4179     // Create Samplers
4180     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
4181     VkSampler sampler;
4182     VkSampler sampler2;
4183     err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler);
4184     ASSERT_VK_SUCCESS(err);
4185     err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler2);
4186     ASSERT_VK_SUCCESS(err);
4187     // Update descriptor with image and sampler
4188     VkDescriptorImageInfo img_info = {};
4189     img_info.sampler = sampler;
4190     img_info.imageView = tmp_view;
4191     img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4192 
4193     VkWriteDescriptorSet descriptor_write;
4194     memset(&descriptor_write, 0, sizeof(descriptor_write));
4195     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4196     descriptor_write.dstSet = descriptorSet;
4197     descriptor_write.dstBinding = 0;
4198     descriptor_write.descriptorCount = 1;
4199     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
4200     descriptor_write.pImageInfo = &img_info;
4201 
4202     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
4203 
4204     // Create PSO to be used for draw-time errors below
4205     char const *fsSource =
4206         "#version 450\n"
4207         "\n"
4208         "layout(set=0, binding=0) uniform sampler2D s;\n"
4209         "layout(location=0) out vec4 x;\n"
4210         "void main(){\n"
4211         "   x = texture(s, vec2(1));\n"
4212         "}\n";
4213     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
4214     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
4215     VkPipelineObj pipe(m_device);
4216     pipe.AddShader(&vs);
4217     pipe.AddShader(&fs);
4218     pipe.AddDefaultColorAttachment();
4219     pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass());
4220 
4221     // First error case is destroying sampler prior to cmd buffer submission
4222     m_commandBuffer->begin();
4223 
4224     // Transit image layout from VK_IMAGE_LAYOUT_UNDEFINED into VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
4225     VkImageMemoryBarrier barrier = {};
4226     barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
4227     barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
4228     barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4229     barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4230     barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4231     barrier.image = image;
4232     barrier.srcAccessMask = 0;
4233     barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
4234     barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
4235     barrier.subresourceRange.baseMipLevel = 0;
4236     barrier.subresourceRange.levelCount = 1;
4237     barrier.subresourceRange.baseArrayLayer = 0;
4238     barrier.subresourceRange.layerCount = 1;
4239     vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0,
4240                          nullptr, 0, nullptr, 1, &barrier);
4241 
4242     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
4243     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
4244     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
4245                             &descriptorSet, 0, NULL);
4246     VkViewport viewport = {0, 0, 16, 16, 0, 1};
4247     VkRect2D scissor = {{0, 0}, {16, 16}};
4248     vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
4249     vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
4250     m_commandBuffer->Draw(1, 0, 0, 0);
4251     m_commandBuffer->EndRenderPass();
4252     m_commandBuffer->end();
4253     VkSubmitInfo submit_info = {};
4254     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
4255     submit_info.commandBufferCount = 1;
4256     submit_info.pCommandBuffers = &m_commandBuffer->handle();
4257     // This first submit should be successful
4258     vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
4259     vkQueueWaitIdle(m_device->m_queue);
4260 
4261     // Now destroy imageview and reset cmdBuffer
4262     vkDestroyImageView(m_device->device(), tmp_view, NULL);
4263     m_commandBuffer->reset(0);
4264     m_commandBuffer->begin();
4265     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
4266     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
4267     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
4268                             &descriptorSet, 0, NULL);
4269     vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
4270     vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
4271     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " that has been destroyed.");
4272     m_commandBuffer->Draw(1, 0, 0, 0);
4273     m_errorMonitor->VerifyFound();
4274     m_commandBuffer->EndRenderPass();
4275     m_commandBuffer->end();
4276 
4277     // Re-update descriptor with new view
4278     img_info.imageView = view;
4279     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
4280     // Now test destroying sampler prior to cmd buffer submission
4281     m_commandBuffer->begin();
4282     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
4283     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
4284     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
4285                             &descriptorSet, 0, NULL);
4286     vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
4287     vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
4288     m_commandBuffer->Draw(1, 0, 0, 0);
4289     m_commandBuffer->EndRenderPass();
4290     m_commandBuffer->end();
4291     // Destroy sampler invalidates the cmd buffer, causing error on submit
4292     vkDestroySampler(m_device->device(), sampler, NULL);
4293     // Attempt to submit cmd buffer
4294     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4295                                          "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkSampler");
4296     submit_info = {};
4297     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
4298     submit_info.commandBufferCount = 1;
4299     submit_info.pCommandBuffers = &m_commandBuffer->handle();
4300     vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
4301     m_errorMonitor->VerifyFound();
4302 
4303     // Now re-update descriptor with valid sampler and delete image
4304     img_info.sampler = sampler2;
4305     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
4306 
4307     VkCommandBufferBeginInfo info = {};
4308     info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
4309     info.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
4310     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4311                                          "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkImage");
4312     m_commandBuffer->begin(&info);
4313     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
4314     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
4315     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
4316                             &descriptorSet, 0, NULL);
4317     vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
4318     vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
4319     m_commandBuffer->Draw(1, 0, 0, 0);
4320     m_commandBuffer->EndRenderPass();
4321     m_commandBuffer->end();
4322     // Destroy image invalidates the cmd buffer, causing error on submit
4323     vkDestroyImage(m_device->device(), image, NULL);
4324     // Attempt to submit cmd buffer
4325     submit_info = {};
4326     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
4327     submit_info.commandBufferCount = 1;
4328     submit_info.pCommandBuffers = &m_commandBuffer->handle();
4329     vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
4330     m_errorMonitor->VerifyFound();
4331     // Now update descriptor to be valid, but then free descriptor
4332     img_info.imageView = view2;
4333     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
4334     m_commandBuffer->begin(&info);
4335 
4336     // Transit image2 layout from VK_IMAGE_LAYOUT_UNDEFINED into VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
4337     barrier.image = image2;
4338     vkCmdPipelineBarrier(m_commandBuffer->handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0,
4339                          nullptr, 0, nullptr, 1, &barrier);
4340 
4341     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
4342     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
4343     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
4344                             &descriptorSet, 0, NULL);
4345     vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
4346     vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
4347     m_commandBuffer->Draw(1, 0, 0, 0);
4348     m_commandBuffer->EndRenderPass();
4349     m_commandBuffer->end();
4350     vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
4351 
4352     // Immediately try to destroy the descriptor set in the active command buffer - failure expected
4353     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkFreeDescriptorSets-pDescriptorSets-00309");
4354     vkFreeDescriptorSets(m_device->device(), ds_pool, 1, &descriptorSet);
4355     m_errorMonitor->VerifyFound();
4356 
4357     // Try again once the queue is idle - should succeed w/o error
4358     // TODO - though the particular error above doesn't re-occur, there are other 'unexpecteds' still to clean up
4359     vkQueueWaitIdle(m_device->m_queue);
4360     m_errorMonitor->SetUnexpectedError(
4361         "pDescriptorSets must be a valid pointer to an array of descriptorSetCount VkDescriptorSet handles, each element of which "
4362         "must either be a valid handle or VK_NULL_HANDLE");
4363     m_errorMonitor->SetUnexpectedError("Unable to remove DescriptorSet obj");
4364     vkFreeDescriptorSets(m_device->device(), ds_pool, 1, &descriptorSet);
4365 
4366     // Attempt to submit cmd buffer containing the freed descriptor set
4367     submit_info = {};
4368     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
4369     submit_info.commandBufferCount = 1;
4370     submit_info.pCommandBuffers = &m_commandBuffer->handle();
4371     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4372                                          "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkDescriptorSet");
4373     vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
4374     m_errorMonitor->VerifyFound();
4375 
4376     // Cleanup
4377     vkFreeMemory(m_device->device(), image_memory, NULL);
4378     vkDestroySampler(m_device->device(), sampler2, NULL);
4379     vkDestroyImage(m_device->device(), image2, NULL);
4380     vkDestroyImageView(m_device->device(), view, NULL);
4381     vkDestroyImageView(m_device->device(), view2, NULL);
4382     vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL);
4383 }
4384 
TEST_F(VkLayerTest,InvalidDescriptorSetSamplerDestroyed)4385 TEST_F(VkLayerTest, InvalidDescriptorSetSamplerDestroyed) {
4386     TEST_DESCRIPTION("Attempt to draw with a bound descriptor sets with a combined image sampler where sampler has been deleted.");
4387     ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
4388     ASSERT_NO_FATAL_FAILURE(InitViewport());
4389     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4390 
4391     OneOffDescriptorSet descriptor_set(m_device,
4392                                        {
4393                                            {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr},
4394                                            {1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr},
4395                                        });
4396 
4397     const VkPipelineLayoutObj pipeline_layout(m_device, {&descriptor_set.layout_});
4398     // Create images to update the descriptor with
4399     VkImageObj image(m_device);
4400     const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
4401     image.Init(32, 32, 1, tex_format, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
4402     ASSERT_TRUE(image.initialized());
4403 
4404     VkImageViewCreateInfo image_view_create_info = {};
4405     image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
4406     image_view_create_info.image = image.handle();
4407     image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
4408     image_view_create_info.format = tex_format;
4409     image_view_create_info.subresourceRange.layerCount = 1;
4410     image_view_create_info.subresourceRange.baseMipLevel = 0;
4411     image_view_create_info.subresourceRange.levelCount = 1;
4412     image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
4413 
4414     VkImageView view;
4415     VkResult err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view);
4416     ASSERT_VK_SUCCESS(err);
4417     // Create Samplers
4418     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
4419     VkSampler sampler;
4420     err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler);
4421     ASSERT_VK_SUCCESS(err);
4422     VkSampler sampler1;
4423     err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler1);
4424     ASSERT_VK_SUCCESS(err);
4425     // Update descriptor with image and sampler
4426     VkDescriptorImageInfo img_info = {};
4427     img_info.sampler = sampler;
4428     img_info.imageView = view;
4429     img_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4430 
4431     VkDescriptorImageInfo img_info1 = img_info;
4432     img_info1.sampler = sampler1;
4433 
4434     VkWriteDescriptorSet descriptor_write;
4435     memset(&descriptor_write, 0, sizeof(descriptor_write));
4436     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4437     descriptor_write.dstSet = descriptor_set.set_;
4438     descriptor_write.dstBinding = 0;
4439     descriptor_write.descriptorCount = 1;
4440     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
4441     descriptor_write.pImageInfo = &img_info;
4442 
4443     std::array<VkWriteDescriptorSet, 2> descriptor_writes = {descriptor_write, descriptor_write};
4444     descriptor_writes[1].dstBinding = 1;
4445     descriptor_writes[1].pImageInfo = &img_info1;
4446 
4447     vkUpdateDescriptorSets(m_device->device(), 2, descriptor_writes.data(), 0, NULL);
4448 
4449     // Destroy the sampler before it's bound to the cmd buffer
4450     vkDestroySampler(m_device->device(), sampler1, NULL);
4451 
4452     // Create PSO to be used for draw-time errors below
4453     char const *fsSource =
4454         "#version 450\n"
4455         "\n"
4456         "layout(set=0, binding=0) uniform sampler2D s;\n"
4457         "layout(set=0, binding=1) uniform sampler2D s1;\n"
4458         "layout(location=0) out vec4 x;\n"
4459         "void main(){\n"
4460         "   x = texture(s, vec2(1));\n"
4461         "   x = texture(s1, vec2(1));\n"
4462         "}\n";
4463     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
4464     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
4465     VkPipelineObj pipe(m_device);
4466     pipe.AddShader(&vs);
4467     pipe.AddShader(&fs);
4468     pipe.AddDefaultColorAttachment();
4469     pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass());
4470 
4471     // First error case is destroying sampler prior to cmd buffer submission
4472     m_commandBuffer->begin();
4473     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
4474     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
4475     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
4476                             &descriptor_set.set_, 0, NULL);
4477     VkViewport viewport = {0, 0, 16, 16, 0, 1};
4478     VkRect2D scissor = {{0, 0}, {16, 16}};
4479     vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
4480     vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
4481     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " Descriptor in binding #1 index 0 is using sampler ");
4482     m_commandBuffer->Draw(1, 0, 0, 0);
4483     m_errorMonitor->VerifyFound();
4484 
4485     m_commandBuffer->EndRenderPass();
4486     m_commandBuffer->end();
4487 
4488     vkDestroySampler(m_device->device(), sampler, NULL);
4489     vkDestroyImageView(m_device->device(), view, NULL);
4490 }
4491 
TEST_F(VkLayerTest,ImageDescriptorLayoutMismatch)4492 TEST_F(VkLayerTest, ImageDescriptorLayoutMismatch) {
4493     TEST_DESCRIPTION("Create an image sampler layout->image layout mismatch within/without a command buffer");
4494 
4495     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
4496     bool maint2_support = DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE2_EXTENSION_NAME);
4497     if (maint2_support) {
4498         m_device_extension_names.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME);
4499     } else {
4500         printf("%s Relaxed layout matching subtest requires API >= 1.1 or KHR_MAINTENANCE2 extension, unavailable - skipped.\n",
4501                kSkipPrefix);
4502     }
4503     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
4504 
4505     ASSERT_NO_FATAL_FAILURE(InitViewport());
4506     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4507 
4508     OneOffDescriptorSet descriptor_set(m_device,
4509                                        {
4510                                            {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr},
4511                                        });
4512     VkDescriptorSet descriptorSet = descriptor_set.set_;
4513 
4514     const VkPipelineLayoutObj pipeline_layout(m_device, {&descriptor_set.layout_});
4515 
4516     // Create image, view, and sampler
4517     const VkFormat format = VK_FORMAT_B8G8R8A8_UNORM;
4518     VkImageObj image(m_device);
4519     image.Init(32, 32, 1, format, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_TILING_OPTIMAL,
4520                0);
4521     ASSERT_TRUE(image.initialized());
4522 
4523     vk_testing::ImageView view;
4524     auto image_view_create_info = SafeSaneImageViewCreateInfo(image, format, VK_IMAGE_ASPECT_COLOR_BIT);
4525     view.init(*m_device, image_view_create_info);
4526     ASSERT_TRUE(view.initialized());
4527 
4528     // Create Sampler
4529     vk_testing::Sampler sampler;
4530     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
4531     sampler.init(*m_device, sampler_ci);
4532     ASSERT_TRUE(sampler.initialized());
4533 
4534     // Setup structure for descriptor update with sampler, for update in do_test below
4535     VkDescriptorImageInfo img_info = {};
4536     img_info.sampler = sampler.handle();
4537 
4538     VkWriteDescriptorSet descriptor_write;
4539     memset(&descriptor_write, 0, sizeof(descriptor_write));
4540     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4541     descriptor_write.dstSet = descriptorSet;
4542     descriptor_write.dstBinding = 0;
4543     descriptor_write.descriptorCount = 1;
4544     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
4545     descriptor_write.pImageInfo = &img_info;
4546 
4547     // Create PSO to be used for draw-time errors below
4548     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
4549     VkShaderObj fs(m_device, bindStateFragSamplerShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
4550     VkPipelineObj pipe(m_device);
4551     pipe.AddShader(&vs);
4552     pipe.AddShader(&fs);
4553     pipe.AddDefaultColorAttachment();
4554     pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass());
4555 
4556     VkViewport viewport = {0, 0, 16, 16, 0, 1};
4557     VkRect2D scissor = {{0, 0}, {16, 16}};
4558 
4559     VkCommandBufferObj cmd_buf(m_device, m_commandPool);
4560 
4561     VkSubmitInfo submit_info = {};
4562     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
4563     submit_info.commandBufferCount = 1;
4564     submit_info.pCommandBuffers = &cmd_buf.handle();
4565 
4566     enum TestType {
4567         kInternal,  // Image layout mismatch is *within* a given command buffer
4568         kExternal   // Image layout mismatch is with the current state of the image, found at QueueSubmit
4569     };
4570     std::array<TestType, 2> test_list = {kInternal, kExternal};
4571     const std::vector<std::string> internal_errors = {"VUID-VkDescriptorImageInfo-imageLayout-00344",
4572                                                       "UNASSIGNED-CoreValidation-DrawState-DescriptorSetNotUpdated"};
4573     const std::vector<std::string> external_errors = {"UNASSIGNED-CoreValidation-DrawState-InvalidImageLayout"};
4574 
4575     // Common steps to create the two classes of errors (or two classes of positives)
4576     auto do_test = [&](VkImageObj *image, vk_testing::ImageView *view, VkImageAspectFlags aspect_mask, VkImageLayout image_layout,
4577                        VkImageLayout descriptor_layout, const bool positive_test) {
4578         // Set up the descriptor
4579         img_info.imageView = view->handle();
4580         img_info.imageLayout = descriptor_layout;
4581         vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
4582 
4583         for (TestType test_type : test_list) {
4584             cmd_buf.begin();
4585             // record layout different than actual descriptor layout.
4586             const VkFlags read_write = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
4587             auto image_barrier = image->image_memory_barrier(read_write, read_write, VK_IMAGE_LAYOUT_UNDEFINED, image_layout,
4588                                                              image->subresource_range(aspect_mask));
4589             cmd_buf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, nullptr, 0,
4590                                     nullptr, 1, &image_barrier);
4591 
4592             if (test_type == kExternal) {
4593                 // The image layout is external to the command buffer we are recording to test.  Submit to push to instance scope.
4594                 cmd_buf.end();
4595                 vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
4596                 vkQueueWaitIdle(m_device->m_queue);
4597                 cmd_buf.begin();
4598             }
4599 
4600             cmd_buf.BeginRenderPass(m_renderPassBeginInfo);
4601             vkCmdBindPipeline(cmd_buf.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
4602             vkCmdBindDescriptorSets(cmd_buf.handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
4603                                     &descriptorSet, 0, NULL);
4604             vkCmdSetViewport(cmd_buf.handle(), 0, 1, &viewport);
4605             vkCmdSetScissor(cmd_buf.handle(), 0, 1, &scissor);
4606 
4607             // At draw time the update layout will mis-match the actual layout
4608             if (positive_test || (test_type == kExternal)) {
4609                 m_errorMonitor->ExpectSuccess();
4610             } else {
4611                 for (const auto &err : internal_errors) {
4612                     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, err.c_str());
4613                 }
4614             }
4615             cmd_buf.Draw(1, 0, 0, 0);
4616             if (positive_test || (test_type == kExternal)) {
4617                 m_errorMonitor->VerifyNotFound();
4618             } else {
4619                 m_errorMonitor->VerifyFound();
4620             }
4621 
4622             m_errorMonitor->ExpectSuccess();
4623             cmd_buf.EndRenderPass();
4624             cmd_buf.end();
4625             m_errorMonitor->VerifyNotFound();
4626 
4627             // Submit cmd buffer
4628             if (positive_test || (test_type == kInternal)) {
4629                 m_errorMonitor->ExpectSuccess();
4630             } else {
4631                 for (const auto &err : external_errors) {
4632                     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, err.c_str());
4633                 }
4634             }
4635             vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
4636             vkQueueWaitIdle(m_device->m_queue);
4637             if (positive_test || (test_type == kInternal)) {
4638                 m_errorMonitor->VerifyNotFound();
4639             } else {
4640                 m_errorMonitor->VerifyFound();
4641             }
4642         }
4643     };
4644     do_test(&image, &view, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4645             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, /* positive */ false);
4646 
4647     // Create depth stencil image and views
4648     const VkFormat format_ds = m_depth_stencil_fmt = FindSupportedDepthStencilFormat(gpu());
4649     bool ds_test_support = maint2_support && (format_ds != VK_FORMAT_UNDEFINED);
4650     VkImageObj image_ds(m_device);
4651     vk_testing::ImageView stencil_view;
4652     vk_testing::ImageView depth_view;
4653     const VkImageLayout ds_image_layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
4654     const VkImageLayout depth_descriptor_layout = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
4655     const VkImageLayout stencil_descriptor_layout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
4656     const VkImageAspectFlags depth_stencil = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
4657     if (ds_test_support) {
4658         image_ds.Init(32, 32, 1, format_ds, VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
4659                       VK_IMAGE_TILING_OPTIMAL, 0);
4660         ASSERT_TRUE(image_ds.initialized());
4661         auto ds_view_ci = SafeSaneImageViewCreateInfo(image_ds, format_ds, VK_IMAGE_ASPECT_DEPTH_BIT);
4662         depth_view.init(*m_device, ds_view_ci);
4663         ds_view_ci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
4664         stencil_view.init(*m_device, ds_view_ci);
4665         do_test(&image_ds, &depth_view, depth_stencil, ds_image_layout, depth_descriptor_layout, /* positive */ true);
4666         do_test(&image_ds, &depth_view, depth_stencil, ds_image_layout, VK_IMAGE_LAYOUT_GENERAL, /* positive */ false);
4667         do_test(&image_ds, &stencil_view, depth_stencil, ds_image_layout, stencil_descriptor_layout, /* positive */ true);
4668         do_test(&image_ds, &stencil_view, depth_stencil, ds_image_layout, VK_IMAGE_LAYOUT_GENERAL, /* positive */ false);
4669     }
4670 }
4671 
TEST_F(VkLayerTest,DescriptorPoolInUseResetSignaled)4672 TEST_F(VkLayerTest, DescriptorPoolInUseResetSignaled) {
4673     TEST_DESCRIPTION("Reset a DescriptorPool with a DescriptorSet that is in use.");
4674     ASSERT_NO_FATAL_FAILURE(Init());
4675     ASSERT_NO_FATAL_FAILURE(InitViewport());
4676     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4677 
4678     OneOffDescriptorSet descriptor_set(m_device,
4679                                        {
4680                                            {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr},
4681                                        });
4682 
4683     const VkPipelineLayoutObj pipeline_layout(m_device, {&descriptor_set.layout_});
4684 
4685     // Create image to update the descriptor with
4686     VkImageObj image(m_device);
4687     image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
4688     ASSERT_TRUE(image.initialized());
4689 
4690     VkImageView view = image.targetView(VK_FORMAT_B8G8R8A8_UNORM);
4691     // Create Sampler
4692     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
4693     VkSampler sampler;
4694     VkResult err = vkCreateSampler(m_device->device(), &sampler_ci, nullptr, &sampler);
4695     ASSERT_VK_SUCCESS(err);
4696     // Update descriptor with image and sampler
4697     descriptor_set.WriteDescriptorImageInfo(0, view, sampler);
4698     descriptor_set.UpdateDescriptorSets();
4699 
4700     // Create PSO to be used for draw-time errors below
4701     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
4702     VkShaderObj fs(m_device, bindStateFragSamplerShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
4703     VkPipelineObj pipe(m_device);
4704     pipe.AddShader(&vs);
4705     pipe.AddShader(&fs);
4706     pipe.AddDefaultColorAttachment();
4707     pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass());
4708 
4709     m_commandBuffer->begin();
4710     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
4711     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
4712     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
4713                             &descriptor_set.set_, 0, nullptr);
4714 
4715     VkViewport viewport = {0, 0, 16, 16, 0, 1};
4716     VkRect2D scissor = {{0, 0}, {16, 16}};
4717     vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
4718     vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
4719 
4720     m_commandBuffer->Draw(1, 0, 0, 0);
4721     m_commandBuffer->EndRenderPass();
4722     m_commandBuffer->end();
4723     // Submit cmd buffer to put pool in-flight
4724     VkSubmitInfo submit_info = {};
4725     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
4726     submit_info.commandBufferCount = 1;
4727     submit_info.pCommandBuffers = &m_commandBuffer->handle();
4728     vkQueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
4729     // Reset pool while in-flight, causing error
4730     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkResetDescriptorPool-descriptorPool-00313");
4731     vkResetDescriptorPool(m_device->device(), descriptor_set.pool_, 0);
4732     m_errorMonitor->VerifyFound();
4733     vkQueueWaitIdle(m_device->m_queue);
4734     // Cleanup
4735     vkDestroySampler(m_device->device(), sampler, nullptr);
4736     m_errorMonitor->SetUnexpectedError(
4737         "If descriptorPool is not VK_NULL_HANDLE, descriptorPool must be a valid VkDescriptorPool handle");
4738     m_errorMonitor->SetUnexpectedError("Unable to remove DescriptorPool obj");
4739 }
4740 
TEST_F(VkLayerTest,DescriptorImageUpdateNoMemoryBound)4741 TEST_F(VkLayerTest, DescriptorImageUpdateNoMemoryBound) {
4742     TEST_DESCRIPTION("Attempt an image descriptor set update where image's bound memory has been freed.");
4743     ASSERT_NO_FATAL_FAILURE(Init());
4744     ASSERT_NO_FATAL_FAILURE(InitViewport());
4745     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4746 
4747     OneOffDescriptorSet descriptor_set(m_device,
4748                                        {
4749                                            {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr},
4750                                        });
4751 
4752     // Create images to update the descriptor with
4753     VkImage image;
4754     const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM;
4755     const int32_t tex_width = 32;
4756     const int32_t tex_height = 32;
4757     VkImageCreateInfo image_create_info = {};
4758     image_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
4759     image_create_info.pNext = NULL;
4760     image_create_info.imageType = VK_IMAGE_TYPE_2D;
4761     image_create_info.format = tex_format;
4762     image_create_info.extent.width = tex_width;
4763     image_create_info.extent.height = tex_height;
4764     image_create_info.extent.depth = 1;
4765     image_create_info.mipLevels = 1;
4766     image_create_info.arrayLayers = 1;
4767     image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
4768     image_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
4769     image_create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
4770     image_create_info.flags = 0;
4771     VkResult err = vkCreateImage(m_device->device(), &image_create_info, NULL, &image);
4772     ASSERT_VK_SUCCESS(err);
4773     // Initially bind memory to avoid error at bind view time. We'll break binding before update.
4774     VkMemoryRequirements memory_reqs;
4775     VkDeviceMemory image_memory;
4776     bool pass;
4777     VkMemoryAllocateInfo memory_info = {};
4778     memory_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
4779     memory_info.pNext = NULL;
4780     memory_info.allocationSize = 0;
4781     memory_info.memoryTypeIndex = 0;
4782     vkGetImageMemoryRequirements(m_device->device(), image, &memory_reqs);
4783     // Allocate enough memory for image
4784     memory_info.allocationSize = memory_reqs.size;
4785     pass = m_device->phy().set_memory_type(memory_reqs.memoryTypeBits, &memory_info, 0);
4786     ASSERT_TRUE(pass);
4787     err = vkAllocateMemory(m_device->device(), &memory_info, NULL, &image_memory);
4788     ASSERT_VK_SUCCESS(err);
4789     err = vkBindImageMemory(m_device->device(), image, image_memory, 0);
4790     ASSERT_VK_SUCCESS(err);
4791 
4792     VkImageViewCreateInfo image_view_create_info = {};
4793     image_view_create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
4794     image_view_create_info.image = image;
4795     image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
4796     image_view_create_info.format = tex_format;
4797     image_view_create_info.subresourceRange.layerCount = 1;
4798     image_view_create_info.subresourceRange.baseMipLevel = 0;
4799     image_view_create_info.subresourceRange.levelCount = 1;
4800     image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
4801 
4802     VkImageView view;
4803     err = vkCreateImageView(m_device->device(), &image_view_create_info, NULL, &view);
4804     ASSERT_VK_SUCCESS(err);
4805     // Create Samplers
4806     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
4807     VkSampler sampler;
4808     err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler);
4809     ASSERT_VK_SUCCESS(err);
4810     // Update descriptor with image and sampler
4811     descriptor_set.WriteDescriptorImageInfo(0, view, sampler);
4812     // Break memory binding and attempt update
4813     vkFreeMemory(m_device->device(), image_memory, nullptr);
4814     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4815                                          " previously bound memory was freed. Memory must not be freed prior to this operation.");
4816     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4817                                          "vkUpdateDescriptorSets() failed write update validation for ");
4818     descriptor_set.UpdateDescriptorSets();
4819     m_errorMonitor->VerifyFound();
4820     // Cleanup
4821     vkDestroyImage(m_device->device(), image, NULL);
4822     vkDestroySampler(m_device->device(), sampler, NULL);
4823     vkDestroyImageView(m_device->device(), view, NULL);
4824 }
4825 
TEST_F(VkLayerTest,InvalidDynamicOffsetCases)4826 TEST_F(VkLayerTest, InvalidDynamicOffsetCases) {
4827     // Create a descriptorSet w/ dynamic descriptor and then hit 3 offset error
4828     // cases:
4829     // 1. No dynamicOffset supplied
4830     // 2. Too many dynamicOffsets supplied
4831     // 3. Dynamic offset oversteps buffer being updated
4832     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4833                                          " requires 1 dynamicOffsets, but only 0 dynamicOffsets are left in pDynamicOffsets ");
4834 
4835     ASSERT_NO_FATAL_FAILURE(Init());
4836     ASSERT_NO_FATAL_FAILURE(InitViewport());
4837     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4838 
4839     OneOffDescriptorSet descriptor_set(m_device,
4840                                        {
4841                                            {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_ALL, nullptr},
4842                                        });
4843 
4844     const VkPipelineLayoutObj pipeline_layout(m_device, {&descriptor_set.layout_});
4845 
4846     // Create a buffer to update the descriptor with
4847     uint32_t qfi = 0;
4848     VkBufferCreateInfo buffCI = {};
4849     buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
4850     buffCI.size = 1024;
4851     buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
4852     buffCI.queueFamilyIndexCount = 1;
4853     buffCI.pQueueFamilyIndices = &qfi;
4854 
4855     VkBufferObj dynamic_uniform_buffer;
4856     dynamic_uniform_buffer.init(*m_device, buffCI);
4857 
4858     // Correctly update descriptor to avoid "NOT_UPDATED" error
4859     descriptor_set.WriteDescriptorBufferInfo(0, dynamic_uniform_buffer.handle(), 1024, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC);
4860     descriptor_set.UpdateDescriptorSets();
4861 
4862     m_commandBuffer->begin();
4863     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
4864     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
4865                             &descriptor_set.set_, 0, NULL);
4866     m_errorMonitor->VerifyFound();
4867     uint32_t pDynOff[2] = {512, 756};
4868     // Now cause error b/c too many dynOffsets in array for # of dyn descriptors
4869     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4870                                          "Attempting to bind 1 descriptorSets with 1 dynamic descriptors, but ");
4871     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
4872                             &descriptor_set.set_, 2, pDynOff);
4873     m_errorMonitor->VerifyFound();
4874     // Finally cause error due to dynamicOffset being too big
4875     m_errorMonitor->SetDesiredFailureMsg(
4876         VK_DEBUG_REPORT_ERROR_BIT_EXT,
4877         " dynamic offset 512 combined with offset 0 and range 1024 that oversteps the buffer size of 1024");
4878     // Create PSO to be used for draw-time errors below
4879     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
4880     VkShaderObj fs(m_device, bindStateFragUniformShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
4881     VkPipelineObj pipe(m_device);
4882     pipe.AddShader(&vs);
4883     pipe.AddShader(&fs);
4884     pipe.AddDefaultColorAttachment();
4885     pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass());
4886 
4887     VkViewport viewport = {0, 0, 16, 16, 0, 1};
4888     vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
4889     VkRect2D scissor = {{0, 0}, {16, 16}};
4890     vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
4891 
4892     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
4893     // This update should succeed, but offset size of 512 will overstep buffer
4894     // /w range 1024 & size 1024
4895     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 1,
4896                             &descriptor_set.set_, 1, pDynOff);
4897     m_commandBuffer->Draw(1, 0, 0, 0);
4898     m_errorMonitor->VerifyFound();
4899 
4900     m_commandBuffer->EndRenderPass();
4901     m_commandBuffer->end();
4902 }
4903 
TEST_F(VkLayerTest,DescriptorBufferUpdateNoMemoryBound)4904 TEST_F(VkLayerTest, DescriptorBufferUpdateNoMemoryBound) {
4905     TEST_DESCRIPTION("Attempt to update a descriptor with a non-sparse buffer that doesn't have memory bound");
4906     VkResult err;
4907     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4908                                          " used with no memory bound. Memory should be bound by calling vkBindBufferMemory().");
4909     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
4910                                          "vkUpdateDescriptorSets() failed write update validation for ");
4911 
4912     ASSERT_NO_FATAL_FAILURE(Init());
4913     ASSERT_NO_FATAL_FAILURE(InitViewport());
4914     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4915 
4916     OneOffDescriptorSet descriptor_set(m_device,
4917                                        {
4918                                            {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_ALL, nullptr},
4919                                        });
4920 
4921     // Create a buffer to update the descriptor with
4922     uint32_t qfi = 0;
4923     VkBufferCreateInfo buffCI = {};
4924     buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
4925     buffCI.size = 1024;
4926     buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
4927     buffCI.queueFamilyIndexCount = 1;
4928     buffCI.pQueueFamilyIndices = &qfi;
4929 
4930     VkBuffer dynamic_uniform_buffer;
4931     err = vkCreateBuffer(m_device->device(), &buffCI, NULL, &dynamic_uniform_buffer);
4932     ASSERT_VK_SUCCESS(err);
4933 
4934     // Attempt to update descriptor without binding memory to it
4935     descriptor_set.WriteDescriptorBufferInfo(0, dynamic_uniform_buffer, 1024, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC);
4936     descriptor_set.UpdateDescriptorSets();
4937     m_errorMonitor->VerifyFound();
4938     vkDestroyBuffer(m_device->device(), dynamic_uniform_buffer, NULL);
4939 }
4940 
TEST_F(VkLayerTest,DescriptorSetCompatibility)4941 TEST_F(VkLayerTest, DescriptorSetCompatibility) {
4942     // Test various desriptorSet errors with bad binding combinations
4943     using std::vector;
4944     VkResult err;
4945 
4946     ASSERT_NO_FATAL_FAILURE(Init());
4947     ASSERT_NO_FATAL_FAILURE(InitViewport());
4948     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
4949 
4950     static const uint32_t NUM_DESCRIPTOR_TYPES = 5;
4951     VkDescriptorPoolSize ds_type_count[NUM_DESCRIPTOR_TYPES] = {};
4952     ds_type_count[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
4953     ds_type_count[0].descriptorCount = 10;
4954     ds_type_count[1].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
4955     ds_type_count[1].descriptorCount = 2;
4956     ds_type_count[2].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
4957     ds_type_count[2].descriptorCount = 2;
4958     ds_type_count[3].type = VK_DESCRIPTOR_TYPE_SAMPLER;
4959     ds_type_count[3].descriptorCount = 5;
4960     // TODO : LunarG ILO driver currently asserts in desc.c w/ INPUT_ATTACHMENT
4961     // type
4962     // ds_type_count[4].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
4963     ds_type_count[4].type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
4964     ds_type_count[4].descriptorCount = 2;
4965 
4966     VkDescriptorPoolCreateInfo ds_pool_ci = {};
4967     ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
4968     ds_pool_ci.pNext = NULL;
4969     ds_pool_ci.maxSets = 5;
4970     ds_pool_ci.poolSizeCount = NUM_DESCRIPTOR_TYPES;
4971     ds_pool_ci.pPoolSizes = ds_type_count;
4972 
4973     VkDescriptorPool ds_pool;
4974     err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
4975     ASSERT_VK_SUCCESS(err);
4976 
4977     static const uint32_t MAX_DS_TYPES_IN_LAYOUT = 2;
4978     VkDescriptorSetLayoutBinding dsl_binding[MAX_DS_TYPES_IN_LAYOUT] = {};
4979     dsl_binding[0].binding = 0;
4980     dsl_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
4981     dsl_binding[0].descriptorCount = 5;
4982     dsl_binding[0].stageFlags = VK_SHADER_STAGE_ALL;
4983     dsl_binding[0].pImmutableSamplers = NULL;
4984 
4985     // Create layout identical to set0 layout but w/ different stageFlags
4986     VkDescriptorSetLayoutBinding dsl_fs_stage_only = {};
4987     dsl_fs_stage_only.binding = 0;
4988     dsl_fs_stage_only.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
4989     dsl_fs_stage_only.descriptorCount = 5;
4990     dsl_fs_stage_only.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;  // Different stageFlags to cause error at
4991                                                                   // bind time
4992     dsl_fs_stage_only.pImmutableSamplers = NULL;
4993 
4994     vector<VkDescriptorSetLayoutObj> ds_layouts;
4995     // Create 4 unique layouts for full pipelineLayout, and 1 special fs-only
4996     // layout for error case
4997     ds_layouts.emplace_back(m_device, std::vector<VkDescriptorSetLayoutBinding>(1, dsl_binding[0]));
4998 
4999     const VkDescriptorSetLayoutObj ds_layout_fs_only(m_device, {dsl_fs_stage_only});
5000 
5001     dsl_binding[0].binding = 0;
5002     dsl_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
5003     dsl_binding[0].descriptorCount = 2;
5004     dsl_binding[1].binding = 1;
5005     dsl_binding[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
5006     dsl_binding[1].descriptorCount = 2;
5007     dsl_binding[1].stageFlags = VK_SHADER_STAGE_ALL;
5008     dsl_binding[1].pImmutableSamplers = NULL;
5009     ds_layouts.emplace_back(m_device, std::vector<VkDescriptorSetLayoutBinding>({dsl_binding[0], dsl_binding[1]}));
5010 
5011     dsl_binding[0].binding = 0;
5012     dsl_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
5013     dsl_binding[0].descriptorCount = 5;
5014     ds_layouts.emplace_back(m_device, std::vector<VkDescriptorSetLayoutBinding>(1, dsl_binding[0]));
5015 
5016     dsl_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
5017     dsl_binding[0].descriptorCount = 2;
5018     ds_layouts.emplace_back(m_device, std::vector<VkDescriptorSetLayoutBinding>(1, dsl_binding[0]));
5019 
5020     const auto &ds_vk_layouts = MakeVkHandles<VkDescriptorSetLayout>(ds_layouts);
5021 
5022     static const uint32_t NUM_SETS = 4;
5023     VkDescriptorSet descriptorSet[NUM_SETS] = {};
5024     VkDescriptorSetAllocateInfo alloc_info = {};
5025     alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
5026     alloc_info.descriptorPool = ds_pool;
5027     alloc_info.descriptorSetCount = ds_vk_layouts.size();
5028     alloc_info.pSetLayouts = ds_vk_layouts.data();
5029     err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, descriptorSet);
5030     ASSERT_VK_SUCCESS(err);
5031     VkDescriptorSet ds0_fs_only = {};
5032     alloc_info.descriptorSetCount = 1;
5033     alloc_info.pSetLayouts = &ds_layout_fs_only.handle();
5034     err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, &ds0_fs_only);
5035     ASSERT_VK_SUCCESS(err);
5036 
5037     const VkPipelineLayoutObj pipeline_layout(m_device, {&ds_layouts[0], &ds_layouts[1]});
5038     // Create pipelineLayout with only one setLayout
5039     const VkPipelineLayoutObj single_pipe_layout(m_device, {&ds_layouts[0]});
5040     // Create pipelineLayout with 2 descriptor setLayout at index 0
5041     const VkPipelineLayoutObj pipe_layout_one_desc(m_device, {&ds_layouts[3]});
5042     // Create pipelineLayout with 5 SAMPLER descriptor setLayout at index 0
5043     const VkPipelineLayoutObj pipe_layout_five_samp(m_device, {&ds_layouts[2]});
5044     // Create pipelineLayout with UB type, but stageFlags for FS only
5045     VkPipelineLayoutObj pipe_layout_fs_only(m_device, {&ds_layout_fs_only});
5046     // Create pipelineLayout w/ incompatible set0 layout, but set1 is fine
5047     const VkPipelineLayoutObj pipe_layout_bad_set0(m_device, {&ds_layout_fs_only, &ds_layouts[1]});
5048 
5049     // Add buffer binding for UBO
5050     uint32_t qfi = 0;
5051     VkBufferCreateInfo bci = {};
5052     bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
5053     bci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
5054     bci.size = 8;
5055     bci.queueFamilyIndexCount = 1;
5056     bci.pQueueFamilyIndices = &qfi;
5057     VkBufferObj buffer;
5058     buffer.init(*m_device, bci);
5059     VkDescriptorBufferInfo buffer_info;
5060     buffer_info.buffer = buffer.handle();
5061     buffer_info.offset = 0;
5062     buffer_info.range = VK_WHOLE_SIZE;
5063     VkWriteDescriptorSet descriptor_write = {};
5064     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
5065     descriptor_write.dstSet = descriptorSet[0];
5066     descriptor_write.dstBinding = 0;
5067     descriptor_write.descriptorCount = 1;
5068     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
5069     descriptor_write.pBufferInfo = &buffer_info;
5070     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
5071 
5072     // Create PSO to be used for draw-time errors below
5073     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
5074     VkShaderObj fs(m_device, bindStateFragUniformShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);
5075     VkPipelineObj pipe(m_device);
5076     pipe.AddShader(&vs);
5077     pipe.AddShader(&fs);
5078     pipe.AddDefaultColorAttachment();
5079     pipe.CreateVKPipeline(pipe_layout_fs_only.handle(), renderPass());
5080 
5081     m_commandBuffer->begin();
5082     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
5083 
5084     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
5085     // TODO : Want to cause various binding incompatibility issues here to test
5086     // DrawState
5087     //  First cause various verify_layout_compatibility() fails
5088     //  Second disturb early and late sets and verify INFO msgs
5089     // VerifySetLayoutCompatibility fail cases:
5090     // 1. invalid VkPipelineLayout (layout) passed into vkCmdBindDescriptorSets
5091     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdBindDescriptorSets-layout-parameter");
5092     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS,
5093                             CastToHandle<VkPipelineLayout, uintptr_t>(0xbaadb1be), 0, 1, &descriptorSet[0], 0, NULL);
5094     m_errorMonitor->VerifyFound();
5095 
5096     // 2. layoutIndex exceeds # of layouts in layout
5097     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " attempting to bind set to index 1");
5098     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, single_pipe_layout.handle(), 0, 2,
5099                             &descriptorSet[0], 0, NULL);
5100     m_errorMonitor->VerifyFound();
5101 
5102     // 3. Pipeline setLayout[0] has 2 descriptors, but set being bound has 5
5103     // descriptors
5104     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " has 2 descriptors, but DescriptorSetLayout ");
5105     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_layout_one_desc.handle(), 0, 1,
5106                             &descriptorSet[0], 0, NULL);
5107     m_errorMonitor->VerifyFound();
5108 
5109     // 4. same # of descriptors but mismatch in type
5110     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " is type 'VK_DESCRIPTOR_TYPE_SAMPLER' but binding ");
5111     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_layout_five_samp.handle(), 0, 1,
5112                             &descriptorSet[0], 0, NULL);
5113     m_errorMonitor->VerifyFound();
5114 
5115     // 5. same # of descriptors but mismatch in stageFlags
5116     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
5117                                          " has stageFlags 16 but binding 0 for DescriptorSetLayout ");
5118     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_layout_fs_only.handle(), 0, 1,
5119                             &descriptorSet[0], 0, NULL);
5120     m_errorMonitor->VerifyFound();
5121 
5122     // Now that we're done actively using the pipelineLayout that gfx pipeline
5123     //  was created with, we should be able to delete it. Do that now to verify
5124     //  that validation obeys pipelineLayout lifetime
5125     pipe_layout_fs_only.Reset();
5126 
5127     // Cause draw-time errors due to PSO incompatibilities
5128     // 1. Error due to not binding required set (we actually use same code as
5129     // above to disturb set0)
5130     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 2,
5131                             &descriptorSet[0], 0, NULL);
5132     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe_layout_bad_set0.handle(), 1, 1,
5133                             &descriptorSet[1], 0, NULL);
5134     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " uses set #0 but that set is not bound.");
5135 
5136     VkViewport viewport = {0, 0, 16, 16, 0, 1};
5137     VkRect2D scissor = {{0, 0}, {16, 16}};
5138     vkCmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
5139     vkCmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissor);
5140 
5141     m_commandBuffer->Draw(1, 0, 0, 0);
5142     m_errorMonitor->VerifyFound();
5143 
5144     // 2. Error due to bound set not being compatible with PSO's
5145     // VkPipelineLayout (diff stageFlags in this case)
5146     vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout.handle(), 0, 2,
5147                             &descriptorSet[0], 0, NULL);
5148     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " bound as set #0 is not compatible with ");
5149     m_commandBuffer->Draw(1, 0, 0, 0);
5150     m_errorMonitor->VerifyFound();
5151 
5152     // Remaining clean-up
5153     m_commandBuffer->EndRenderPass();
5154     m_commandBuffer->end();
5155 
5156     vkDestroyDescriptorPool(m_device->device(), ds_pool, NULL);
5157 }
5158 
TEST_F(VkLayerTest,NullRenderPass)5159 TEST_F(VkLayerTest, NullRenderPass) {
5160     // Bind a NULL RenderPass
5161     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
5162                                          "vkCmdBeginRenderPass: required parameter pRenderPassBegin specified as NULL");
5163 
5164     ASSERT_NO_FATAL_FAILURE(Init());
5165     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
5166 
5167     m_commandBuffer->begin();
5168     // Don't care about RenderPass handle b/c error should be flagged before
5169     // that
5170     vkCmdBeginRenderPass(m_commandBuffer->handle(), NULL, VK_SUBPASS_CONTENTS_INLINE);
5171 
5172     m_errorMonitor->VerifyFound();
5173 
5174     m_commandBuffer->end();
5175 }
5176 
TEST_F(VkLayerTest,EndCommandBufferWithinRenderPass)5177 TEST_F(VkLayerTest, EndCommandBufferWithinRenderPass) {
5178     TEST_DESCRIPTION("End a command buffer with an active render pass");
5179 
5180     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkEndCommandBuffer-commandBuffer-00060");
5181 
5182     ASSERT_NO_FATAL_FAILURE(Init());
5183     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
5184 
5185     m_commandBuffer->begin();
5186     m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
5187     vkEndCommandBuffer(m_commandBuffer->handle());
5188 
5189     m_errorMonitor->VerifyFound();
5190 
5191     // End command buffer properly to avoid driver issues. This is safe -- the
5192     // previous vkEndCommandBuffer should not have reached the driver.
5193     m_commandBuffer->EndRenderPass();
5194     m_commandBuffer->end();
5195 
5196     // TODO: Add test for VK_COMMAND_BUFFER_LEVEL_SECONDARY
5197     // TODO: Add test for VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
5198 }
5199 
TEST_F(VkLayerTest,DSUsageBitsErrors)5200 TEST_F(VkLayerTest, DSUsageBitsErrors) {
5201     TEST_DESCRIPTION("Attempt to update descriptor sets for images and buffers that do not have correct usage bits sets.");
5202 
5203     ASSERT_NO_FATAL_FAILURE(Init());
5204 
5205     const VkFormat buffer_format = VK_FORMAT_R8_UNORM;
5206     VkFormatProperties format_properties;
5207     vkGetPhysicalDeviceFormatProperties(gpu(), buffer_format, &format_properties);
5208     if (!(format_properties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)) {
5209         printf("%s Device does not support VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT for this format; skipped.\n", kSkipPrefix);
5210         return;
5211     }
5212 
5213     std::array<VkDescriptorPoolSize, VK_DESCRIPTOR_TYPE_RANGE_SIZE> ds_type_count;
5214     for (uint32_t i = 0; i < ds_type_count.size(); ++i) {
5215         ds_type_count[i].type = VkDescriptorType(i);
5216         ds_type_count[i].descriptorCount = 1;
5217     }
5218 
5219     vk_testing::DescriptorPool ds_pool;
5220     ds_pool.init(*m_device, vk_testing::DescriptorPool::create_info(0, VK_DESCRIPTOR_TYPE_RANGE_SIZE, ds_type_count));
5221     ASSERT_TRUE(ds_pool.initialized());
5222 
5223     std::vector<VkDescriptorSetLayoutBinding> dsl_bindings(1);
5224     dsl_bindings[0].binding = 0;
5225     dsl_bindings[0].descriptorType = VkDescriptorType(0);
5226     dsl_bindings[0].descriptorCount = 1;
5227     dsl_bindings[0].stageFlags = VK_SHADER_STAGE_ALL;
5228     dsl_bindings[0].pImmutableSamplers = NULL;
5229 
5230     // Create arrays of layout and descriptor objects
5231     using UpDescriptorSet = std::unique_ptr<vk_testing::DescriptorSet>;
5232     std::vector<UpDescriptorSet> descriptor_sets;
5233     using UpDescriptorSetLayout = std::unique_ptr<VkDescriptorSetLayoutObj>;
5234     std::vector<UpDescriptorSetLayout> ds_layouts;
5235     descriptor_sets.reserve(VK_DESCRIPTOR_TYPE_RANGE_SIZE);
5236     ds_layouts.reserve(VK_DESCRIPTOR_TYPE_RANGE_SIZE);
5237     for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; ++i) {
5238         dsl_bindings[0].descriptorType = VkDescriptorType(i);
5239         ds_layouts.push_back(UpDescriptorSetLayout(new VkDescriptorSetLayoutObj(m_device, dsl_bindings)));
5240         descriptor_sets.push_back(UpDescriptorSet(ds_pool.alloc_sets(*m_device, *ds_layouts.back())));
5241         ASSERT_TRUE(descriptor_sets.back()->initialized());
5242     }
5243 
5244     // Create a buffer & bufferView to be used for invalid updates
5245     const VkDeviceSize buffer_size = 256;
5246     uint8_t data[buffer_size];
5247     VkConstantBufferObj buffer(m_device, buffer_size, data, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT);
5248     VkConstantBufferObj storage_texel_buffer(m_device, buffer_size, data, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
5249     ASSERT_TRUE(buffer.initialized() && storage_texel_buffer.initialized());
5250 
5251     auto buff_view_ci = vk_testing::BufferView::createInfo(buffer.handle(), VK_FORMAT_R8_UNORM);
5252     vk_testing::BufferView buffer_view_obj, storage_texel_buffer_view_obj;
5253     buffer_view_obj.init(*m_device, buff_view_ci);
5254     buff_view_ci.buffer = storage_texel_buffer.handle();
5255     storage_texel_buffer_view_obj.init(*m_device, buff_view_ci);
5256     ASSERT_TRUE(buffer_view_obj.initialized() && storage_texel_buffer_view_obj.initialized());
5257     VkBufferView buffer_view = buffer_view_obj.handle();
5258     VkBufferView storage_texel_buffer_view = storage_texel_buffer_view_obj.handle();
5259 
5260     // Create an image to be used for invalid updates
5261     VkImageObj image_obj(m_device);
5262     image_obj.InitNoLayout(64, 64, 1, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
5263     ASSERT_TRUE(image_obj.initialized());
5264     VkImageView image_view = image_obj.targetView(VK_FORMAT_R8G8B8A8_UNORM);
5265 
5266     VkDescriptorBufferInfo buff_info = {};
5267     buff_info.buffer = buffer.handle();
5268     VkDescriptorImageInfo img_info = {};
5269     img_info.imageView = image_view;
5270     VkWriteDescriptorSet descriptor_write = {};
5271     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
5272     descriptor_write.dstBinding = 0;
5273     descriptor_write.descriptorCount = 1;
5274     descriptor_write.pTexelBufferView = &buffer_view;
5275     descriptor_write.pBufferInfo = &buff_info;
5276     descriptor_write.pImageInfo = &img_info;
5277 
5278     // These error messages align with VkDescriptorType struct
5279     std::string error_codes[] = {
5280         "UNASSIGNED-CoreValidation-DrawState-InvalidImageView",  // placeholder, no error for SAMPLER descriptor
5281         "UNASSIGNED-CoreValidation-DrawState-InvalidImageView",  // COMBINED_IMAGE_SAMPLER
5282         "UNASSIGNED-CoreValidation-DrawState-InvalidImageView",  // SAMPLED_IMAGE
5283         "UNASSIGNED-CoreValidation-DrawState-InvalidImageView",  // STORAGE_IMAGE
5284         "VUID-VkWriteDescriptorSet-descriptorType-00334",        // UNIFORM_TEXEL_BUFFER
5285         "VUID-VkWriteDescriptorSet-descriptorType-00335",        // STORAGE_TEXEL_BUFFER
5286         "VUID-VkWriteDescriptorSet-descriptorType-00330",        // UNIFORM_BUFFER
5287         "VUID-VkWriteDescriptorSet-descriptorType-00331",        // STORAGE_BUFFER
5288         "VUID-VkWriteDescriptorSet-descriptorType-00330",        // UNIFORM_BUFFER_DYNAMIC
5289         "VUID-VkWriteDescriptorSet-descriptorType-00331",        // STORAGE_BUFFER_DYNAMIC
5290         "UNASSIGNED-CoreValidation-DrawState-InvalidImageView"   // INPUT_ATTACHMENT
5291     };
5292     // Start loop at 1 as SAMPLER desc type has no usage bit error
5293     for (uint32_t i = 1; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; ++i) {
5294         if (VkDescriptorType(i) == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) {
5295             // Now check for UNIFORM_TEXEL_BUFFER using storage_texel_buffer_view
5296             descriptor_write.pTexelBufferView = &storage_texel_buffer_view;
5297         }
5298         descriptor_write.descriptorType = VkDescriptorType(i);
5299         descriptor_write.dstSet = descriptor_sets[i]->handle();
5300         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, error_codes[i]);
5301 
5302         vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
5303 
5304         m_errorMonitor->VerifyFound();
5305         if (VkDescriptorType(i) == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) {
5306             descriptor_write.pTexelBufferView = &buffer_view;
5307         }
5308     }
5309 }
5310 
TEST_F(VkLayerTest,DSBufferInfoErrors)5311 TEST_F(VkLayerTest, DSBufferInfoErrors) {
5312     TEST_DESCRIPTION(
5313         "Attempt to update buffer descriptor set that has incorrect parameters in VkDescriptorBufferInfo struct. This includes:\n"
5314         "1. offset value greater than or equal to buffer size\n"
5315         "2. range value of 0\n"
5316         "3. range value greater than buffer (size - offset)");
5317 
5318     // GPDDP2 needed for push descriptors support below
5319     bool gpdp2_support = InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
5320                                                     VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION);
5321     if (gpdp2_support) {
5322         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
5323     }
5324     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
5325     bool update_template_support = DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME);
5326     if (update_template_support) {
5327         m_device_extension_names.push_back(VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME);
5328     } else {
5329         printf("%s Descriptor Update Template Extensions not supported, template cases skipped.\n", kSkipPrefix);
5330     }
5331 
5332     // Note: Includes workaround for some implementations which incorrectly return 0 maxPushDescriptors
5333     bool push_descriptor_support = gpdp2_support &&
5334                                    DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME) &&
5335                                    (GetPushDescriptorProperties(instance(), gpu()).maxPushDescriptors > 0);
5336     if (push_descriptor_support) {
5337         m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
5338     } else {
5339         printf("%s Push Descriptor Extension not supported, push descriptor cases skipped.\n", kSkipPrefix);
5340     }
5341 
5342     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
5343 
5344     std::vector<VkDescriptorSetLayoutBinding> ds_bindings = {
5345         {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}};
5346     OneOffDescriptorSet descriptor_set(m_device, ds_bindings);
5347 
5348     // Create a buffer to be used for invalid updates
5349     VkBufferCreateInfo buff_ci = {};
5350     buff_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
5351     buff_ci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
5352     buff_ci.size = m_device->props.limits.minUniformBufferOffsetAlignment;
5353     buff_ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
5354     VkBufferObj buffer;
5355     buffer.init(*m_device, buff_ci);
5356 
5357     VkDescriptorBufferInfo buff_info = {};
5358     buff_info.buffer = buffer.handle();
5359     VkWriteDescriptorSet descriptor_write = {};
5360     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
5361     descriptor_write.dstBinding = 0;
5362     descriptor_write.descriptorCount = 1;
5363     descriptor_write.pTexelBufferView = nullptr;
5364     descriptor_write.pBufferInfo = &buff_info;
5365     descriptor_write.pImageInfo = nullptr;
5366 
5367     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
5368     descriptor_write.dstSet = descriptor_set.set_;
5369 
5370     // Relying on the "return nullptr for non-enabled extensions
5371     auto vkCreateDescriptorUpdateTemplateKHR =
5372         (PFN_vkCreateDescriptorUpdateTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkCreateDescriptorUpdateTemplateKHR");
5373     auto vkDestroyDescriptorUpdateTemplateKHR =
5374         (PFN_vkDestroyDescriptorUpdateTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkDestroyDescriptorUpdateTemplateKHR");
5375     auto vkUpdateDescriptorSetWithTemplateKHR =
5376         (PFN_vkUpdateDescriptorSetWithTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkUpdateDescriptorSetWithTemplateKHR");
5377 
5378     if (update_template_support) {
5379         ASSERT_NE(vkCreateDescriptorUpdateTemplateKHR, nullptr);
5380         ASSERT_NE(vkDestroyDescriptorUpdateTemplateKHR, nullptr);
5381         ASSERT_NE(vkUpdateDescriptorSetWithTemplateKHR, nullptr);
5382     }
5383 
5384     // Setup for update w/ template tests
5385     // Create a template of descriptor set updates
5386     struct SimpleTemplateData {
5387         uint8_t padding[7];
5388         VkDescriptorBufferInfo buff_info;
5389         uint32_t other_padding[4];
5390     };
5391     SimpleTemplateData update_template_data = {};
5392 
5393     VkDescriptorUpdateTemplateEntry update_template_entry = {};
5394     update_template_entry.dstBinding = 0;
5395     update_template_entry.dstArrayElement = 0;
5396     update_template_entry.descriptorCount = 1;
5397     update_template_entry.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
5398     update_template_entry.offset = offsetof(SimpleTemplateData, buff_info);
5399     update_template_entry.stride = sizeof(SimpleTemplateData);
5400 
5401     auto update_template_ci = lvl_init_struct<VkDescriptorUpdateTemplateCreateInfoKHR>();
5402     update_template_ci.descriptorUpdateEntryCount = 1;
5403     update_template_ci.pDescriptorUpdateEntries = &update_template_entry;
5404     update_template_ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET;
5405     update_template_ci.descriptorSetLayout = descriptor_set.layout_.handle();
5406 
5407     VkDescriptorUpdateTemplate update_template = VK_NULL_HANDLE;
5408     if (update_template_support) {
5409         auto result = vkCreateDescriptorUpdateTemplateKHR(m_device->device(), &update_template_ci, nullptr, &update_template);
5410         ASSERT_VK_SUCCESS(result);
5411     }
5412 
5413     // VK_KHR_push_descriptor support
5414     auto vkCmdPushDescriptorSetKHR =
5415         (PFN_vkCmdPushDescriptorSetKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdPushDescriptorSetKHR");
5416     auto vkCmdPushDescriptorSetWithTemplateKHR =
5417         (PFN_vkCmdPushDescriptorSetWithTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkCmdPushDescriptorSetWithTemplateKHR");
5418 
5419     std::unique_ptr<VkDescriptorSetLayoutObj> push_dsl = nullptr;
5420     std::unique_ptr<VkPipelineLayoutObj> pipeline_layout = nullptr;
5421     VkDescriptorUpdateTemplate push_template = VK_NULL_HANDLE;
5422     if (push_descriptor_support) {
5423         ASSERT_NE(vkCmdPushDescriptorSetKHR, nullptr);
5424         push_dsl.reset(
5425             new VkDescriptorSetLayoutObj(m_device, ds_bindings, VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR));
5426         pipeline_layout.reset(new VkPipelineLayoutObj(m_device, {push_dsl.get()}));
5427         ASSERT_TRUE(push_dsl->initialized());
5428 
5429         if (update_template_support) {
5430             ASSERT_NE(vkCmdPushDescriptorSetWithTemplateKHR, nullptr);
5431             auto push_template_ci = lvl_init_struct<VkDescriptorUpdateTemplateCreateInfoKHR>();
5432             push_template_ci.descriptorUpdateEntryCount = 1;
5433             push_template_ci.pDescriptorUpdateEntries = &update_template_entry;
5434             push_template_ci.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR;
5435             push_template_ci.descriptorSetLayout = VK_NULL_HANDLE;
5436             push_template_ci.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
5437             push_template_ci.pipelineLayout = pipeline_layout->handle();
5438             push_template_ci.set = 0;
5439             auto result = vkCreateDescriptorUpdateTemplateKHR(m_device->device(), &push_template_ci, nullptr, &push_template);
5440             ASSERT_VK_SUCCESS(result);
5441         }
5442     }
5443 
5444     auto do_test = [&](const char *desired_failure) {
5445         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, desired_failure);
5446         vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
5447         m_errorMonitor->VerifyFound();
5448 
5449         if (push_descriptor_support) {
5450             m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, desired_failure);
5451             m_commandBuffer->begin();
5452             vkCmdPushDescriptorSetKHR(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout->handle(), 0, 1,
5453                                       &descriptor_write);
5454             m_commandBuffer->end();
5455             m_errorMonitor->VerifyFound();
5456         }
5457 
5458         if (update_template_support) {
5459             update_template_data.buff_info = buff_info;  // copy the test case information into our "pData"
5460             m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, desired_failure);
5461             vkUpdateDescriptorSetWithTemplateKHR(m_device->device(), descriptor_set.set_, update_template, &update_template_data);
5462             m_errorMonitor->VerifyFound();
5463             if (push_descriptor_support) {
5464                 m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, desired_failure);
5465                 m_commandBuffer->begin();
5466                 vkCmdPushDescriptorSetWithTemplateKHR(m_commandBuffer->handle(), push_template, pipeline_layout->handle(), 0,
5467                                                       &update_template_data);
5468                 m_commandBuffer->end();
5469                 m_errorMonitor->VerifyFound();
5470             }
5471         }
5472     };
5473 
5474     // Cause error due to offset out of range
5475     buff_info.offset = buff_ci.size;
5476     buff_info.range = VK_WHOLE_SIZE;
5477     do_test("VUID-VkDescriptorBufferInfo-offset-00340");
5478 
5479     // Now cause error due to range of 0
5480     buff_info.offset = 0;
5481     buff_info.range = 0;
5482     do_test("VUID-VkDescriptorBufferInfo-range-00341");
5483 
5484     // Now cause error due to range exceeding buffer size - offset
5485     buff_info.offset = 0;
5486     buff_info.range = buff_ci.size + 1;
5487     do_test("VUID-VkDescriptorBufferInfo-range-00342");
5488 
5489     if (update_template_support) {
5490         vkDestroyDescriptorUpdateTemplateKHR(m_device->device(), update_template, nullptr);
5491         if (push_descriptor_support) {
5492             vkDestroyDescriptorUpdateTemplateKHR(m_device->device(), push_template, nullptr);
5493         }
5494     }
5495 }
5496 
TEST_F(VkLayerTest,DSBufferLimitErrors)5497 TEST_F(VkLayerTest, DSBufferLimitErrors) {
5498     TEST_DESCRIPTION(
5499         "Attempt to update buffer descriptor set that has VkDescriptorBufferInfo values that violate device limits.\n"
5500         "Test cases include:\n"
5501         "1. range of uniform buffer update exceeds maxUniformBufferRange\n"
5502         "2. offset of uniform buffer update is not multiple of minUniformBufferOffsetAlignment\n"
5503         "3. using VK_WHOLE_SIZE with uniform buffer size exceeding maxUniformBufferRange\n"
5504         "4. range of storage buffer update exceeds maxStorageBufferRange\n"
5505         "5. offset of storage buffer update is not multiple of minStorageBufferOffsetAlignment\n"
5506         "6. using VK_WHOLE_SIZE with storage buffer size exceeding maxStorageBufferRange");
5507 
5508     ASSERT_NO_FATAL_FAILURE(Init());
5509 
5510     struct TestCase {
5511         VkDescriptorType descriptor_type;
5512         VkBufferUsageFlagBits buffer_usage;
5513         VkDeviceSize max_range;
5514         std::string max_range_vu;
5515         VkDeviceSize min_align;
5516         std::string min_align_vu;
5517     };
5518 
5519     for (const auto &test_case : {
5520              TestCase({VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
5521                        m_device->props.limits.maxUniformBufferRange, "VUID-VkWriteDescriptorSet-descriptorType-00332",
5522                        m_device->props.limits.minUniformBufferOffsetAlignment, "VUID-VkWriteDescriptorSet-descriptorType-00327"}),
5523              TestCase({VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
5524                        m_device->props.limits.maxStorageBufferRange, "VUID-VkWriteDescriptorSet-descriptorType-00333",
5525                        m_device->props.limits.minStorageBufferOffsetAlignment, "VUID-VkWriteDescriptorSet-descriptorType-00328"}),
5526          }) {
5527         // Create layout with single buffer
5528         OneOffDescriptorSet descriptor_set(m_device, {
5529                                                          {0, test_case.descriptor_type, 1, VK_SHADER_STAGE_ALL, nullptr},
5530                                                      });
5531 
5532         // Create a buffer to be used for invalid updates
5533         VkBufferCreateInfo bci = {};
5534         bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
5535         bci.usage = test_case.buffer_usage;
5536         bci.size = test_case.max_range + test_case.min_align;  // Make buffer bigger than range limit
5537         bci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
5538         VkBuffer buffer;
5539         VkResult err = vkCreateBuffer(m_device->device(), &bci, NULL, &buffer);
5540         ASSERT_VK_SUCCESS(err);
5541 
5542         // Have to bind memory to buffer before descriptor update
5543         VkMemoryRequirements mem_reqs;
5544         vkGetBufferMemoryRequirements(m_device->device(), buffer, &mem_reqs);
5545 
5546         VkMemoryAllocateInfo mem_alloc = {};
5547         mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
5548         mem_alloc.pNext = NULL;
5549         mem_alloc.allocationSize = mem_reqs.size;
5550         bool pass = m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc, 0);
5551         if (!pass) {
5552             printf("%s Failed to allocate memory in DSBufferLimitErrors; skipped.\n", kSkipPrefix);
5553             vkDestroyBuffer(m_device->device(), buffer, NULL);
5554             continue;
5555         }
5556 
5557         VkDeviceMemory mem;
5558         err = vkAllocateMemory(m_device->device(), &mem_alloc, NULL, &mem);
5559         if (VK_SUCCESS != err) {
5560             printf("%s Failed to allocate memory in DSBufferLimitErrors; skipped.\n", kSkipPrefix);
5561             vkDestroyBuffer(m_device->device(), buffer, NULL);
5562             continue;
5563         }
5564         err = vkBindBufferMemory(m_device->device(), buffer, mem, 0);
5565         ASSERT_VK_SUCCESS(err);
5566 
5567         VkDescriptorBufferInfo buff_info = {};
5568         buff_info.buffer = buffer;
5569         VkWriteDescriptorSet descriptor_write = {};
5570         descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
5571         descriptor_write.dstBinding = 0;
5572         descriptor_write.descriptorCount = 1;
5573         descriptor_write.pTexelBufferView = nullptr;
5574         descriptor_write.pBufferInfo = &buff_info;
5575         descriptor_write.pImageInfo = nullptr;
5576         descriptor_write.descriptorType = test_case.descriptor_type;
5577         descriptor_write.dstSet = descriptor_set.set_;
5578 
5579         // Exceed range limit
5580         if (test_case.max_range != UINT32_MAX) {
5581             buff_info.range = test_case.max_range + 1;
5582             buff_info.offset = 0;
5583             m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.max_range_vu);
5584             vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
5585             m_errorMonitor->VerifyFound();
5586         }
5587 
5588         // Reduce size of range to acceptable limit and cause offset error
5589         if (test_case.min_align > 1) {
5590             buff_info.range = test_case.max_range;
5591             buff_info.offset = test_case.min_align - 1;
5592             m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.min_align_vu);
5593             vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
5594             m_errorMonitor->VerifyFound();
5595         }
5596 
5597         // Exceed effective range limit by using VK_WHOLE_SIZE
5598         buff_info.range = VK_WHOLE_SIZE;
5599         buff_info.offset = 0;
5600         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, test_case.max_range_vu);
5601         vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
5602         m_errorMonitor->VerifyFound();
5603 
5604         // Cleanup
5605         vkFreeMemory(m_device->device(), mem, NULL);
5606         vkDestroyBuffer(m_device->device(), buffer, NULL);
5607     }
5608 }
5609 
TEST_F(VkLayerTest,DSAspectBitsErrors)5610 TEST_F(VkLayerTest, DSAspectBitsErrors) {
5611     // TODO : Initially only catching case where DEPTH & STENCIL aspect bits
5612     //  are set, but could expand this test to hit more cases.
5613     TEST_DESCRIPTION("Attempt to update descriptor sets for images that do not have correct aspect bits sets.");
5614     VkResult err;
5615 
5616     ASSERT_NO_FATAL_FAILURE(Init());
5617     auto depth_format = FindSupportedDepthStencilFormat(gpu());
5618     if (!depth_format) {
5619         printf("%s No Depth + Stencil format found. Skipped.\n", kSkipPrefix);
5620         return;
5621     }
5622 
5623     OneOffDescriptorSet descriptor_set(m_device, {
5624                                                      {0, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1, VK_SHADER_STAGE_ALL, nullptr},
5625                                                  });
5626 
5627     // Create an image to be used for invalid updates
5628     VkImageObj image_obj(m_device);
5629     VkFormatProperties fmt_props;
5630     vkGetPhysicalDeviceFormatProperties(m_device->phy().handle(), depth_format, &fmt_props);
5631     if (!image_obj.IsCompatible(VK_IMAGE_USAGE_SAMPLED_BIT, fmt_props.linearTilingFeatures) &&
5632         !image_obj.IsCompatible(VK_IMAGE_USAGE_SAMPLED_BIT, fmt_props.optimalTilingFeatures)) {
5633         printf("%s Depth + Stencil format cannot be sampled. Skipped.\n", kSkipPrefix);
5634         return;
5635     }
5636     image_obj.Init(64, 64, 1, depth_format, VK_IMAGE_USAGE_SAMPLED_BIT);
5637     ASSERT_TRUE(image_obj.initialized());
5638     VkImage image = image_obj.image();
5639 
5640     // Now create view for image
5641     VkImageViewCreateInfo image_view_ci = {};
5642     image_view_ci.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
5643     image_view_ci.image = image;
5644     image_view_ci.format = depth_format;
5645     image_view_ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
5646     image_view_ci.subresourceRange.layerCount = 1;
5647     image_view_ci.subresourceRange.baseArrayLayer = 0;
5648     image_view_ci.subresourceRange.levelCount = 1;
5649     // Setting both depth & stencil aspect bits is illegal for an imageView used
5650     // to populate a descriptor set.
5651     image_view_ci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
5652 
5653     VkImageView image_view;
5654     err = vkCreateImageView(m_device->device(), &image_view_ci, NULL, &image_view);
5655     ASSERT_VK_SUCCESS(err);
5656     descriptor_set.WriteDescriptorImageInfo(0, image_view, VK_NULL_HANDLE, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT);
5657 
5658     const char *error_msg = "VUID-VkDescriptorImageInfo-imageView-01976";
5659     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, error_msg);
5660     descriptor_set.UpdateDescriptorSets();
5661     m_errorMonitor->VerifyFound();
5662     vkDestroyImageView(m_device->device(), image_view, NULL);
5663 }
5664 
TEST_F(VkLayerTest,DSTypeMismatch)5665 TEST_F(VkLayerTest, DSTypeMismatch) {
5666     // Create DS w/ layout of one type and attempt Update w/ mis-matched type
5667     VkResult err;
5668 
5669     m_errorMonitor->SetDesiredFailureMsg(
5670         VK_DEBUG_REPORT_ERROR_BIT_EXT,
5671         " binding #0 with type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER but update type is VK_DESCRIPTOR_TYPE_SAMPLER");
5672 
5673     ASSERT_NO_FATAL_FAILURE(Init());
5674     OneOffDescriptorSet descriptor_set(m_device, {
5675                                                      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
5676                                                  });
5677 
5678     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
5679     VkSampler sampler;
5680     err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler);
5681     ASSERT_VK_SUCCESS(err);
5682 
5683     descriptor_set.WriteDescriptorImageInfo(0, VK_NULL_HANDLE, sampler, VK_DESCRIPTOR_TYPE_SAMPLER);
5684     descriptor_set.UpdateDescriptorSets();
5685 
5686     m_errorMonitor->VerifyFound();
5687 
5688     vkDestroySampler(m_device->device(), sampler, NULL);
5689 }
5690 
TEST_F(VkLayerTest,DSUpdateOutOfBounds)5691 TEST_F(VkLayerTest, DSUpdateOutOfBounds) {
5692     // For overlapping Update, have arrayIndex exceed that of layout
5693     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-dstArrayElement-00321");
5694 
5695     ASSERT_NO_FATAL_FAILURE(Init());
5696     OneOffDescriptorSet descriptor_set(m_device, {
5697                                                      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
5698                                                  });
5699 
5700     VkBufferTest buffer_test(m_device, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
5701     if (!buffer_test.GetBufferCurrent()) {
5702         // Something prevented creation of buffer so abort
5703         printf("%s Buffer creation failed, skipping test\n", kSkipPrefix);
5704         return;
5705     }
5706 
5707     // Correctly update descriptor to avoid "NOT_UPDATED" error
5708     VkDescriptorBufferInfo buff_info = {};
5709     buff_info.buffer = buffer_test.GetBuffer();
5710     buff_info.offset = 0;
5711     buff_info.range = 1024;
5712 
5713     VkWriteDescriptorSet descriptor_write;
5714     memset(&descriptor_write, 0, sizeof(descriptor_write));
5715     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
5716     descriptor_write.dstSet = descriptor_set.set_;
5717     descriptor_write.dstArrayElement = 1; /* This index out of bounds for the update */
5718     descriptor_write.descriptorCount = 1;
5719     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
5720     descriptor_write.pBufferInfo = &buff_info;
5721 
5722     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
5723 
5724     m_errorMonitor->VerifyFound();
5725 }
5726 
TEST_F(VkLayerTest,InvalidDSUpdateIndex)5727 TEST_F(VkLayerTest, InvalidDSUpdateIndex) {
5728     // Create layout w/ count of 1 and attempt update to that layout w/ binding index 2
5729     VkResult err;
5730 
5731     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-dstBinding-00315");
5732 
5733     ASSERT_NO_FATAL_FAILURE(Init());
5734     OneOffDescriptorSet descriptor_set(m_device, {
5735                                                      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
5736                                                  });
5737 
5738     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
5739     VkSampler sampler;
5740     err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler);
5741     ASSERT_VK_SUCCESS(err);
5742 
5743     // This is the wrong type, but out of bounds will be flagged first
5744     descriptor_set.WriteDescriptorImageInfo(2, VK_NULL_HANDLE, sampler, VK_DESCRIPTOR_TYPE_SAMPLER);
5745     descriptor_set.UpdateDescriptorSets();
5746     m_errorMonitor->VerifyFound();
5747 
5748     vkDestroySampler(m_device->device(), sampler, NULL);
5749 }
5750 
TEST_F(VkLayerTest,DSUpdateEmptyBinding)5751 TEST_F(VkLayerTest, DSUpdateEmptyBinding) {
5752     // Create layout w/ empty binding and attempt to update it
5753     VkResult err;
5754 
5755     ASSERT_NO_FATAL_FAILURE(Init());
5756 
5757     OneOffDescriptorSet descriptor_set(m_device, {
5758                                                      {0, VK_DESCRIPTOR_TYPE_SAMPLER, 0 /* !! */, VK_SHADER_STAGE_ALL, nullptr},
5759                                                  });
5760 
5761     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
5762     VkSampler sampler;
5763     err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler);
5764     ASSERT_VK_SUCCESS(err);
5765 
5766     // descriptor_write.descriptorCount = 1, Lie here to avoid parameter_validation error
5767     // This is the wrong type, but empty binding error will be flagged first
5768     descriptor_set.WriteDescriptorImageInfo(0, VK_NULL_HANDLE, sampler, VK_DESCRIPTOR_TYPE_SAMPLER);
5769 
5770     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-dstBinding-00316");
5771     descriptor_set.UpdateDescriptorSets();
5772     m_errorMonitor->VerifyFound();
5773 
5774     vkDestroySampler(m_device->device(), sampler, NULL);
5775 }
5776 
TEST_F(VkLayerTest,InvalidDSUpdateStruct)5777 TEST_F(VkLayerTest, InvalidDSUpdateStruct) {
5778     // Call UpdateDS w/ struct type other than valid VK_STRUCTUR_TYPE_UPDATE_*
5779     // types
5780     VkResult err;
5781 
5782     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, ".sType must be VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET");
5783 
5784     ASSERT_NO_FATAL_FAILURE(Init());
5785 
5786     OneOffDescriptorSet descriptor_set(m_device, {
5787                                                      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
5788                                                  });
5789 
5790     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
5791     VkSampler sampler;
5792     err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler);
5793     ASSERT_VK_SUCCESS(err);
5794 
5795     VkDescriptorImageInfo info = {};
5796     info.sampler = sampler;
5797 
5798     VkWriteDescriptorSet descriptor_write;
5799     memset(&descriptor_write, 0, sizeof(descriptor_write));
5800     descriptor_write.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; /* Intentionally broken struct type */
5801     descriptor_write.dstSet = descriptor_set.set_;
5802     descriptor_write.descriptorCount = 1;
5803     // This is the wrong type, but out of bounds will be flagged first
5804     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
5805     descriptor_write.pImageInfo = &info;
5806 
5807     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
5808 
5809     m_errorMonitor->VerifyFound();
5810 
5811     vkDestroySampler(m_device->device(), sampler, NULL);
5812 }
5813 
TEST_F(VkLayerTest,SampleDescriptorUpdateError)5814 TEST_F(VkLayerTest, SampleDescriptorUpdateError) {
5815     // Create a single Sampler descriptor and send it an invalid Sampler
5816     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-00325");
5817 
5818     ASSERT_NO_FATAL_FAILURE(Init());
5819     OneOffDescriptorSet descriptor_set(m_device, {
5820                                                      {0, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr},
5821                                                  });
5822 
5823     VkSampler sampler = CastToHandle<VkSampler, uintptr_t>(0xbaadbeef);  // Sampler with invalid handle
5824 
5825     descriptor_set.WriteDescriptorImageInfo(0, VK_NULL_HANDLE, sampler, VK_DESCRIPTOR_TYPE_SAMPLER);
5826     descriptor_set.UpdateDescriptorSets();
5827     m_errorMonitor->VerifyFound();
5828 }
5829 
TEST_F(VkLayerTest,ImageViewDescriptorUpdateError)5830 TEST_F(VkLayerTest, ImageViewDescriptorUpdateError) {
5831     // Create a single combined Image/Sampler descriptor and send it an invalid
5832     // imageView
5833     VkResult err;
5834 
5835     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-00326");
5836 
5837     ASSERT_NO_FATAL_FAILURE(Init());
5838     OneOffDescriptorSet descriptor_set(m_device,
5839                                        {
5840                                            {0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr},
5841                                        });
5842 
5843     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
5844     VkSampler sampler;
5845     err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler);
5846     ASSERT_VK_SUCCESS(err);
5847 
5848     VkImageView view = CastToHandle<VkImageView, uintptr_t>(0xbaadbeef);  // invalid imageView object
5849 
5850     descriptor_set.WriteDescriptorImageInfo(0, view, sampler, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
5851     descriptor_set.UpdateDescriptorSets();
5852     m_errorMonitor->VerifyFound();
5853 
5854     vkDestroySampler(m_device->device(), sampler, NULL);
5855 }
5856 
TEST_F(VkLayerTest,CopyDescriptorUpdateErrors)5857 TEST_F(VkLayerTest, CopyDescriptorUpdateErrors) {
5858     // Create DS w/ layout of 2 types, write update 1 and attempt to copy-update
5859     // into the other
5860     VkResult err;
5861 
5862     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
5863                                          " binding #1 with type VK_DESCRIPTOR_TYPE_SAMPLER. Types do not match.");
5864 
5865     ASSERT_NO_FATAL_FAILURE(Init());
5866     OneOffDescriptorSet descriptor_set(m_device, {
5867                                                      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
5868                                                      {1, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_ALL, nullptr},
5869                                                  });
5870 
5871     VkSamplerCreateInfo sampler_ci = SafeSaneSamplerCreateInfo();
5872     VkSampler sampler;
5873     err = vkCreateSampler(m_device->device(), &sampler_ci, NULL, &sampler);
5874     ASSERT_VK_SUCCESS(err);
5875 
5876     // SAMPLER binding from layout above
5877     // This write update should succeed
5878     descriptor_set.WriteDescriptorImageInfo(1, VK_NULL_HANDLE, sampler, VK_DESCRIPTOR_TYPE_SAMPLER);
5879     descriptor_set.UpdateDescriptorSets();
5880     // Now perform a copy update that fails due to type mismatch
5881     VkCopyDescriptorSet copy_ds_update;
5882     memset(&copy_ds_update, 0, sizeof(VkCopyDescriptorSet));
5883     copy_ds_update.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
5884     copy_ds_update.srcSet = descriptor_set.set_;
5885     copy_ds_update.srcBinding = 1;  // Copy from SAMPLER binding
5886     copy_ds_update.dstSet = descriptor_set.set_;
5887     copy_ds_update.dstBinding = 0;       // ERROR : copy to UNIFORM binding
5888     copy_ds_update.descriptorCount = 1;  // copy 1 descriptor
5889     vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, &copy_ds_update);
5890 
5891     m_errorMonitor->VerifyFound();
5892     // Now perform a copy update that fails due to binding out of bounds
5893     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, " does not have copy update src binding of 3.");
5894     memset(&copy_ds_update, 0, sizeof(VkCopyDescriptorSet));
5895     copy_ds_update.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
5896     copy_ds_update.srcSet = descriptor_set.set_;
5897     copy_ds_update.srcBinding = 3;  // ERROR : Invalid binding for matching layout
5898     copy_ds_update.dstSet = descriptor_set.set_;
5899     copy_ds_update.dstBinding = 0;
5900     copy_ds_update.descriptorCount = 1;  // Copy 1 descriptor
5901     vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, &copy_ds_update);
5902 
5903     m_errorMonitor->VerifyFound();
5904 
5905     // Now perform a copy update that fails due to binding out of bounds
5906     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
5907                                          " binding#1 with offset index of 1 plus update array offset of 0 and update of 5 "
5908                                          "descriptors oversteps total number of descriptors in set: 2.");
5909 
5910     memset(&copy_ds_update, 0, sizeof(VkCopyDescriptorSet));
5911     copy_ds_update.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
5912     copy_ds_update.srcSet = descriptor_set.set_;
5913     copy_ds_update.srcBinding = 1;
5914     copy_ds_update.dstSet = descriptor_set.set_;
5915     copy_ds_update.dstBinding = 0;
5916     copy_ds_update.descriptorCount = 5;  // ERROR copy 5 descriptors (out of bounds for layout)
5917     vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, &copy_ds_update);
5918 
5919     m_errorMonitor->VerifyFound();
5920 
5921     vkDestroySampler(m_device->device(), sampler, NULL);
5922 }
5923 
TEST_F(VkLayerTest,DrawWithPipelineIncompatibleWithRenderPass)5924 TEST_F(VkLayerTest, DrawWithPipelineIncompatibleWithRenderPass) {
5925     TEST_DESCRIPTION(
5926         "Hit RenderPass incompatible cases. Initial case is drawing with an active renderpass that's not compatible with the bound "
5927         "pipeline state object's creation renderpass");
5928 
5929     ASSERT_NO_FATAL_FAILURE(Init());
5930     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
5931 
5932     OneOffDescriptorSet descriptor_set(m_device, {
5933                                                      {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
5934                                                  });
5935 
5936     const VkPipelineLayoutObj pipeline_layout(m_device, {&descriptor_set.layout_});
5937 
5938     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
5939     VkShaderObj fs(m_device, bindStateFragShaderText, VK_SHADER_STAGE_FRAGMENT_BIT, this);  // We shouldn't need a fragment shader
5940     // but add it to be able to run on more devices
5941     // Create a renderpass that will be incompatible with default renderpass
5942     VkAttachmentReference color_att = {};
5943     color_att.layout = VK_IMAGE_LAYOUT_GENERAL;
5944     VkSubpassDescription subpass = {};
5945     subpass.colorAttachmentCount = 1;
5946     subpass.pColorAttachments = &color_att;
5947     VkRenderPassCreateInfo rpci = {};
5948     rpci.subpassCount = 1;
5949     rpci.pSubpasses = &subpass;
5950     rpci.attachmentCount = 1;
5951     VkAttachmentDescription attach_desc = {};
5952     attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
5953     // Format incompatible with PSO RP color attach format B8G8R8A8_UNORM
5954     attach_desc.format = VK_FORMAT_R8G8B8A8_UNORM;
5955     attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
5956     rpci.pAttachments = &attach_desc;
5957     rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
5958     VkRenderPass rp;
5959     vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp);
5960     VkPipelineObj pipe(m_device);
5961     pipe.AddShader(&vs);
5962     pipe.AddShader(&fs);
5963     pipe.AddDefaultColorAttachment();
5964     VkViewport viewport = {0.0f, 0.0f, 64.0f, 64.0f, 0.0f, 1.0f};
5965     m_viewports.push_back(viewport);
5966     pipe.SetViewport(m_viewports);
5967     VkRect2D rect = {{0, 0}, {64, 64}};
5968     m_scissors.push_back(rect);
5969     pipe.SetScissor(m_scissors);
5970     pipe.CreateVKPipeline(pipeline_layout.handle(), rp);
5971 
5972     VkCommandBufferInheritanceInfo cbii = {};
5973     cbii.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
5974     cbii.renderPass = rp;
5975     cbii.subpass = 0;
5976     VkCommandBufferBeginInfo cbbi = {};
5977     cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
5978     cbbi.pInheritanceInfo = &cbii;
5979     vkBeginCommandBuffer(m_commandBuffer->handle(), &cbbi);
5980     vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
5981     vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
5982 
5983     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdDraw-renderPass-02684");
5984     // Render triangle (the error should trigger on the attempt to draw).
5985     m_commandBuffer->Draw(3, 1, 0, 0);
5986 
5987     // Finalize recording of the command buffer
5988     m_commandBuffer->EndRenderPass();
5989     m_commandBuffer->end();
5990 
5991     m_errorMonitor->VerifyFound();
5992 
5993     vkDestroyRenderPass(m_device->device(), rp, NULL);
5994 }
5995 
TEST_F(VkLayerTest,Maint1BindingSliceOf3DImage)5996 TEST_F(VkLayerTest, Maint1BindingSliceOf3DImage) {
5997     TEST_DESCRIPTION(
5998         "Attempt to bind a slice of a 3D texture in a descriptor set. This is explicitly disallowed by KHR_maintenance1 to keep "
5999         "things simple for drivers.");
6000     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
6001     if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE1_EXTENSION_NAME)) {
6002         m_device_extension_names.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
6003     } else {
6004         printf("%s %s is not supported; skipping\n", kSkipPrefix, VK_KHR_MAINTENANCE1_EXTENSION_NAME);
6005         return;
6006     }
6007     ASSERT_NO_FATAL_FAILURE(InitState());
6008 
6009     VkResult err;
6010 
6011     OneOffDescriptorSet descriptor_set(m_device,
6012                                        {
6013                                            {0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr},
6014                                        });
6015 
6016     VkImageCreateInfo ici = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
6017                              nullptr,
6018                              VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR,
6019                              VK_IMAGE_TYPE_3D,
6020                              VK_FORMAT_R8G8B8A8_UNORM,
6021                              {32, 32, 32},
6022                              1,
6023                              1,
6024                              VK_SAMPLE_COUNT_1_BIT,
6025                              VK_IMAGE_TILING_OPTIMAL,
6026                              VK_IMAGE_USAGE_SAMPLED_BIT,
6027                              VK_SHARING_MODE_EXCLUSIVE,
6028                              0,
6029                              nullptr,
6030                              VK_IMAGE_LAYOUT_UNDEFINED};
6031     VkImageObj image(m_device);
6032     image.init(&ici);
6033     ASSERT_TRUE(image.initialized());
6034 
6035     VkImageViewCreateInfo ivci = {
6036         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
6037         nullptr,
6038         0,
6039         image.handle(),
6040         VK_IMAGE_VIEW_TYPE_2D,
6041         VK_FORMAT_R8G8B8A8_UNORM,
6042         {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
6043          VK_COMPONENT_SWIZZLE_IDENTITY},
6044         {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
6045     };
6046     VkImageView view;
6047     err = vkCreateImageView(m_device->device(), &ivci, nullptr, &view);
6048     ASSERT_VK_SUCCESS(err);
6049 
6050     // Meat of the test.
6051     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorImageInfo-imageView-00343");
6052 
6053     VkDescriptorImageInfo dii = {VK_NULL_HANDLE, view, VK_IMAGE_LAYOUT_GENERAL};
6054     VkWriteDescriptorSet write = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
6055                                   nullptr,
6056                                   descriptor_set.set_,
6057                                   0,
6058                                   0,
6059                                   1,
6060                                   VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
6061                                   &dii,
6062                                   nullptr,
6063                                   nullptr};
6064     vkUpdateDescriptorSets(m_device->device(), 1, &write, 0, nullptr);
6065 
6066     m_errorMonitor->VerifyFound();
6067 
6068     vkDestroyImageView(m_device->device(), view, nullptr);
6069 }
6070 
TEST_F(VkLayerTest,UpdateDestroyDescriptorSetLayout)6071 TEST_F(VkLayerTest, UpdateDestroyDescriptorSetLayout) {
6072     TEST_DESCRIPTION("Attempt updates to descriptor sets with destroyed descriptor set layouts");
6073     // TODO: Update to match the descriptor set layout specific VUIDs/VALIDATION_ERROR_* when present
6074     const auto kWriteDestroyedLayout = "VUID-VkWriteDescriptorSet-dstSet-00320";
6075     const auto kCopyDstDestroyedLayout = "VUID-VkCopyDescriptorSet-dstSet-parameter";
6076     const auto kCopySrcDestroyedLayout = "VUID-VkCopyDescriptorSet-srcSet-parameter";
6077 
6078     ASSERT_NO_FATAL_FAILURE(Init());
6079 
6080     // Set up the descriptor (resource) and write/copy operations to use.
6081     float data[16] = {};
6082     VkConstantBufferObj buffer(m_device, sizeof(data), data, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
6083     ASSERT_TRUE(buffer.initialized());
6084 
6085     VkDescriptorBufferInfo info = {};
6086     info.buffer = buffer.handle();
6087     info.range = VK_WHOLE_SIZE;
6088 
6089     VkWriteDescriptorSet write_descriptor = {};
6090     write_descriptor.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
6091     write_descriptor.dstSet = VK_NULL_HANDLE;  // must update this
6092     write_descriptor.dstBinding = 0;
6093     write_descriptor.descriptorCount = 1;
6094     write_descriptor.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
6095     write_descriptor.pBufferInfo = &info;
6096 
6097     VkCopyDescriptorSet copy_descriptor = {};
6098     copy_descriptor.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
6099     copy_descriptor.srcSet = VK_NULL_HANDLE;  // must update
6100     copy_descriptor.srcBinding = 0;
6101     copy_descriptor.dstSet = VK_NULL_HANDLE;  // must update
6102     copy_descriptor.dstBinding = 0;
6103     copy_descriptor.descriptorCount = 1;
6104 
6105     // Create valid and invalid source and destination descriptor sets
6106     std::vector<VkDescriptorSetLayoutBinding> one_uniform_buffer = {
6107         {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr},
6108     };
6109     OneOffDescriptorSet good_dst(m_device, one_uniform_buffer);
6110     ASSERT_TRUE(good_dst.Initialized());
6111 
6112     OneOffDescriptorSet bad_dst(m_device, one_uniform_buffer);
6113     // Must assert before invalidating it below
6114     ASSERT_TRUE(bad_dst.Initialized());
6115     bad_dst.layout_ = VkDescriptorSetLayoutObj();
6116 
6117     OneOffDescriptorSet good_src(m_device, one_uniform_buffer);
6118     ASSERT_TRUE(good_src.Initialized());
6119 
6120     // Put valid data in the good and bad sources, simultaneously doing a positive test on write and copy operations
6121     m_errorMonitor->ExpectSuccess();
6122     write_descriptor.dstSet = good_src.set_;
6123     vkUpdateDescriptorSets(m_device->device(), 1, &write_descriptor, 0, NULL);
6124     m_errorMonitor->VerifyNotFound();
6125 
6126     OneOffDescriptorSet bad_src(m_device, one_uniform_buffer);
6127     ASSERT_TRUE(bad_src.Initialized());
6128 
6129     // to complete our positive testing use copy, where above we used write.
6130     copy_descriptor.srcSet = good_src.set_;
6131     copy_descriptor.dstSet = bad_src.set_;
6132     vkUpdateDescriptorSets(m_device->device(), 0, nullptr, 1, &copy_descriptor);
6133     bad_src.layout_ = VkDescriptorSetLayoutObj();
6134     m_errorMonitor->VerifyNotFound();
6135 
6136     // Trigger the three invalid use errors
6137     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, kWriteDestroyedLayout);
6138     write_descriptor.dstSet = bad_dst.set_;
6139     vkUpdateDescriptorSets(m_device->device(), 1, &write_descriptor, 0, NULL);
6140     m_errorMonitor->VerifyFound();
6141 
6142     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, kCopyDstDestroyedLayout);
6143     copy_descriptor.dstSet = bad_dst.set_;
6144     vkUpdateDescriptorSets(m_device->device(), 0, nullptr, 1, &copy_descriptor);
6145     m_errorMonitor->VerifyFound();
6146 
6147     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, kCopySrcDestroyedLayout);
6148     copy_descriptor.srcSet = bad_src.set_;
6149     copy_descriptor.dstSet = good_dst.set_;
6150     vkUpdateDescriptorSets(m_device->device(), 0, nullptr, 1, &copy_descriptor);
6151     m_errorMonitor->VerifyFound();
6152 }
6153 
TEST_F(VkLayerTest,FramebufferIncompatible)6154 TEST_F(VkLayerTest, FramebufferIncompatible) {
6155     TEST_DESCRIPTION(
6156         "Bind a secondary command buffer with a framebuffer that does not match the framebuffer for the active renderpass.");
6157     ASSERT_NO_FATAL_FAILURE(Init());
6158     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
6159 
6160     // A renderpass with one color attachment.
6161     VkAttachmentDescription attachment = {0,
6162                                           VK_FORMAT_B8G8R8A8_UNORM,
6163                                           VK_SAMPLE_COUNT_1_BIT,
6164                                           VK_ATTACHMENT_LOAD_OP_DONT_CARE,
6165                                           VK_ATTACHMENT_STORE_OP_STORE,
6166                                           VK_ATTACHMENT_LOAD_OP_DONT_CARE,
6167                                           VK_ATTACHMENT_STORE_OP_DONT_CARE,
6168                                           VK_IMAGE_LAYOUT_UNDEFINED,
6169                                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
6170 
6171     VkAttachmentReference att_ref = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
6172 
6173     VkSubpassDescription subpass = {0, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, nullptr, 1, &att_ref, nullptr, nullptr, 0, nullptr};
6174 
6175     VkRenderPassCreateInfo rpci = {VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, nullptr, 0, 1, &attachment, 1, &subpass, 0, nullptr};
6176 
6177     VkRenderPass rp;
6178     VkResult err = vkCreateRenderPass(m_device->device(), &rpci, nullptr, &rp);
6179     ASSERT_VK_SUCCESS(err);
6180 
6181     // A compatible framebuffer.
6182     VkImageObj image(m_device);
6183     image.Init(32, 32, 1, VK_FORMAT_B8G8R8A8_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_TILING_OPTIMAL, 0);
6184     ASSERT_TRUE(image.initialized());
6185 
6186     VkImageViewCreateInfo ivci = {
6187         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
6188         nullptr,
6189         0,
6190         image.handle(),
6191         VK_IMAGE_VIEW_TYPE_2D,
6192         VK_FORMAT_B8G8R8A8_UNORM,
6193         {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
6194          VK_COMPONENT_SWIZZLE_IDENTITY},
6195         {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1},
6196     };
6197     VkImageView view;
6198     err = vkCreateImageView(m_device->device(), &ivci, nullptr, &view);
6199     ASSERT_VK_SUCCESS(err);
6200 
6201     VkFramebufferCreateInfo fci = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, nullptr, 0, rp, 1, &view, 32, 32, 1};
6202     VkFramebuffer fb;
6203     err = vkCreateFramebuffer(m_device->device(), &fci, nullptr, &fb);
6204     ASSERT_VK_SUCCESS(err);
6205 
6206     VkCommandBufferAllocateInfo cbai = {};
6207     cbai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
6208     cbai.commandPool = m_commandPool->handle();
6209     cbai.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
6210     cbai.commandBufferCount = 1;
6211 
6212     VkCommandBuffer sec_cb;
6213     err = vkAllocateCommandBuffers(m_device->device(), &cbai, &sec_cb);
6214     ASSERT_VK_SUCCESS(err);
6215     VkCommandBufferBeginInfo cbbi = {};
6216     VkCommandBufferInheritanceInfo cbii = {};
6217     cbii.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
6218     cbii.renderPass = renderPass();
6219     cbii.framebuffer = fb;
6220     cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
6221     cbbi.pNext = NULL;
6222     cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
6223     cbbi.pInheritanceInfo = &cbii;
6224     vkBeginCommandBuffer(sec_cb, &cbbi);
6225     vkEndCommandBuffer(sec_cb);
6226 
6227     VkCommandBufferBeginInfo cbbi2 = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, 0, nullptr};
6228     vkBeginCommandBuffer(m_commandBuffer->handle(), &cbbi2);
6229     vkCmdBeginRenderPass(m_commandBuffer->handle(), &m_renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
6230 
6231     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-vkCmdExecuteCommands-pCommandBuffers-00099");
6232     vkCmdExecuteCommands(m_commandBuffer->handle(), 1, &sec_cb);
6233     m_errorMonitor->VerifyFound();
6234     // Cleanup
6235 
6236     vkCmdEndRenderPass(m_commandBuffer->handle());
6237     vkEndCommandBuffer(m_commandBuffer->handle());
6238 
6239     vkDestroyImageView(m_device->device(), view, NULL);
6240     vkDestroyRenderPass(m_device->device(), rp, NULL);
6241     vkDestroyFramebuffer(m_device->device(), fb, NULL);
6242 }
6243 
TEST_F(VkLayerTest,RenderPassMissingAttachment)6244 TEST_F(VkLayerTest, RenderPassMissingAttachment) {
6245     TEST_DESCRIPTION("Begin render pass with missing framebuffer attachment");
6246     ASSERT_NO_FATAL_FAILURE(Init());
6247     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
6248 
6249     // Create a renderPass with a single color attachment
6250     VkAttachmentReference attach = {};
6251     attach.layout = VK_IMAGE_LAYOUT_GENERAL;
6252     VkSubpassDescription subpass = {};
6253     subpass.pColorAttachments = &attach;
6254     VkRenderPassCreateInfo rpci = {};
6255     rpci.subpassCount = 1;
6256     rpci.pSubpasses = &subpass;
6257     rpci.attachmentCount = 1;
6258     VkAttachmentDescription attach_desc = {};
6259     attach_desc.format = VK_FORMAT_B8G8R8A8_UNORM;
6260     attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
6261     attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
6262     rpci.pAttachments = &attach_desc;
6263     rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
6264     VkRenderPass rp;
6265     VkResult err = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp);
6266     ASSERT_VK_SUCCESS(err);
6267 
6268     auto createView = lvl_init_struct<VkImageViewCreateInfo>();
6269     createView.image = m_renderTargets[0]->handle();
6270     createView.viewType = VK_IMAGE_VIEW_TYPE_2D;
6271     createView.format = VK_FORMAT_B8G8R8A8_UNORM;
6272     createView.components.r = VK_COMPONENT_SWIZZLE_R;
6273     createView.components.g = VK_COMPONENT_SWIZZLE_G;
6274     createView.components.b = VK_COMPONENT_SWIZZLE_B;
6275     createView.components.a = VK_COMPONENT_SWIZZLE_A;
6276     createView.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
6277     createView.flags = 0;
6278 
6279     VkImageView iv;
6280     vkCreateImageView(m_device->handle(), &createView, nullptr, &iv);
6281 
6282     auto fb_info = lvl_init_struct<VkFramebufferCreateInfo>();
6283     fb_info.renderPass = rp;
6284     fb_info.attachmentCount = 1;
6285     fb_info.pAttachments = &iv;
6286     fb_info.width = 100;
6287     fb_info.height = 100;
6288     fb_info.layers = 1;
6289 
6290     // Create the framebuffer then destory the view it uses.
6291     VkFramebuffer fb;
6292     err = vkCreateFramebuffer(device(), &fb_info, NULL, &fb);
6293     vkDestroyImageView(device(), iv, NULL);
6294     ASSERT_VK_SUCCESS(err);
6295 
6296     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkRenderPassBeginInfo-framebuffer-parameter");
6297 
6298     auto rpbi = lvl_init_struct<VkRenderPassBeginInfo>();
6299     rpbi.renderPass = rp;
6300     rpbi.framebuffer = fb;
6301     rpbi.renderArea = {{0, 0}, {32, 32}};
6302 
6303     m_commandBuffer->begin();
6304     vkCmdBeginRenderPass(m_commandBuffer->handle(), &rpbi, VK_SUBPASS_CONTENTS_INLINE);
6305     // Don't call vkCmdEndRenderPass; as the begin has been "skipped" based on the error condition
6306     m_errorMonitor->VerifyFound();
6307     m_commandBuffer->end();
6308 
6309     vkDestroyFramebuffer(m_device->device(), fb, NULL);
6310     vkDestroyRenderPass(m_device->device(), rp, NULL);
6311 }
6312 
TEST_F(VkLayerTest,AttachmentDescriptionUndefinedFormat)6313 TEST_F(VkLayerTest, AttachmentDescriptionUndefinedFormat) {
6314     TEST_DESCRIPTION("Create a render pass with an attachment description format set to VK_FORMAT_UNDEFINED");
6315 
6316     ASSERT_NO_FATAL_FAILURE(Init());
6317     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
6318 
6319     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_WARNING_BIT_EXT, "format is VK_FORMAT_UNDEFINED");
6320 
6321     VkAttachmentReference color_attach = {};
6322     color_attach.layout = VK_IMAGE_LAYOUT_GENERAL;
6323     color_attach.attachment = 0;
6324     VkSubpassDescription subpass = {};
6325     subpass.colorAttachmentCount = 1;
6326     subpass.pColorAttachments = &color_attach;
6327 
6328     VkRenderPassCreateInfo rpci = {};
6329     rpci.subpassCount = 1;
6330     rpci.pSubpasses = &subpass;
6331     rpci.attachmentCount = 1;
6332     VkAttachmentDescription attach_desc = {};
6333     attach_desc.format = VK_FORMAT_UNDEFINED;
6334     attach_desc.samples = VK_SAMPLE_COUNT_1_BIT;
6335     attach_desc.finalLayout = VK_IMAGE_LAYOUT_GENERAL;
6336     rpci.pAttachments = &attach_desc;
6337     rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
6338     VkRenderPass rp;
6339     VkResult result = vkCreateRenderPass(m_device->device(), &rpci, NULL, &rp);
6340 
6341     m_errorMonitor->VerifyFound();
6342 
6343     if (result == VK_SUCCESS) {
6344         vkDestroyRenderPass(m_device->device(), rp, NULL);
6345     }
6346 }
6347 
TEST_F(VkLayerTest,InvalidCreateDescriptorPool)6348 TEST_F(VkLayerTest, InvalidCreateDescriptorPool) {
6349     TEST_DESCRIPTION("Attempt to create descriptor pool with invalid parameters");
6350 
6351     ASSERT_NO_FATAL_FAILURE(Init());
6352 
6353     const uint32_t default_descriptor_count = 1;
6354     const VkDescriptorPoolSize dp_size_template{VK_DESCRIPTOR_TYPE_SAMPLER, default_descriptor_count};
6355 
6356     const VkDescriptorPoolCreateInfo dp_ci_template{VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
6357                                                     nullptr,  // pNext
6358                                                     0,        // flags
6359                                                     1,        // maxSets
6360                                                     1,        // poolSizeCount
6361                                                     &dp_size_template};
6362 
6363     // try maxSets = 0
6364     {
6365         VkDescriptorPoolCreateInfo invalid_dp_ci = dp_ci_template;
6366         invalid_dp_ci.maxSets = 0;  // invalid maxSets value
6367 
6368         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorPoolCreateInfo-maxSets-00301");
6369         {
6370             VkDescriptorPool pool;
6371             vkCreateDescriptorPool(m_device->device(), &invalid_dp_ci, nullptr, &pool);
6372         }
6373         m_errorMonitor->VerifyFound();
6374     }
6375 
6376     // try descriptorCount = 0
6377     {
6378         VkDescriptorPoolSize invalid_dp_size = dp_size_template;
6379         invalid_dp_size.descriptorCount = 0;  // invalid descriptorCount value
6380 
6381         VkDescriptorPoolCreateInfo dp_ci = dp_ci_template;
6382         dp_ci.pPoolSizes = &invalid_dp_size;
6383 
6384         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorPoolSize-descriptorCount-00302");
6385         {
6386             VkDescriptorPool pool;
6387             vkCreateDescriptorPool(m_device->device(), &dp_ci, nullptr, &pool);
6388         }
6389         m_errorMonitor->VerifyFound();
6390     }
6391 }
6392 
TEST_F(VkLayerTest,DuplicateDescriptorBinding)6393 TEST_F(VkLayerTest, DuplicateDescriptorBinding) {
6394     TEST_DESCRIPTION("Create a descriptor set layout with a duplicate binding number.");
6395 
6396     ASSERT_NO_FATAL_FAILURE(Init());
6397     // Create layout where two binding #s are "1"
6398     static const uint32_t NUM_BINDINGS = 3;
6399     VkDescriptorSetLayoutBinding dsl_binding[NUM_BINDINGS] = {};
6400     dsl_binding[0].binding = 1;
6401     dsl_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
6402     dsl_binding[0].descriptorCount = 1;
6403     dsl_binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
6404     dsl_binding[0].pImmutableSamplers = NULL;
6405     dsl_binding[1].binding = 0;
6406     dsl_binding[1].descriptorCount = 1;
6407     dsl_binding[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
6408     dsl_binding[1].descriptorCount = 1;
6409     dsl_binding[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
6410     dsl_binding[1].pImmutableSamplers = NULL;
6411     dsl_binding[2].binding = 1;  // Duplicate binding should cause error
6412     dsl_binding[2].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
6413     dsl_binding[2].descriptorCount = 1;
6414     dsl_binding[2].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
6415     dsl_binding[2].pImmutableSamplers = NULL;
6416 
6417     VkDescriptorSetLayoutCreateInfo ds_layout_ci = {};
6418     ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
6419     ds_layout_ci.pNext = NULL;
6420     ds_layout_ci.bindingCount = NUM_BINDINGS;
6421     ds_layout_ci.pBindings = dsl_binding;
6422     VkDescriptorSetLayout ds_layout;
6423     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetLayoutCreateInfo-binding-00279");
6424     vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
6425     m_errorMonitor->VerifyFound();
6426 }
6427 
TEST_F(VkLayerTest,InvalidPushDescriptorSetLayout)6428 TEST_F(VkLayerTest, InvalidPushDescriptorSetLayout) {
6429     TEST_DESCRIPTION("Create a push descriptor set layout with invalid bindings.");
6430 
6431     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
6432         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
6433     } else {
6434         printf("%s Did not find VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; skipped.\n", kSkipPrefix);
6435         return;
6436     }
6437 
6438     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
6439     if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)) {
6440         m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
6441     } else {
6442         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
6443         return;
6444     }
6445 
6446     ASSERT_NO_FATAL_FAILURE(InitState());
6447 
6448     // Get the push descriptor limits
6449     auto push_descriptor_prop = GetPushDescriptorProperties(instance(), gpu());
6450     if (push_descriptor_prop.maxPushDescriptors < 1) {
6451         // Some implementations report an invalid maxPushDescriptors of 0
6452         printf("%s maxPushDescriptors is zero, skipping tests\n", kSkipPrefix);
6453         return;
6454     }
6455 
6456     VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr};
6457 
6458     auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>();
6459     ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
6460     ds_layout_ci.bindingCount = 1;
6461     ds_layout_ci.pBindings = &binding;
6462 
6463     // Note that as binding is referenced in ds_layout_ci, it is effectively in the closure by reference as well.
6464     auto test_create_ds_layout = [&ds_layout_ci, this](std::string error) {
6465         VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
6466         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, error);
6467         vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
6468         m_errorMonitor->VerifyFound();
6469         vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
6470     };
6471 
6472     // Starting with the initial VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC type set above..
6473     test_create_ds_layout("VUID-VkDescriptorSetLayoutCreateInfo-flags-00280");
6474 
6475     binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
6476     test_create_ds_layout(
6477         "VUID-VkDescriptorSetLayoutCreateInfo-flags-00280");  // This is the same VUID as above, just a second error condition.
6478 
6479     if (!(push_descriptor_prop.maxPushDescriptors == std::numeric_limits<uint32_t>::max())) {
6480         binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
6481         binding.descriptorCount = push_descriptor_prop.maxPushDescriptors + 1;
6482         test_create_ds_layout("VUID-VkDescriptorSetLayoutCreateInfo-flags-00281");
6483     } else {
6484         printf("%s maxPushDescriptors is set to maximum unit32_t value, skipping 'out of range test'.\n", kSkipPrefix);
6485     }
6486 }
6487 
TEST_F(VkLayerTest,PushDescriptorSetLayoutWithoutExtension)6488 TEST_F(VkLayerTest, PushDescriptorSetLayoutWithoutExtension) {
6489     TEST_DESCRIPTION("Create a push descriptor set layout without loading the needed extension.");
6490     ASSERT_NO_FATAL_FAILURE(Init());
6491 
6492     VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr};
6493 
6494     auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>();
6495     ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
6496     ds_layout_ci.bindingCount = 1;
6497     ds_layout_ci.pBindings = &binding;
6498 
6499     std::string error = "Attempted to use VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR in ";
6500     error = error + "VkDescriptorSetLayoutCreateInfo::flags but its required extension ";
6501     error = error + VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME;
6502     error = error + " has not been enabled.";
6503 
6504     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, error.c_str());
6505     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetLayoutCreateInfo-flags-00281");
6506     VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
6507     vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
6508     m_errorMonitor->VerifyFound();
6509     vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
6510 }
6511 
TEST_F(VkLayerTest,DescriptorIndexingSetLayoutWithoutExtension)6512 TEST_F(VkLayerTest, DescriptorIndexingSetLayoutWithoutExtension) {
6513     TEST_DESCRIPTION("Create an update_after_bind set layout without loading the needed extension.");
6514     ASSERT_NO_FATAL_FAILURE(Init());
6515 
6516     auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>();
6517     ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
6518 
6519     std::string error = "Attemped to use VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT in ";
6520     error = error + "VkDescriptorSetLayoutCreateInfo::flags but its required extension ";
6521     error = error + VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME;
6522     error = error + " has not been enabled.";
6523 
6524     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, error.c_str());
6525     VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
6526     vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
6527     m_errorMonitor->VerifyFound();
6528     vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
6529 }
6530 
TEST_F(VkLayerTest,DescriptorIndexingSetLayout)6531 TEST_F(VkLayerTest, DescriptorIndexingSetLayout) {
6532     TEST_DESCRIPTION("Exercise various create/allocate-time errors related to VK_EXT_descriptor_indexing.");
6533 
6534     if (!(CheckDescriptorIndexingSupportAndInitFramework(this, m_instance_extension_names, m_device_extension_names, NULL,
6535                                                          m_errorMonitor))) {
6536         printf("%s Descriptor indexing or one of its dependencies not supported, skipping tests\n.", kSkipPrefix);
6537         return;
6538     }
6539 
6540     PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR =
6541         (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR");
6542     ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr);
6543 
6544     // Create a device that enables all supported indexing features except descriptorBindingUniformBufferUpdateAfterBind
6545     auto indexing_features = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>();
6546     auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&indexing_features);
6547     vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2);
6548 
6549     indexing_features.descriptorBindingUniformBufferUpdateAfterBind = VK_FALSE;
6550 
6551     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2));
6552 
6553     std::array<VkDescriptorBindingFlagsEXT, 2> flags = {VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT,
6554                                                         VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT};
6555     auto flags_create_info = lvl_init_struct<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>();
6556     flags_create_info.bindingCount = (uint32_t)flags.size();
6557     flags_create_info.pBindingFlags = flags.data();
6558 
6559     VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr};
6560     auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>(&flags_create_info);
6561     ds_layout_ci.bindingCount = 1;
6562     ds_layout_ci.pBindings = &binding;
6563     VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
6564 
6565     // VU for VkDescriptorSetLayoutBindingFlagsCreateInfoEXT::bindingCount
6566     flags_create_info.bindingCount = 2;
6567     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
6568                                          "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-bindingCount-03002");
6569     VkResult err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
6570     m_errorMonitor->VerifyFound();
6571     vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
6572 
6573     flags_create_info.bindingCount = 1;
6574 
6575     // set is missing UPDATE_AFTER_BIND_POOL flag.
6576     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetLayoutCreateInfo-flags-03000");
6577     // binding uses a feature we disabled
6578     m_errorMonitor->SetDesiredFailureMsg(
6579         VK_DEBUG_REPORT_ERROR_BIT_EXT,
6580         "VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUniformBufferUpdateAfterBind-03005");
6581     err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
6582     m_errorMonitor->VerifyFound();
6583     vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
6584 
6585     ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
6586     ds_layout_ci.bindingCount = 0;
6587     flags_create_info.bindingCount = 0;
6588     err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
6589     ASSERT_VK_SUCCESS(err);
6590 
6591     VkDescriptorPoolSize pool_size = {binding.descriptorType, binding.descriptorCount};
6592     auto dspci = lvl_init_struct<VkDescriptorPoolCreateInfo>();
6593     dspci.poolSizeCount = 1;
6594     dspci.pPoolSizes = &pool_size;
6595     dspci.maxSets = 1;
6596     VkDescriptorPool pool;
6597     err = vkCreateDescriptorPool(m_device->handle(), &dspci, nullptr, &pool);
6598     ASSERT_VK_SUCCESS(err);
6599 
6600     auto ds_alloc_info = lvl_init_struct<VkDescriptorSetAllocateInfo>();
6601     ds_alloc_info.descriptorPool = pool;
6602     ds_alloc_info.descriptorSetCount = 1;
6603     ds_alloc_info.pSetLayouts = &ds_layout;
6604 
6605     VkDescriptorSet ds = VK_NULL_HANDLE;
6606     // mismatch between descriptor set and pool
6607     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044");
6608     vkAllocateDescriptorSets(m_device->handle(), &ds_alloc_info, &ds);
6609     m_errorMonitor->VerifyFound();
6610 
6611     vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
6612     vkDestroyDescriptorPool(m_device->handle(), pool, nullptr);
6613 
6614     if (indexing_features.descriptorBindingVariableDescriptorCount) {
6615         ds_layout_ci.flags = 0;
6616         ds_layout_ci.bindingCount = 1;
6617         flags_create_info.bindingCount = 1;
6618         flags[0] = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT;
6619         err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
6620         ASSERT_VK_SUCCESS(err);
6621 
6622         pool_size = {binding.descriptorType, binding.descriptorCount};
6623         dspci = lvl_init_struct<VkDescriptorPoolCreateInfo>();
6624         dspci.poolSizeCount = 1;
6625         dspci.pPoolSizes = &pool_size;
6626         dspci.maxSets = 1;
6627         err = vkCreateDescriptorPool(m_device->handle(), &dspci, nullptr, &pool);
6628         ASSERT_VK_SUCCESS(err);
6629 
6630         auto count_alloc_info = lvl_init_struct<VkDescriptorSetVariableDescriptorCountAllocateInfoEXT>();
6631         count_alloc_info.descriptorSetCount = 1;
6632         // Set variable count larger than what was in the descriptor binding
6633         uint32_t variable_count = 2;
6634         count_alloc_info.pDescriptorCounts = &variable_count;
6635 
6636         ds_alloc_info = lvl_init_struct<VkDescriptorSetAllocateInfo>(&count_alloc_info);
6637         ds_alloc_info.descriptorPool = pool;
6638         ds_alloc_info.descriptorSetCount = 1;
6639         ds_alloc_info.pSetLayouts = &ds_layout;
6640 
6641         ds = VK_NULL_HANDLE;
6642         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
6643                                              "VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-pSetLayouts-03046");
6644         vkAllocateDescriptorSets(m_device->handle(), &ds_alloc_info, &ds);
6645         m_errorMonitor->VerifyFound();
6646 
6647         vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
6648         vkDestroyDescriptorPool(m_device->handle(), pool, nullptr);
6649     }
6650 }
6651 
TEST_F(VkLayerTest,DescriptorIndexingUpdateAfterBind)6652 TEST_F(VkLayerTest, DescriptorIndexingUpdateAfterBind) {
6653     TEST_DESCRIPTION("Exercise errors for updating a descriptor set after it is bound.");
6654 
6655     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
6656         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
6657     } else {
6658         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix,
6659                VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
6660         return;
6661     }
6662 
6663     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
6664     if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME) &&
6665         DeviceExtensionSupported(gpu(), nullptr, VK_KHR_MAINTENANCE3_EXTENSION_NAME)) {
6666         m_device_extension_names.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
6667         m_device_extension_names.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
6668     } else {
6669         printf("%s Descriptor Indexing or Maintenance3 Extension not supported, skipping tests\n", kSkipPrefix);
6670         return;
6671     }
6672 
6673     PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR =
6674         (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR");
6675     ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr);
6676 
6677     // Create a device that enables all supported indexing features except descriptorBindingUniformBufferUpdateAfterBind
6678     auto indexing_features = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>();
6679     auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&indexing_features);
6680     vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2);
6681 
6682     indexing_features.descriptorBindingUniformBufferUpdateAfterBind = VK_FALSE;
6683 
6684     if (VK_FALSE == indexing_features.descriptorBindingStorageBufferUpdateAfterBind) {
6685         printf("%s Test requires (unsupported) descriptorBindingStorageBufferUpdateAfterBind, skipping\n", kSkipPrefix);
6686         return;
6687     }
6688     if (VK_FALSE == features2.features.fragmentStoresAndAtomics) {
6689         printf("%s Test requires (unsupported) fragmentStoresAndAtomics, skipping\n", kSkipPrefix);
6690         return;
6691     }
6692 
6693     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
6694     ASSERT_NO_FATAL_FAILURE(InitViewport());
6695     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
6696 
6697     VkDescriptorBindingFlagsEXT flags[2] = {0, VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT};
6698     auto flags_create_info = lvl_init_struct<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>();
6699     flags_create_info.bindingCount = 2;
6700     flags_create_info.pBindingFlags = &flags[0];
6701 
6702     // Descriptor set has two bindings - only the second is update_after_bind
6703     VkDescriptorSetLayoutBinding binding[2] = {
6704         {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr},
6705         {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr},
6706     };
6707     auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>(&flags_create_info);
6708     ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
6709     ds_layout_ci.bindingCount = 2;
6710     ds_layout_ci.pBindings = &binding[0];
6711     VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
6712 
6713     VkResult err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
6714 
6715     VkDescriptorPoolSize pool_sizes[2] = {
6716         {binding[0].descriptorType, binding[0].descriptorCount},
6717         {binding[1].descriptorType, binding[1].descriptorCount},
6718     };
6719     auto dspci = lvl_init_struct<VkDescriptorPoolCreateInfo>();
6720     dspci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT;
6721     dspci.poolSizeCount = 2;
6722     dspci.pPoolSizes = &pool_sizes[0];
6723     dspci.maxSets = 1;
6724     VkDescriptorPool pool;
6725     err = vkCreateDescriptorPool(m_device->handle(), &dspci, nullptr, &pool);
6726     ASSERT_VK_SUCCESS(err);
6727 
6728     auto ds_alloc_info = lvl_init_struct<VkDescriptorSetAllocateInfo>();
6729     ds_alloc_info.descriptorPool = pool;
6730     ds_alloc_info.descriptorSetCount = 1;
6731     ds_alloc_info.pSetLayouts = &ds_layout;
6732 
6733     VkDescriptorSet ds = VK_NULL_HANDLE;
6734     vkAllocateDescriptorSets(m_device->handle(), &ds_alloc_info, &ds);
6735     ASSERT_VK_SUCCESS(err);
6736 
6737     VkBufferCreateInfo buffCI = {};
6738     buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
6739     buffCI.size = 1024;
6740     buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
6741 
6742     VkBuffer dynamic_uniform_buffer;
6743     err = vkCreateBuffer(m_device->device(), &buffCI, NULL, &dynamic_uniform_buffer);
6744     ASSERT_VK_SUCCESS(err);
6745 
6746     VkDeviceMemory mem;
6747     VkMemoryRequirements mem_reqs;
6748     vkGetBufferMemoryRequirements(m_device->device(), dynamic_uniform_buffer, &mem_reqs);
6749 
6750     VkMemoryAllocateInfo mem_alloc_info = {};
6751     mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
6752     mem_alloc_info.allocationSize = mem_reqs.size;
6753     m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
6754     err = vkAllocateMemory(m_device->device(), &mem_alloc_info, NULL, &mem);
6755     ASSERT_VK_SUCCESS(err);
6756 
6757     err = vkBindBufferMemory(m_device->device(), dynamic_uniform_buffer, mem, 0);
6758     ASSERT_VK_SUCCESS(err);
6759 
6760     VkDescriptorBufferInfo buffInfo[2] = {};
6761     buffInfo[0].buffer = dynamic_uniform_buffer;
6762     buffInfo[0].offset = 0;
6763     buffInfo[0].range = 1024;
6764 
6765     VkWriteDescriptorSet descriptor_write[2] = {};
6766     descriptor_write[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
6767     descriptor_write[0].dstSet = ds;
6768     descriptor_write[0].dstBinding = 0;
6769     descriptor_write[0].descriptorCount = 1;
6770     descriptor_write[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
6771     descriptor_write[0].pBufferInfo = buffInfo;
6772     descriptor_write[1] = descriptor_write[0];
6773     descriptor_write[1].dstBinding = 1;
6774     descriptor_write[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
6775 
6776     VkPipelineLayout pipeline_layout;
6777     VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
6778     pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
6779     pipeline_layout_ci.setLayoutCount = 1;
6780     pipeline_layout_ci.pSetLayouts = &ds_layout;
6781 
6782     vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
6783 
6784     // Create a dummy pipeline, since VL inspects which bindings are actually used at draw time
6785     char const *fsSource =
6786         "#version 450\n"
6787         "\n"
6788         "layout(location=0) out vec4 color;\n"
6789         "layout(set=0, binding=0) uniform foo0 { float x0; } bar0;\n"
6790         "layout(set=0, binding=1) buffer  foo1 { float x1; } bar1;\n"
6791         "void main(){\n"
6792         "   color = vec4(bar0.x0 + bar1.x1);\n"
6793         "}\n";
6794 
6795     VkShaderObj vs(m_device, bindStateVertShaderText, VK_SHADER_STAGE_VERTEX_BIT, this);
6796     VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
6797 
6798     VkPipelineObj pipe(m_device);
6799     pipe.SetViewport(m_viewports);
6800     pipe.SetScissor(m_scissors);
6801     pipe.AddDefaultColorAttachment();
6802     pipe.AddShader(&vs);
6803     pipe.AddShader(&fs);
6804     pipe.CreateVKPipeline(pipeline_layout, m_renderPass);
6805 
6806     // Make both bindings valid before binding to the command buffer
6807     vkUpdateDescriptorSets(m_device->device(), 2, &descriptor_write[0], 0, NULL);
6808     m_errorMonitor->VerifyNotFound();
6809 
6810     // Two subtests. First only updates the update_after_bind binding and expects
6811     // no error. Second updates the other binding and expects an error when the
6812     // command buffer is ended.
6813     for (uint32_t i = 0; i < 2; ++i) {
6814         m_commandBuffer->begin();
6815 
6816         vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &ds, 0, NULL);
6817 
6818         m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
6819         vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
6820         vkCmdDraw(m_commandBuffer->handle(), 0, 0, 0, 0);
6821         vkCmdEndRenderPass(m_commandBuffer->handle());
6822 
6823         m_errorMonitor->VerifyNotFound();
6824         // Valid to update binding 1 after being bound
6825         vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write[1], 0, NULL);
6826         m_errorMonitor->VerifyNotFound();
6827 
6828         if (i == 0) {
6829             // expect no errors
6830             m_commandBuffer->end();
6831             m_errorMonitor->VerifyNotFound();
6832         } else {
6833             // Invalid to update binding 0 after being bound. But the error is actually
6834             // generated during vkEndCommandBuffer
6835             vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write[0], 0, NULL);
6836             m_errorMonitor->VerifyNotFound();
6837 
6838             m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT,
6839                                                  "UNASSIGNED-CoreValidation-DrawState-InvalidCommandBuffer-VkDescriptorSet");
6840 
6841             vkEndCommandBuffer(m_commandBuffer->handle());
6842             m_errorMonitor->VerifyFound();
6843         }
6844     }
6845 
6846     vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
6847     vkDestroyDescriptorPool(m_device->handle(), pool, nullptr);
6848     vkDestroyBuffer(m_device->handle(), dynamic_uniform_buffer, NULL);
6849     vkFreeMemory(m_device->handle(), mem, NULL);
6850     vkDestroyPipelineLayout(m_device->handle(), pipeline_layout, NULL);
6851 }
6852 
TEST_F(VkLayerTest,AllocatePushDescriptorSet)6853 TEST_F(VkLayerTest, AllocatePushDescriptorSet) {
6854     TEST_DESCRIPTION("Attempt to allocate a push descriptor set.");
6855     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
6856         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
6857     } else {
6858         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix,
6859                VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
6860         return;
6861     }
6862 
6863     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
6864     if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)) {
6865         m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
6866     } else {
6867         printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
6868         return;
6869     }
6870     ASSERT_NO_FATAL_FAILURE(InitState());
6871 
6872     auto push_descriptor_prop = GetPushDescriptorProperties(instance(), gpu());
6873     if (push_descriptor_prop.maxPushDescriptors < 1) {
6874         // Some implementations report an invalid maxPushDescriptors of 0
6875         printf("%s maxPushDescriptors is zero, skipping tests\n", kSkipPrefix);
6876         return;
6877     }
6878 
6879     VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr};
6880     auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>();
6881     ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
6882     ds_layout_ci.bindingCount = 1;
6883     ds_layout_ci.pBindings = &binding;
6884     VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
6885     VkResult err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
6886     ASSERT_VK_SUCCESS(err);
6887 
6888     VkDescriptorPoolSize pool_size = {binding.descriptorType, binding.descriptorCount};
6889     auto dspci = lvl_init_struct<VkDescriptorPoolCreateInfo>();
6890     dspci.poolSizeCount = 1;
6891     dspci.pPoolSizes = &pool_size;
6892     dspci.maxSets = 1;
6893     VkDescriptorPool pool;
6894     err = vkCreateDescriptorPool(m_device->handle(), &dspci, nullptr, &pool);
6895     ASSERT_VK_SUCCESS(err);
6896 
6897     auto ds_alloc_info = lvl_init_struct<VkDescriptorSetAllocateInfo>();
6898     ds_alloc_info.descriptorPool = pool;
6899     ds_alloc_info.descriptorSetCount = 1;
6900     ds_alloc_info.pSetLayouts = &ds_layout;
6901 
6902     VkDescriptorSet ds = VK_NULL_HANDLE;
6903     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetAllocateInfo-pSetLayouts-00308");
6904     vkAllocateDescriptorSets(m_device->handle(), &ds_alloc_info, &ds);
6905     m_errorMonitor->VerifyFound();
6906 
6907     vkDestroyDescriptorPool(m_device->handle(), pool, nullptr);
6908     vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
6909 }
6910 
TEST_F(VkLayerTest,CreateDescriptorUpdateTemplate)6911 TEST_F(VkLayerTest, CreateDescriptorUpdateTemplate) {
6912     TEST_DESCRIPTION("Verify error messages for invalid vkCreateDescriptorUpdateTemplate calls.");
6913 
6914     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
6915         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
6916     } else {
6917         printf("%s Did not find VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; skipped.\n", kSkipPrefix);
6918         return;
6919     }
6920     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
6921     // Note: Includes workaround for some implementations which incorrectly return 0 maxPushDescriptors
6922     if (DeviceExtensionSupported(gpu(), nullptr, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME) &&
6923         DeviceExtensionSupported(gpu(), nullptr, VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME) &&
6924         (GetPushDescriptorProperties(instance(), gpu()).maxPushDescriptors > 0)) {
6925         m_device_extension_names.push_back(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
6926         m_device_extension_names.push_back(VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME);
6927     } else {
6928         printf("%s Push Descriptors and Descriptor Update Template Extensions not supported, skipping tests\n", kSkipPrefix);
6929         return;
6930     }
6931     ASSERT_NO_FATAL_FAILURE(InitState());
6932 
6933     VkDescriptorSetLayoutBinding dsl_binding = {};
6934     dsl_binding.binding = 0;
6935     dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
6936     dsl_binding.descriptorCount = 1;
6937     dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
6938     dsl_binding.pImmutableSamplers = NULL;
6939 
6940     const VkDescriptorSetLayoutObj ds_layout_ub(m_device, {dsl_binding});
6941     const VkDescriptorSetLayoutObj ds_layout_ub1(m_device, {dsl_binding});
6942     const VkDescriptorSetLayoutObj ds_layout_ub_push(m_device, {dsl_binding},
6943                                                      VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR);
6944     const VkPipelineLayoutObj pipeline_layout(m_device, {{&ds_layout_ub, &ds_layout_ub1, &ds_layout_ub_push}});
6945     PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR =
6946         (PFN_vkCreateDescriptorUpdateTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkCreateDescriptorUpdateTemplateKHR");
6947     ASSERT_NE(vkCreateDescriptorUpdateTemplateKHR, nullptr);
6948     PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR =
6949         (PFN_vkDestroyDescriptorUpdateTemplateKHR)vkGetDeviceProcAddr(m_device->device(), "vkDestroyDescriptorUpdateTemplateKHR");
6950     ASSERT_NE(vkDestroyDescriptorUpdateTemplateKHR, nullptr);
6951 
6952     VkDescriptorUpdateTemplateEntry entries = {0, 0, 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, sizeof(VkBuffer)};
6953     VkDescriptorUpdateTemplateCreateInfo create_info = {};
6954     create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO;
6955     create_info.pNext = nullptr;
6956     create_info.flags = 0;
6957     create_info.descriptorUpdateEntryCount = 1;
6958     create_info.pDescriptorUpdateEntries = &entries;
6959 
6960     auto do_test = [&](std::string err) {
6961         VkDescriptorUpdateTemplateKHR dut = VK_NULL_HANDLE;
6962         m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, err);
6963         if (VK_SUCCESS == vkCreateDescriptorUpdateTemplateKHR(m_device->handle(), &create_info, nullptr, &dut)) {
6964             vkDestroyDescriptorUpdateTemplateKHR(m_device->handle(), dut, nullptr);
6965         }
6966         m_errorMonitor->VerifyFound();
6967     };
6968 
6969     // Descriptor set type template
6970     create_info.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET;
6971     // descriptorSetLayout is NULL
6972     do_test("VUID-VkDescriptorUpdateTemplateCreateInfo-templateType-00350");
6973 
6974     // Push descriptor type template
6975     create_info.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR;
6976     create_info.pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
6977     create_info.pipelineLayout = pipeline_layout.handle();
6978     create_info.set = 2;
6979 
6980     // Bad bindpoint -- force fuzz the bind point
6981     memset(&create_info.pipelineBindPoint, 0xFE, sizeof(create_info.pipelineBindPoint));
6982     do_test("VUID-VkDescriptorUpdateTemplateCreateInfo-templateType-00351");
6983     create_info.pipelineBindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
6984 
6985     // Bad pipeline layout
6986     create_info.pipelineLayout = VK_NULL_HANDLE;
6987     do_test("VUID-VkDescriptorUpdateTemplateCreateInfo-templateType-00352");
6988     create_info.pipelineLayout = pipeline_layout.handle();
6989 
6990     // Wrong set #
6991     create_info.set = 0;
6992     do_test("VUID-VkDescriptorUpdateTemplateCreateInfo-templateType-00353");
6993 
6994     // Invalid set #
6995     create_info.set = 42;
6996     do_test("VUID-VkDescriptorUpdateTemplateCreateInfo-templateType-00353");
6997 }
6998 
TEST_F(VkLayerTest,InlineUniformBlockEXT)6999 TEST_F(VkLayerTest, InlineUniformBlockEXT) {
7000     TEST_DESCRIPTION("Test VK_EXT_inline_uniform_block.");
7001 
7002     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
7003         m_instance_extension_names.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
7004     } else {
7005         printf("%s Did not find required instance extension %s; skipped.\n", kSkipPrefix,
7006                VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
7007         return;
7008     }
7009     ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
7010     std::array<const char *, 2> required_device_extensions = {VK_KHR_MAINTENANCE1_EXTENSION_NAME,
7011                                                               VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME};
7012     for (auto device_extension : required_device_extensions) {
7013         if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) {
7014             m_device_extension_names.push_back(device_extension);
7015         } else {
7016             printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension);
7017             return;
7018         }
7019     }
7020 
7021     // Enable descriptor indexing if supported, but don't require it.
7022     bool supportsDescriptorIndexing = true;
7023     required_device_extensions = {VK_KHR_MAINTENANCE3_EXTENSION_NAME, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME};
7024     for (auto device_extension : required_device_extensions) {
7025         if (DeviceExtensionSupported(gpu(), nullptr, device_extension)) {
7026             m_device_extension_names.push_back(device_extension);
7027         } else {
7028             printf("%s %s Extension not supported, skipping tests\n", kSkipPrefix, device_extension);
7029             supportsDescriptorIndexing = false;
7030             return;
7031         }
7032     }
7033 
7034     PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR =
7035         (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceFeatures2KHR");
7036     ASSERT_TRUE(vkGetPhysicalDeviceFeatures2KHR != nullptr);
7037 
7038     auto descriptor_indexing_features = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>();
7039     void *pNext = supportsDescriptorIndexing ? &descriptor_indexing_features : nullptr;
7040     // Create a device that enables inline_uniform_block
7041     auto inline_uniform_block_features = lvl_init_struct<VkPhysicalDeviceInlineUniformBlockFeaturesEXT>(pNext);
7042     auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&inline_uniform_block_features);
7043     vkGetPhysicalDeviceFeatures2KHR(gpu(), &features2);
7044 
7045     PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR =
7046         (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(instance(), "vkGetPhysicalDeviceProperties2KHR");
7047     assert(vkGetPhysicalDeviceProperties2KHR != nullptr);
7048 
7049     // Get the inline uniform block limits
7050     auto inline_uniform_props = lvl_init_struct<VkPhysicalDeviceInlineUniformBlockPropertiesEXT>();
7051     auto prop2 = lvl_init_struct<VkPhysicalDeviceProperties2KHR>(&inline_uniform_props);
7052     vkGetPhysicalDeviceProperties2KHR(gpu(), &prop2);
7053 
7054     ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2));
7055 
7056     VkDescriptorSetLayoutBinding dslb = {};
7057     std::vector<VkDescriptorSetLayoutBinding> dslb_vec = {};
7058     VkDescriptorSetLayoutCreateInfo ds_layout_ci = {};
7059     ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
7060     VkDescriptorSetLayout ds_layout = {};
7061 
7062     // Test too many bindings
7063     dslb_vec.clear();
7064     dslb.binding = 0;
7065     dslb.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;
7066     dslb.descriptorCount = 4;
7067     dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
7068 
7069     if (inline_uniform_props.maxInlineUniformBlockSize < dslb.descriptorCount) {
7070         printf("%sDescriptorCount exceeds InlineUniformBlockSize limit, skipping tests\n", kSkipPrefix);
7071         return;
7072     }
7073 
7074     uint32_t maxBlocks = std::max(inline_uniform_props.maxPerStageDescriptorInlineUniformBlocks,
7075                                   inline_uniform_props.maxDescriptorSetInlineUniformBlocks);
7076     for (uint32_t i = 0; i < 1 + maxBlocks; ++i) {
7077         dslb.binding = i;
7078         dslb_vec.push_back(dslb);
7079     }
7080 
7081     ds_layout_ci.bindingCount = dslb_vec.size();
7082     ds_layout_ci.pBindings = dslb_vec.data();
7083     VkResult err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
7084     ASSERT_VK_SUCCESS(err);
7085 
7086     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-descriptorType-02214");
7087     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-descriptorType-02216");
7088     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-descriptorType-02215");
7089     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkPipelineLayoutCreateInfo-descriptorType-02217");
7090 
7091     VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
7092     pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
7093     pipeline_layout_ci.pNext = NULL;
7094     pipeline_layout_ci.setLayoutCount = 1;
7095     pipeline_layout_ci.pSetLayouts = &ds_layout;
7096     VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
7097 
7098     err = vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
7099     m_errorMonitor->VerifyFound();
7100     vkDestroyPipelineLayout(m_device->device(), pipeline_layout, NULL);
7101     pipeline_layout = VK_NULL_HANDLE;
7102     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, nullptr);
7103     ds_layout = VK_NULL_HANDLE;
7104 
7105     // Single binding that's too large and is not a multiple of 4
7106     dslb.binding = 0;
7107     dslb.descriptorCount = inline_uniform_props.maxInlineUniformBlockSize + 1;
7108 
7109     ds_layout_ci.bindingCount = 1;
7110     ds_layout_ci.pBindings = &dslb;
7111     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02209");
7112     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorSetLayoutBinding-descriptorType-02210");
7113     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
7114     m_errorMonitor->VerifyFound();
7115     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, nullptr);
7116     ds_layout = VK_NULL_HANDLE;
7117 
7118     // Pool size must be a multiple of 4
7119     VkDescriptorPoolSize ds_type_count = {};
7120     ds_type_count.type = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;
7121     ds_type_count.descriptorCount = 33;
7122 
7123     VkDescriptorPoolCreateInfo ds_pool_ci = {};
7124     ds_pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
7125     ds_pool_ci.pNext = NULL;
7126     ds_pool_ci.flags = 0;
7127     ds_pool_ci.maxSets = 2;
7128     ds_pool_ci.poolSizeCount = 1;
7129     ds_pool_ci.pPoolSizes = &ds_type_count;
7130 
7131     VkDescriptorPool ds_pool = VK_NULL_HANDLE;
7132     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkDescriptorPoolSize-type-02218");
7133     err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
7134     m_errorMonitor->VerifyFound();
7135     if (ds_pool) {
7136         vkDestroyDescriptorPool(m_device->handle(), ds_pool, nullptr);
7137         ds_pool = VK_NULL_HANDLE;
7138     }
7139 
7140     // Create a valid pool
7141     ds_type_count.descriptorCount = 32;
7142     err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
7143     m_errorMonitor->VerifyNotFound();
7144 
7145     // Create two valid sets with 8 bytes each
7146     dslb_vec.clear();
7147     dslb.binding = 0;
7148     dslb.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;
7149     dslb.descriptorCount = 8;
7150     dslb.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
7151     dslb_vec.push_back(dslb);
7152     dslb.binding = 1;
7153     dslb_vec.push_back(dslb);
7154 
7155     ds_layout_ci.bindingCount = dslb_vec.size();
7156     ds_layout_ci.pBindings = &dslb_vec[0];
7157 
7158     err = vkCreateDescriptorSetLayout(m_device->device(), &ds_layout_ci, NULL, &ds_layout);
7159     m_errorMonitor->VerifyNotFound();
7160 
7161     VkDescriptorSet descriptor_sets[2];
7162     VkDescriptorSetLayout set_layouts[2] = {ds_layout, ds_layout};
7163     VkDescriptorSetAllocateInfo alloc_info = {};
7164     alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
7165     alloc_info.descriptorSetCount = 2;
7166     alloc_info.descriptorPool = ds_pool;
7167     alloc_info.pSetLayouts = set_layouts;
7168     err = vkAllocateDescriptorSets(m_device->device(), &alloc_info, descriptor_sets);
7169     m_errorMonitor->VerifyNotFound();
7170 
7171     // Test invalid VkWriteDescriptorSet parameters (array element and size must be multiple of 4)
7172     VkWriteDescriptorSet descriptor_write = {};
7173     descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
7174     descriptor_write.dstSet = descriptor_sets[0];
7175     descriptor_write.dstBinding = 0;
7176     descriptor_write.dstArrayElement = 0;
7177     descriptor_write.descriptorCount = 3;
7178     descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;
7179 
7180     uint32_t dummyData[8] = {};
7181     VkWriteDescriptorSetInlineUniformBlockEXT write_inline_uniform = {};
7182     write_inline_uniform.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT;
7183     write_inline_uniform.dataSize = 3;
7184     write_inline_uniform.pData = &dummyData[0];
7185     descriptor_write.pNext = &write_inline_uniform;
7186 
7187     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-02220");
7188     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
7189     m_errorMonitor->VerifyFound();
7190 
7191     descriptor_write.dstArrayElement = 1;
7192     descriptor_write.descriptorCount = 4;
7193     write_inline_uniform.dataSize = 4;
7194     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-02219");
7195     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
7196     m_errorMonitor->VerifyFound();
7197 
7198     descriptor_write.pNext = nullptr;
7199     descriptor_write.dstArrayElement = 0;
7200     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkWriteDescriptorSet-descriptorType-02221");
7201     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
7202     m_errorMonitor->VerifyFound();
7203 
7204     descriptor_write.pNext = &write_inline_uniform;
7205     vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write, 0, NULL);
7206     m_errorMonitor->VerifyNotFound();
7207 
7208     // Test invalid VkCopyDescriptorSet parameters (array element and size must be multiple of 4)
7209     VkCopyDescriptorSet copy_ds_update = {};
7210     copy_ds_update.sType = VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET;
7211     copy_ds_update.srcSet = descriptor_sets[0];
7212     copy_ds_update.srcBinding = 0;
7213     copy_ds_update.srcArrayElement = 0;
7214     copy_ds_update.dstSet = descriptor_sets[1];
7215     copy_ds_update.dstBinding = 0;
7216     copy_ds_update.dstArrayElement = 0;
7217     copy_ds_update.descriptorCount = 4;
7218 
7219     copy_ds_update.srcArrayElement = 1;
7220     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkCopyDescriptorSet-srcBinding-02223");
7221     vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, &copy_ds_update);
7222     m_errorMonitor->VerifyFound();
7223 
7224     copy_ds_update.srcArrayElement = 0;
7225     copy_ds_update.dstArrayElement = 1;
7226     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkCopyDescriptorSet-dstBinding-02224");
7227     vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, &copy_ds_update);
7228     m_errorMonitor->VerifyFound();
7229 
7230     copy_ds_update.dstArrayElement = 0;
7231     copy_ds_update.descriptorCount = 5;
7232     m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "VUID-VkCopyDescriptorSet-srcBinding-02225");
7233     vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, &copy_ds_update);
7234     m_errorMonitor->VerifyFound();
7235 
7236     copy_ds_update.descriptorCount = 4;
7237     vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, &copy_ds_update);
7238     m_errorMonitor->VerifyNotFound();
7239 
7240     vkDestroyDescriptorPool(m_device->handle(), ds_pool, nullptr);
7241     vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, nullptr);
7242 }