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(©_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, ©_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(©_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, ©_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(©_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, ©_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, ©_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, ©_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, ©_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, ©_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, ©_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, ©_ds_update);
7234 m_errorMonitor->VerifyFound();
7235
7236 copy_ds_update.descriptorCount = 4;
7237 vkUpdateDescriptorSets(m_device->device(), 0, NULL, 1, ©_ds_update);
7238 m_errorMonitor->VerifyNotFound();
7239
7240 vkDestroyDescriptorPool(m_device->handle(), ds_pool, nullptr);
7241 vkDestroyDescriptorSetLayout(m_device->device(), ds_layout, nullptr);
7242 }