blob: ff7b471b799a26bccc6fb91c20a367ee4a3afd36 [file] [log] [blame]
Mark Lobodzinski103c58a2020-01-29 13:20:00 -07001/* Copyright (c) 2018-2020 The Khronos Group Inc.
2 * Copyright (c) 2018-2020 Valve Corporation
3 * Copyright (c) 2018-2020 LunarG, Inc.
Karl Schultz7b024b42018-08-30 16:18:18 -06004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060017 * Author: Karl Schultz <karl@lunarg.com>
18 * Author: Tony Barbour <tony@lunarg.com>
Karl Schultz7b024b42018-08-30 16:18:18 -060019 */
20
Tony-LunarGc28e28a2020-08-14 10:37:48 -060021#include <climits>
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -070022#include "gpu_validation.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060023#include "spirv-tools/optimizer.hpp"
24#include "spirv-tools/instrument.hpp"
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060025#include "layer_chassis_dispatch.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060026
Jason Macnak67407e72019-07-11 11:05:09 -070027static const VkShaderStageFlags kShaderStageAllRayTracing =
28 VK_SHADER_STAGE_ANY_HIT_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV | VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV |
29 VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV | VK_SHADER_STAGE_RAYGEN_BIT_NV;
30
Jason Macnak83cfd582019-07-31 10:14:24 -070031// Keep in sync with the GLSL shader below.
32struct GpuAccelerationStructureBuildValidationBuffer {
33 uint32_t instances_to_validate;
34 uint32_t replacement_handle_bits_0;
35 uint32_t replacement_handle_bits_1;
36 uint32_t invalid_handle_found;
37 uint32_t invalid_handle_bits_0;
38 uint32_t invalid_handle_bits_1;
39 uint32_t valid_handles_count;
40};
41
42// This is the GLSL source for the compute shader that is used during ray tracing acceleration structure
43// building validation which inspects instance buffers for top level acceleration structure builds and
44// reports and replaces invalid bottom level acceleration structure handles with good bottom level
45// acceleration structure handle so that applications can continue without undefined behavior long enough
46// to report errors.
47//
48// #version 450
49// layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
50// struct VkGeometryInstanceNV {
51// uint unused[14];
52// uint handle_bits_0;
53// uint handle_bits_1;
54// };
55// layout(set=0, binding=0, std430) buffer InstanceBuffer {
56// VkGeometryInstanceNV instances[];
57// };
58// layout(set=0, binding=1, std430) buffer ValidationBuffer {
59// uint instances_to_validate;
60// uint replacement_handle_bits_0;
61// uint replacement_handle_bits_1;
62// uint invalid_handle_found;
63// uint invalid_handle_bits_0;
64// uint invalid_handle_bits_1;
65// uint valid_handles_count;
66// uint valid_handles[];
67// };
68// void main() {
69// for (uint instance_index = 0; instance_index < instances_to_validate; instance_index++) {
70// uint instance_handle_bits_0 = instances[instance_index].handle_bits_0;
71// uint instance_handle_bits_1 = instances[instance_index].handle_bits_1;
72// bool valid = false;
73// for (uint valid_handle_index = 0; valid_handle_index < valid_handles_count; valid_handle_index++) {
74// if (instance_handle_bits_0 == valid_handles[2*valid_handle_index+0] &&
75// instance_handle_bits_1 == valid_handles[2*valid_handle_index+1]) {
76// valid = true;
77// break;
78// }
79// }
80// if (!valid) {
81// invalid_handle_found += 1;
82// invalid_handle_bits_0 = instance_handle_bits_0;
83// invalid_handle_bits_1 = instance_handle_bits_1;
84// instances[instance_index].handle_bits_0 = replacement_handle_bits_0;
85// instances[instance_index].handle_bits_1 = replacement_handle_bits_1;
86// }
87// }
88// }
89//
90// To regenerate the spirv below:
91// 1. Save the above GLSL source to a file called validation_shader.comp.
92// 2. Run in terminal
93//
94// glslangValidator.exe -x -V validation_shader.comp -o validation_shader.comp.spv
95//
96// 4. Copy-paste the contents of validation_shader.comp.spv here (clang-format will fix up the alignment).
97static const uint32_t kComputeShaderSpirv[] = {
98 0x07230203, 0x00010000, 0x00080007, 0x0000006d, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, 0x00000001, 0x4c534c47,
99 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0005000f, 0x00000005, 0x00000004, 0x6e69616d,
100 0x00000000, 0x00060010, 0x00000004, 0x00000011, 0x00000001, 0x00000001, 0x00000001, 0x00030003, 0x00000002, 0x000001c2,
101 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00060005, 0x00000008, 0x74736e69, 0x65636e61, 0x646e695f, 0x00007865,
102 0x00070005, 0x00000011, 0x696c6156, 0x69746164, 0x75426e6f, 0x72656666, 0x00000000, 0x00090006, 0x00000011, 0x00000000,
103 0x74736e69, 0x65636e61, 0x6f745f73, 0x6c61765f, 0x74616469, 0x00000065, 0x000a0006, 0x00000011, 0x00000001, 0x6c706572,
104 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x000a0006, 0x00000011, 0x00000002, 0x6c706572,
105 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00090006, 0x00000011, 0x00000003, 0x61766e69,
106 0x5f64696c, 0x646e6168, 0x665f656c, 0x646e756f, 0x00000000, 0x00090006, 0x00000011, 0x00000004, 0x61766e69, 0x5f64696c,
107 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00090006, 0x00000011, 0x00000005, 0x61766e69, 0x5f64696c, 0x646e6168,
108 0x625f656c, 0x5f737469, 0x00000031, 0x00080006, 0x00000011, 0x00000006, 0x696c6176, 0x61685f64, 0x656c646e, 0x6f635f73,
109 0x00746e75, 0x00070006, 0x00000011, 0x00000007, 0x696c6176, 0x61685f64, 0x656c646e, 0x00000073, 0x00030005, 0x00000013,
110 0x00000000, 0x00080005, 0x0000001b, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000305f, 0x00080005,
111 0x0000001e, 0x65476b56, 0x74656d6f, 0x6e497972, 0x6e617473, 0x564e6563, 0x00000000, 0x00050006, 0x0000001e, 0x00000000,
112 0x73756e75, 0x00006465, 0x00070006, 0x0000001e, 0x00000001, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00070006,
113 0x0000001e, 0x00000002, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00060005, 0x00000020, 0x74736e49, 0x65636e61,
114 0x66667542, 0x00007265, 0x00060006, 0x00000020, 0x00000000, 0x74736e69, 0x65636e61, 0x00000073, 0x00030005, 0x00000022,
115 0x00000000, 0x00080005, 0x00000027, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000315f, 0x00040005,
116 0x0000002d, 0x696c6176, 0x00000064, 0x00070005, 0x0000002f, 0x696c6176, 0x61685f64, 0x656c646e, 0x646e695f, 0x00007865,
117 0x00040047, 0x00000010, 0x00000006, 0x00000004, 0x00050048, 0x00000011, 0x00000000, 0x00000023, 0x00000000, 0x00050048,
118 0x00000011, 0x00000001, 0x00000023, 0x00000004, 0x00050048, 0x00000011, 0x00000002, 0x00000023, 0x00000008, 0x00050048,
119 0x00000011, 0x00000003, 0x00000023, 0x0000000c, 0x00050048, 0x00000011, 0x00000004, 0x00000023, 0x00000010, 0x00050048,
120 0x00000011, 0x00000005, 0x00000023, 0x00000014, 0x00050048, 0x00000011, 0x00000006, 0x00000023, 0x00000018, 0x00050048,
121 0x00000011, 0x00000007, 0x00000023, 0x0000001c, 0x00030047, 0x00000011, 0x00000003, 0x00040047, 0x00000013, 0x00000022,
122 0x00000000, 0x00040047, 0x00000013, 0x00000021, 0x00000001, 0x00040047, 0x0000001d, 0x00000006, 0x00000004, 0x00050048,
123 0x0000001e, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x0000001e, 0x00000001, 0x00000023, 0x00000038, 0x00050048,
124 0x0000001e, 0x00000002, 0x00000023, 0x0000003c, 0x00040047, 0x0000001f, 0x00000006, 0x00000040, 0x00050048, 0x00000020,
125 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x00000020, 0x00000003, 0x00040047, 0x00000022, 0x00000022, 0x00000000,
126 0x00040047, 0x00000022, 0x00000021, 0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00040015,
127 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, 0x00000006, 0x0004002b, 0x00000006, 0x00000009,
128 0x00000000, 0x0003001d, 0x00000010, 0x00000006, 0x000a001e, 0x00000011, 0x00000006, 0x00000006, 0x00000006, 0x00000006,
129 0x00000006, 0x00000006, 0x00000006, 0x00000010, 0x00040020, 0x00000012, 0x00000002, 0x00000011, 0x0004003b, 0x00000012,
130 0x00000013, 0x00000002, 0x00040015, 0x00000014, 0x00000020, 0x00000001, 0x0004002b, 0x00000014, 0x00000015, 0x00000000,
131 0x00040020, 0x00000016, 0x00000002, 0x00000006, 0x00020014, 0x00000019, 0x0004002b, 0x00000006, 0x0000001c, 0x0000000e,
132 0x0004001c, 0x0000001d, 0x00000006, 0x0000001c, 0x0005001e, 0x0000001e, 0x0000001d, 0x00000006, 0x00000006, 0x0003001d,
133 0x0000001f, 0x0000001e, 0x0003001e, 0x00000020, 0x0000001f, 0x00040020, 0x00000021, 0x00000002, 0x00000020, 0x0004003b,
134 0x00000021, 0x00000022, 0x00000002, 0x0004002b, 0x00000014, 0x00000024, 0x00000001, 0x0004002b, 0x00000014, 0x00000029,
135 0x00000002, 0x00040020, 0x0000002c, 0x00000007, 0x00000019, 0x0003002a, 0x00000019, 0x0000002e, 0x0004002b, 0x00000014,
136 0x00000036, 0x00000006, 0x0004002b, 0x00000014, 0x0000003b, 0x00000007, 0x0004002b, 0x00000006, 0x0000003c, 0x00000002,
137 0x0004002b, 0x00000006, 0x00000048, 0x00000001, 0x00030029, 0x00000019, 0x00000050, 0x0004002b, 0x00000014, 0x00000058,
138 0x00000003, 0x0004002b, 0x00000014, 0x0000005d, 0x00000004, 0x0004002b, 0x00000014, 0x00000060, 0x00000005, 0x00050036,
139 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007,
140 0x0004003b, 0x00000007, 0x0000001b, 0x00000007, 0x0004003b, 0x00000007, 0x00000027, 0x00000007, 0x0004003b, 0x0000002c,
141 0x0000002d, 0x00000007, 0x0004003b, 0x00000007, 0x0000002f, 0x00000007, 0x0003003e, 0x00000008, 0x00000009, 0x000200f9,
142 0x0000000a, 0x000200f8, 0x0000000a, 0x000400f6, 0x0000000c, 0x0000000d, 0x00000000, 0x000200f9, 0x0000000e, 0x000200f8,
143 0x0000000e, 0x0004003d, 0x00000006, 0x0000000f, 0x00000008, 0x00050041, 0x00000016, 0x00000017, 0x00000013, 0x00000015,
144 0x0004003d, 0x00000006, 0x00000018, 0x00000017, 0x000500b0, 0x00000019, 0x0000001a, 0x0000000f, 0x00000018, 0x000400fa,
145 0x0000001a, 0x0000000b, 0x0000000c, 0x000200f8, 0x0000000b, 0x0004003d, 0x00000006, 0x00000023, 0x00000008, 0x00070041,
146 0x00000016, 0x00000025, 0x00000022, 0x00000015, 0x00000023, 0x00000024, 0x0004003d, 0x00000006, 0x00000026, 0x00000025,
147 0x0003003e, 0x0000001b, 0x00000026, 0x0004003d, 0x00000006, 0x00000028, 0x00000008, 0x00070041, 0x00000016, 0x0000002a,
148 0x00000022, 0x00000015, 0x00000028, 0x00000029, 0x0004003d, 0x00000006, 0x0000002b, 0x0000002a, 0x0003003e, 0x00000027,
149 0x0000002b, 0x0003003e, 0x0000002d, 0x0000002e, 0x0003003e, 0x0000002f, 0x00000009, 0x000200f9, 0x00000030, 0x000200f8,
150 0x00000030, 0x000400f6, 0x00000032, 0x00000033, 0x00000000, 0x000200f9, 0x00000034, 0x000200f8, 0x00000034, 0x0004003d,
151 0x00000006, 0x00000035, 0x0000002f, 0x00050041, 0x00000016, 0x00000037, 0x00000013, 0x00000036, 0x0004003d, 0x00000006,
152 0x00000038, 0x00000037, 0x000500b0, 0x00000019, 0x00000039, 0x00000035, 0x00000038, 0x000400fa, 0x00000039, 0x00000031,
153 0x00000032, 0x000200f8, 0x00000031, 0x0004003d, 0x00000006, 0x0000003a, 0x0000001b, 0x0004003d, 0x00000006, 0x0000003d,
154 0x0000002f, 0x00050084, 0x00000006, 0x0000003e, 0x0000003c, 0x0000003d, 0x00050080, 0x00000006, 0x0000003f, 0x0000003e,
155 0x00000009, 0x00060041, 0x00000016, 0x00000040, 0x00000013, 0x0000003b, 0x0000003f, 0x0004003d, 0x00000006, 0x00000041,
156 0x00000040, 0x000500aa, 0x00000019, 0x00000042, 0x0000003a, 0x00000041, 0x000300f7, 0x00000044, 0x00000000, 0x000400fa,
157 0x00000042, 0x00000043, 0x00000044, 0x000200f8, 0x00000043, 0x0004003d, 0x00000006, 0x00000045, 0x00000027, 0x0004003d,
158 0x00000006, 0x00000046, 0x0000002f, 0x00050084, 0x00000006, 0x00000047, 0x0000003c, 0x00000046, 0x00050080, 0x00000006,
159 0x00000049, 0x00000047, 0x00000048, 0x00060041, 0x00000016, 0x0000004a, 0x00000013, 0x0000003b, 0x00000049, 0x0004003d,
160 0x00000006, 0x0000004b, 0x0000004a, 0x000500aa, 0x00000019, 0x0000004c, 0x00000045, 0x0000004b, 0x000200f9, 0x00000044,
161 0x000200f8, 0x00000044, 0x000700f5, 0x00000019, 0x0000004d, 0x00000042, 0x00000031, 0x0000004c, 0x00000043, 0x000300f7,
162 0x0000004f, 0x00000000, 0x000400fa, 0x0000004d, 0x0000004e, 0x0000004f, 0x000200f8, 0x0000004e, 0x0003003e, 0x0000002d,
163 0x00000050, 0x000200f9, 0x00000032, 0x000200f8, 0x0000004f, 0x000200f9, 0x00000033, 0x000200f8, 0x00000033, 0x0004003d,
164 0x00000006, 0x00000052, 0x0000002f, 0x00050080, 0x00000006, 0x00000053, 0x00000052, 0x00000024, 0x0003003e, 0x0000002f,
165 0x00000053, 0x000200f9, 0x00000030, 0x000200f8, 0x00000032, 0x0004003d, 0x00000019, 0x00000054, 0x0000002d, 0x000400a8,
166 0x00000019, 0x00000055, 0x00000054, 0x000300f7, 0x00000057, 0x00000000, 0x000400fa, 0x00000055, 0x00000056, 0x00000057,
167 0x000200f8, 0x00000056, 0x00050041, 0x00000016, 0x00000059, 0x00000013, 0x00000058, 0x0004003d, 0x00000006, 0x0000005a,
168 0x00000059, 0x00050080, 0x00000006, 0x0000005b, 0x0000005a, 0x00000048, 0x00050041, 0x00000016, 0x0000005c, 0x00000013,
169 0x00000058, 0x0003003e, 0x0000005c, 0x0000005b, 0x0004003d, 0x00000006, 0x0000005e, 0x0000001b, 0x00050041, 0x00000016,
170 0x0000005f, 0x00000013, 0x0000005d, 0x0003003e, 0x0000005f, 0x0000005e, 0x0004003d, 0x00000006, 0x00000061, 0x00000027,
171 0x00050041, 0x00000016, 0x00000062, 0x00000013, 0x00000060, 0x0003003e, 0x00000062, 0x00000061, 0x0004003d, 0x00000006,
172 0x00000063, 0x00000008, 0x00050041, 0x00000016, 0x00000064, 0x00000013, 0x00000024, 0x0004003d, 0x00000006, 0x00000065,
173 0x00000064, 0x00070041, 0x00000016, 0x00000066, 0x00000022, 0x00000015, 0x00000063, 0x00000024, 0x0003003e, 0x00000066,
174 0x00000065, 0x0004003d, 0x00000006, 0x00000067, 0x00000008, 0x00050041, 0x00000016, 0x00000068, 0x00000013, 0x00000029,
175 0x0004003d, 0x00000006, 0x00000069, 0x00000068, 0x00070041, 0x00000016, 0x0000006a, 0x00000022, 0x00000015, 0x00000067,
176 0x00000029, 0x0003003e, 0x0000006a, 0x00000069, 0x000200f9, 0x00000057, 0x000200f8, 0x00000057, 0x000200f9, 0x0000000d,
177 0x000200f8, 0x0000000d, 0x0004003d, 0x00000006, 0x0000006b, 0x00000008, 0x00050080, 0x00000006, 0x0000006c, 0x0000006b,
178 0x00000024, 0x0003003e, 0x00000008, 0x0000006c, 0x000200f9, 0x0000000a, 0x000200f8, 0x0000000c, 0x000100fd, 0x00010038};
179
Karl Schultz7b024b42018-08-30 16:18:18 -0600180// Convenience function for reporting problems with setting up GPU Validation.
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700181template <typename T>
182void GpuAssisted::ReportSetupProblem(T object, const char *const specific_message) const {
183 LogError(object, "UNASSIGNED-GPU-Assisted Validation Error. ", "Detail: (%s)", specific_message);
Karl Schultz7b024b42018-08-30 16:18:18 -0600184}
185
Tony-LunarG5c38b182020-06-10 16:15:32 -0600186bool GpuAssisted::CheckForDescriptorIndexing(DeviceFeatures enabled_features) const {
187 bool result =
188 (IsExtEnabled(device_extensions.vk_ext_descriptor_indexing) &&
189 (enabled_features.core12.descriptorIndexing || enabled_features.core12.shaderInputAttachmentArrayDynamicIndexing ||
190 enabled_features.core12.shaderUniformTexelBufferArrayDynamicIndexing ||
191 enabled_features.core12.shaderStorageTexelBufferArrayDynamicIndexing ||
192 enabled_features.core12.shaderUniformBufferArrayNonUniformIndexing ||
193 enabled_features.core12.shaderSampledImageArrayNonUniformIndexing ||
194 enabled_features.core12.shaderStorageBufferArrayNonUniformIndexing ||
195 enabled_features.core12.shaderStorageImageArrayNonUniformIndexing ||
196 enabled_features.core12.shaderInputAttachmentArrayNonUniformIndexing ||
197 enabled_features.core12.shaderUniformTexelBufferArrayNonUniformIndexing ||
198 enabled_features.core12.shaderStorageTexelBufferArrayNonUniformIndexing ||
199 enabled_features.core12.descriptorBindingUniformBufferUpdateAfterBind ||
200 enabled_features.core12.descriptorBindingSampledImageUpdateAfterBind ||
201 enabled_features.core12.descriptorBindingStorageImageUpdateAfterBind ||
202 enabled_features.core12.descriptorBindingStorageBufferUpdateAfterBind ||
203 enabled_features.core12.descriptorBindingUniformTexelBufferUpdateAfterBind ||
204 enabled_features.core12.descriptorBindingStorageTexelBufferUpdateAfterBind ||
205 enabled_features.core12.descriptorBindingUpdateUnusedWhilePending ||
206 enabled_features.core12.descriptorBindingPartiallyBound ||
207 enabled_features.core12.descriptorBindingVariableDescriptorCount || enabled_features.core12.runtimeDescriptorArray));
208 return result;
209}
210
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600211void GpuAssisted::PreCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
212 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer, void *cb_state_data) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700213 // Ray tracing acceleration structure instance buffers also need the storage buffer usage as
214 // acceleration structure build validation will find and replace invalid acceleration structure
215 // handles inside of a compute shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600216 create_buffer_api_state *cb_state = reinterpret_cast<create_buffer_api_state *>(cb_state_data);
217 if (cb_state && cb_state->modified_create_info.usage & VK_BUFFER_USAGE_RAY_TRACING_BIT_NV) {
218 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
Jason Macnak83cfd582019-07-31 10:14:24 -0700219 }
220}
221
Karl Schultz7b024b42018-08-30 16:18:18 -0600222// Turn on necessary device features.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600223void GpuAssisted::PreCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info,
224 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
Mark Lobodzinskib588cd42020-09-30 11:03:34 -0600225 void *modified_create_info) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600226 DispatchGetPhysicalDeviceFeatures(gpu, &supported_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600227 VkPhysicalDeviceFeatures features = {};
228 features.vertexPipelineStoresAndAtomics = true;
229 features.fragmentStoresAndAtomics = true;
230 features.shaderInt64 = true;
Mark Lobodzinskib588cd42020-09-30 11:03:34 -0600231 UtilPreCallRecordCreateDevice(gpu, reinterpret_cast<safe_VkDeviceCreateInfo *>(modified_create_info), supported_features,
232 features);
Karl Schultz7b024b42018-08-30 16:18:18 -0600233}
Karl Schultz7b024b42018-08-30 16:18:18 -0600234// Perform initializations that can be done at Create Device time.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600235void GpuAssisted::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
236 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result) {
237 // The state tracker sets up the device state
Tony-LunarG99b880b2019-09-26 11:19:52 -0600238 ValidationStateTracker::PostCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski5dc3dcd2019-04-23 14:26:28 -0600239
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600240 ValidationObject *device_object = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
241 ValidationObject *validation_data = GetValidationObject(device_object->object_dispatch, this->container_type);
242 GpuAssisted *device_gpu_assisted = static_cast<GpuAssisted *>(validation_data);
Tony-LunarG65f9c492019-01-17 14:24:42 -0700243
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600244 const char *bufferoob_string = getLayerOption("khronos_validation.gpuav_buffer_oob");
245 if (device_gpu_assisted->enabled_features.core.robustBufferAccess ||
246 device_gpu_assisted->enabled_features.robustness2_features.robustBufferAccess2)
247 device_gpu_assisted->buffer_oob_enabled = false;
248 else
249 device_gpu_assisted->buffer_oob_enabled = *bufferoob_string ? !strcmp(bufferoob_string, "true") : true;
250
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600251 if (device_gpu_assisted->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700252 ReportSetupProblem(device, "GPU-Assisted validation requires Vulkan 1.1 or later. GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600253 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600254 return;
255 }
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600256
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600257 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700258 ReportSetupProblem(device,
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600259 "GPU-Assisted validation requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
260 "GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600261 device_gpu_assisted->aborted = true;
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600262 return;
263 }
264
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700265 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) &&
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600266 !supported_features.shaderInt64) {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700267 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
268 "shaderInt64 feature is not available. No buffer device address checking will be attempted");
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600269 }
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600270 device_gpu_assisted->shaderInt64 = supported_features.shaderInt64;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600271 device_gpu_assisted->physicalDevice = physicalDevice;
272 device_gpu_assisted->device = *pDevice;
Tony-LunarGbb145f32020-04-27 13:41:29 -0600273 device_gpu_assisted->output_buffer_size = sizeof(uint32_t) * (spvtools::kInstMaxOutCnt + 1);
Tony-LunarG5c38b182020-06-10 16:15:32 -0600274 device_gpu_assisted->descriptor_indexing = CheckForDescriptorIndexing(device_gpu_assisted->enabled_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600275 std::vector<VkDescriptorSetLayoutBinding> bindings;
276 VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
Tony-LunarGc7ed2082020-06-11 14:00:04 -0600277 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT |
278 VK_SHADER_STAGE_MESH_BIT_NV | VK_SHADER_STAGE_TASK_BIT_NV |
279 kShaderStageAllRayTracing,
Tony-LunarG1dce2392019-10-23 16:49:29 -0600280 NULL};
281 bindings.push_back(binding);
282 for (auto i = 1; i < 3; i++) {
283 binding.binding = i;
284 bindings.push_back(binding);
Karl Schultz7b024b42018-08-30 16:18:18 -0600285 }
Tony-LunarGb5fae462020-03-05 12:43:25 -0700286 UtilPostCallRecordCreateDevice(pCreateInfo, bindings, device_gpu_assisted, device_gpu_assisted->phys_dev_props);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600287 CreateAccelerationStructureBuildValidationState(device_gpu_assisted);
Karl Schultz7b024b42018-08-30 16:18:18 -0600288}
289
Tony-LunarG588c7052020-04-23 10:47:21 -0600290void GpuAssisted::PostCallRecordGetBufferDeviceAddress(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
291 VkDeviceAddress address) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600292 BUFFER_STATE *buffer_state = GetBufferState(pInfo->buffer);
293 // Validate against the size requested when the buffer was created
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600294 if (buffer_state) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600295 buffer_map[address] = buffer_state->createInfo.size;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600296 buffer_state->deviceAddress = address;
297 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600298}
299
Tony-LunarG588c7052020-04-23 10:47:21 -0600300void GpuAssisted::PostCallRecordGetBufferDeviceAddressEXT(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
301 VkDeviceAddress address) {
302 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
303}
304
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700305void GpuAssisted::PostCallRecordGetBufferDeviceAddressKHR(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
306 VkDeviceAddress address) {
Tony-LunarG588c7052020-04-23 10:47:21 -0600307 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700308}
309
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600310void GpuAssisted::PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600311 BUFFER_STATE *buffer_state = GetBufferState(buffer);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600312 if (buffer_state) buffer_map.erase(buffer_state->deviceAddress);
Tony-LunarG2966c732020-05-21 10:33:53 -0600313 ValidationStateTracker::PreCallRecordDestroyBuffer(device, buffer, pAllocator);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600314}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600315
Karl Schultz7b024b42018-08-30 16:18:18 -0600316// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600317void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600318 DestroyAccelerationStructureBuildValidationState();
Tony-LunarGb5fae462020-03-05 12:43:25 -0700319 UtilPreCallRecordDestroyDevice(this);
Tony-LunarG2966c732020-05-21 10:33:53 -0600320 ValidationStateTracker::PreCallRecordDestroyDevice(device, pAllocator);
Tony-LunarG0a863bc2020-09-16 09:50:04 -0600321 // State Tracker can end up making vma calls through callbacks - don't destroy allocator until ST is done
322 if (vmaAllocator) {
323 vmaDestroyAllocator(vmaAllocator);
324 }
325 desc_set_manager.reset();
Karl Schultz7b024b42018-08-30 16:18:18 -0600326}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600327
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600328void GpuAssisted::CreateAccelerationStructureBuildValidationState(GpuAssisted *device_gpuav) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600329 if (device_gpuav->aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700330 return;
331 }
332
Tony-LunarG99b880b2019-09-26 11:19:52 -0600333 auto &as_validation_state = device_gpuav->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700334 if (as_validation_state.initialized) {
335 return;
336 }
337
338 if (!device_extensions.vk_nv_ray_tracing) {
339 return;
340 }
341
342 // Outline:
343 // - Create valid bottom level acceleration structure which acts as replacement
344 // - Create and load vertex buffer
345 // - Create and load index buffer
346 // - Create, allocate memory for, and bind memory for acceleration structure
347 // - Query acceleration structure handle
348 // - Create command pool and command buffer
349 // - Record build acceleration structure command
350 // - Submit command buffer and wait for completion
351 // - Cleanup
352 // - Create compute pipeline for validating instance buffers
353 // - Create descriptor set layout
354 // - Create pipeline layout
355 // - Create pipeline
356 // - Cleanup
357
358 VkResult result = VK_SUCCESS;
359
360 VkBuffer vbo = VK_NULL_HANDLE;
361 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
362 if (result == VK_SUCCESS) {
363 VkBufferCreateInfo vbo_ci = {};
364 vbo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
365 vbo_ci.size = sizeof(float) * 9;
366 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
367
368 VmaAllocationCreateInfo vbo_ai = {};
369 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
370 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
371
Tony-LunarG99b880b2019-09-26 11:19:52 -0600372 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700373 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700374 ReportSetupProblem(device, "Failed to create vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700375 }
376 }
377
378 if (result == VK_SUCCESS) {
379 uint8_t *mapped_vbo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600380 result = vmaMapMemory(device_gpuav->vmaAllocator, vbo_allocation, (void **)&mapped_vbo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700381 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700382 ReportSetupProblem(device, "Failed to map vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700383 } else {
384 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
385 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600386 vmaUnmapMemory(device_gpuav->vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700387 }
388 }
389
390 VkBuffer ibo = VK_NULL_HANDLE;
391 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
392 if (result == VK_SUCCESS) {
393 VkBufferCreateInfo ibo_ci = {};
394 ibo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
395 ibo_ci.size = sizeof(uint32_t) * 3;
396 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
397
398 VmaAllocationCreateInfo ibo_ai = {};
399 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
400 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
401
Tony-LunarG99b880b2019-09-26 11:19:52 -0600402 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700403 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700404 ReportSetupProblem(device, "Failed to create index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700405 }
406 }
407
408 if (result == VK_SUCCESS) {
409 uint8_t *mapped_ibo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600410 result = vmaMapMemory(device_gpuav->vmaAllocator, ibo_allocation, (void **)&mapped_ibo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700411 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700412 ReportSetupProblem(device, "Failed to map index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700413 } else {
414 const std::vector<uint32_t> indicies = {0, 1, 2};
415 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600416 vmaUnmapMemory(device_gpuav->vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700417 }
418 }
419
420 VkGeometryNV geometry = {};
421 geometry.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
422 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
423 geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
424 geometry.geometry.triangles.vertexData = vbo;
425 geometry.geometry.triangles.vertexOffset = 0;
426 geometry.geometry.triangles.vertexCount = 3;
427 geometry.geometry.triangles.vertexStride = 12;
428 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
429 geometry.geometry.triangles.indexData = ibo;
430 geometry.geometry.triangles.indexOffset = 0;
431 geometry.geometry.triangles.indexCount = 3;
432 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
433 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
434 geometry.geometry.triangles.transformOffset = 0;
435 geometry.geometry.aabbs = {};
436 geometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
437
438 VkAccelerationStructureCreateInfoNV as_ci = {};
439 as_ci.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
440 as_ci.info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
441 as_ci.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV;
442 as_ci.info.instanceCount = 0;
443 as_ci.info.geometryCount = 1;
444 as_ci.info.pGeometries = &geometry;
445 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600446 result = DispatchCreateAccelerationStructureNV(device_gpuav->device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700447 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700448 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700449 "Failed to create acceleration structure for acceleration structure build validation.");
450 }
451 }
452
453 VkMemoryRequirements2 as_mem_requirements = {};
454 if (result == VK_SUCCESS) {
455 VkAccelerationStructureMemoryRequirementsInfoNV as_mem_requirements_info = {};
456 as_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
457 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
458 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
459
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600460 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700461 }
462
463 VmaAllocationInfo as_memory_ai = {};
464 if (result == VK_SUCCESS) {
465 VmaAllocationCreateInfo as_memory_aci = {};
466 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
467
Tony-LunarG99b880b2019-09-26 11:19:52 -0600468 result = vmaAllocateMemory(device_gpuav->vmaAllocator, &as_mem_requirements.memoryRequirements, &as_memory_aci,
469 &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700470 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700471 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700472 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
473 }
474 }
475
476 if (result == VK_SUCCESS) {
477 VkBindAccelerationStructureMemoryInfoNV as_bind_info = {};
478 as_bind_info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
479 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
480 as_bind_info.memory = as_memory_ai.deviceMemory;
481 as_bind_info.memoryOffset = as_memory_ai.offset;
482
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600483 result = DispatchBindAccelerationStructureMemoryNV(device_gpuav->device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700484 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700485 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700486 "Failed to bind acceleration structure memory for acceleration structure build validation.");
487 }
488 }
489
490 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600491 result = DispatchGetAccelerationStructureHandleNV(device_gpuav->device, as_validation_state.replacement_as,
492 sizeof(uint64_t), &as_validation_state.replacement_as_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700493 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700494 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700495 "Failed to get acceleration structure handle for acceleration structure build validation.");
496 }
497 }
498
499 VkMemoryRequirements2 scratch_mem_requirements = {};
500 if (result == VK_SUCCESS) {
501 VkAccelerationStructureMemoryRequirementsInfoNV scratch_mem_requirements_info = {};
502 scratch_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
503 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
504 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
505
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600506 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &scratch_mem_requirements_info,
507 &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700508 }
509
510 VkBuffer scratch = VK_NULL_HANDLE;
Tony-LunarG18900282020-05-20 12:34:33 -0600511 VmaAllocation scratch_allocation = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700512 if (result == VK_SUCCESS) {
513 VkBufferCreateInfo scratch_ci = {};
514 scratch_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
515 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
516 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
Jason Macnak83cfd582019-07-31 10:14:24 -0700517 VmaAllocationCreateInfo scratch_aci = {};
518 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
519
Tony-LunarG18900282020-05-20 12:34:33 -0600520 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &scratch_ci, &scratch_aci, &scratch, &scratch_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700521 if (result != VK_SUCCESS) {
Tony-LunarG18900282020-05-20 12:34:33 -0600522 ReportSetupProblem(device_gpuav->device,
523 "Failed to create scratch buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700524 }
525 }
526
527 VkCommandPool command_pool = VK_NULL_HANDLE;
528 if (result == VK_SUCCESS) {
529 VkCommandPoolCreateInfo command_pool_ci = {};
530 command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
531 command_pool_ci.queueFamilyIndex = 0;
532
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600533 result = DispatchCreateCommandPool(device_gpuav->device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700534 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700535 ReportSetupProblem(device_gpuav->device, "Failed to create command pool for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700536 }
537 }
538
539 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
540
541 if (result == VK_SUCCESS) {
542 VkCommandBufferAllocateInfo command_buffer_ai = {};
543 command_buffer_ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
544 command_buffer_ai.commandPool = command_pool;
545 command_buffer_ai.commandBufferCount = 1;
546 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
547
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600548 result = DispatchAllocateCommandBuffers(device_gpuav->device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700549 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700550 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700551 "Failed to create command buffer for acceleration structure build validation.");
552 }
553
554 // Hook up command buffer dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600555 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700556 }
557
558 if (result == VK_SUCCESS) {
559 VkCommandBufferBeginInfo command_buffer_bi = {};
560 command_buffer_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
561
562 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
563 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700564 ReportSetupProblem(device_gpuav->device, "Failed to begin command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700565 }
566 }
567
568 if (result == VK_SUCCESS) {
569 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
570 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
571 DispatchEndCommandBuffer(command_buffer);
572 }
573
574 VkQueue queue = VK_NULL_HANDLE;
575 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600576 DispatchGetDeviceQueue(device_gpuav->device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700577
578 // Hook up queue dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600579 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700580
581 VkSubmitInfo submit_info = {};
582 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
583 submit_info.commandBufferCount = 1;
584 submit_info.pCommandBuffers = &command_buffer;
585 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
586 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700587 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700588 "Failed to submit command buffer for acceleration structure build validation.");
589 }
590 }
591
592 if (result == VK_SUCCESS) {
593 result = DispatchQueueWaitIdle(queue);
594 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700595 ReportSetupProblem(device_gpuav->device, "Failed to wait for queue idle for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700596 }
597 }
598
599 if (vbo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600600 vmaDestroyBuffer(device_gpuav->vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700601 }
602 if (ibo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600603 vmaDestroyBuffer(device_gpuav->vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700604 }
605 if (scratch != VK_NULL_HANDLE) {
Tony-LunarG18900282020-05-20 12:34:33 -0600606 vmaDestroyBuffer(device_gpuav->vmaAllocator, scratch, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700607 }
608 if (command_pool != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600609 DispatchDestroyCommandPool(device_gpuav->device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700610 }
611
Tony-LunarG99b880b2019-09-26 11:19:52 -0600612 if (device_gpuav->debug_desc_layout == VK_NULL_HANDLE) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700613 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700614 "Failed to find descriptor set layout for acceleration structure build validation.");
615 result = VK_INCOMPLETE;
616 }
617
618 if (result == VK_SUCCESS) {
619 VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
620 pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
621 pipeline_layout_ci.setLayoutCount = 1;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600622 pipeline_layout_ci.pSetLayouts = &device_gpuav->debug_desc_layout;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600623 result = DispatchCreatePipelineLayout(device_gpuav->device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700624 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700625 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700626 "Failed to create pipeline layout for acceleration structure build validation.");
627 }
628 }
629
630 VkShaderModule shader_module = VK_NULL_HANDLE;
631 if (result == VK_SUCCESS) {
632 VkShaderModuleCreateInfo shader_module_ci = {};
633 shader_module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
634 shader_module_ci.codeSize = sizeof(kComputeShaderSpirv);
635 shader_module_ci.pCode = (uint32_t *)kComputeShaderSpirv;
636
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600637 result = DispatchCreateShaderModule(device_gpuav->device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700638 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700639 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700640 "Failed to create compute shader module for acceleration structure build validation.");
641 }
642 }
643
644 if (result == VK_SUCCESS) {
645 VkPipelineShaderStageCreateInfo pipeline_stage_ci = {};
646 pipeline_stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
647 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
648 pipeline_stage_ci.module = shader_module;
649 pipeline_stage_ci.pName = "main";
650
651 VkComputePipelineCreateInfo pipeline_ci = {};
652 pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
653 pipeline_ci.stage = pipeline_stage_ci;
654 pipeline_ci.layout = as_validation_state.pipeline_layout;
655
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600656 result = DispatchCreateComputePipelines(device_gpuav->device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr,
657 &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700658 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700659 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700660 "Failed to create compute pipeline for acceleration structure build validation.");
661 }
662 }
663
664 if (shader_module != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600665 DispatchDestroyShaderModule(device_gpuav->device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700666 }
667
668 if (result == VK_SUCCESS) {
669 as_validation_state.initialized = true;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700670 LogInfo(device_gpuav->device, "UNASSIGNED-GPU-Assisted Validation.",
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600671 "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700672 } else {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600673 device_gpuav->aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700674 }
675}
676
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600677void GpuAssisted::DestroyAccelerationStructureBuildValidationState() {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600678 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700679 if (as_validation_state.pipeline != VK_NULL_HANDLE) {
680 DispatchDestroyPipeline(device, as_validation_state.pipeline, nullptr);
681 }
682 if (as_validation_state.pipeline_layout != VK_NULL_HANDLE) {
683 DispatchDestroyPipelineLayout(device, as_validation_state.pipeline_layout, nullptr);
684 }
685 if (as_validation_state.replacement_as != VK_NULL_HANDLE) {
686 DispatchDestroyAccelerationStructureNV(device, as_validation_state.replacement_as, nullptr);
687 }
688 if (as_validation_state.replacement_as_allocation != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600689 vmaFreeMemory(vmaAllocator, as_validation_state.replacement_as_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700690 }
691}
692
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600693struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700694 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
695 VkPipeline pipeline = VK_NULL_HANDLE;
696 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
697 std::vector<VkDescriptorSet> descriptor_sets;
698 std::vector<std::vector<uint32_t>> dynamic_offsets;
699 uint32_t push_descriptor_set_index = 0;
700 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
701 std::vector<uint8_t> push_constants_data;
702 PushConstantRangesId push_constants_ranges;
703
704 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
705 pipeline_bind_point = bind_point;
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600706 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
Jason Macnak83cfd582019-07-31 10:14:24 -0700707
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600708 LAST_BOUND_STATE &last_bound = cb_state->lastBound[lv_bind_point];
Jason Macnak83cfd582019-07-31 10:14:24 -0700709 if (last_bound.pipeline_state) {
710 pipeline = last_bound.pipeline_state->pipeline;
711 pipeline_layout = last_bound.pipeline_layout;
712 descriptor_sets.reserve(last_bound.per_set.size());
713 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
714 const auto *bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
715
716 descriptor_sets.push_back(bound_descriptor_set->GetSet());
717 if (bound_descriptor_set->IsPushDescriptor()) {
718 push_descriptor_set_index = static_cast<uint32_t>(i);
719 }
720 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
721 }
722
723 if (last_bound.push_descriptor_set) {
724 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
725 }
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500726 if (last_bound.pipeline_state->pipeline_layout->push_constant_ranges == cb_state->push_constant_data_ranges) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700727 push_constants_data = cb_state->push_constant_data;
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500728 push_constants_ranges = last_bound.pipeline_state->pipeline_layout->push_constant_ranges;
Jason Macnak83cfd582019-07-31 10:14:24 -0700729 }
730 }
731 }
732
733 void Restore(VkCommandBuffer command_buffer) const {
734 if (pipeline != VK_NULL_HANDLE) {
735 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
736 if (!descriptor_sets.empty()) {
737 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
738 VkDescriptorSet descriptor_set = descriptor_sets[i];
739 if (descriptor_set != VK_NULL_HANDLE) {
740 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
741 static_cast<uint32_t>(i), 1, &descriptor_set,
742 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
743 }
744 }
745 }
746 if (!push_descriptor_set_writes.empty()) {
747 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
748 static_cast<uint32_t>(push_descriptor_set_writes.size()),
749 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
750 }
751 for (const auto &push_constant_range : *push_constants_ranges) {
752 if (push_constant_range.size == 0) continue;
753 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
754 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
755 }
756 }
757 }
758};
759
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600760void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
761 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
762 VkDeviceSize instanceOffset, VkBool32 update,
763 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
764 VkBuffer scratch, VkDeviceSize scratchOffset) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700765 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
766 return;
767 }
768
Tony-LunarG99b880b2019-09-26 11:19:52 -0600769 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700770 if (!as_validation_state.initialized) {
771 return;
772 }
773
774 // Empty acceleration structure is valid according to the spec.
775 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
776 return;
777 }
778
779 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
780 assert(cb_state != nullptr);
781
782 std::vector<uint64_t> current_valid_handles;
783 for (const auto &as_state_kv : accelerationStructureMap) {
784 const ACCELERATION_STRUCTURE_STATE &as_state = *as_state_kv.second;
Jeff Bolz95176d02020-04-01 00:36:16 -0500785 if (as_state.built && as_state.create_infoNV.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700786 current_valid_handles.push_back(as_state.opaque_handle);
787 }
788 }
789
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600790 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700791 as_validation_buffer_info.acceleration_structure = dst;
792
793 const VkDeviceSize validation_buffer_size =
794 // One uint for number of instances to validate
795 4 +
796 // Two uint for the replacement acceleration structure handle
797 8 +
798 // One uint for number of invalid handles found
799 4 +
800 // Two uint for the first invalid handle found
801 8 +
802 // One uint for the number of current valid handles
803 4 +
804 // Two uint for each current valid handle
805 (8 * current_valid_handles.size());
806
807 VkBufferCreateInfo validation_buffer_create_info = {};
808 validation_buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
809 validation_buffer_create_info.size = validation_buffer_size;
810 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
811
812 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
813 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
814
Tony-LunarG99b880b2019-09-26 11:19:52 -0600815 VkResult result = vmaCreateBuffer(vmaAllocator, &validation_buffer_create_info, &validation_buffer_alloc_info,
816 &as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -0700817 &as_validation_buffer_info.validation_buffer_allocation, nullptr);
818 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700819 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600820 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700821 return;
822 }
823
824 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600825 result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700826 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700827 ReportSetupProblem(device, "Unable to allocate device memory for acceleration structure build val buffer.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600828 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700829 return;
830 }
831
832 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
833 mapped_validation_buffer->replacement_handle_bits_0 =
834 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
835 mapped_validation_buffer->replacement_handle_bits_1 =
836 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
837 mapped_validation_buffer->invalid_handle_found = 0;
838 mapped_validation_buffer->invalid_handle_bits_0 = 0;
839 mapped_validation_buffer->invalid_handle_bits_1 = 0;
840 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
841
842 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
843 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
844 const uint64_t current_valid_handle = current_valid_handles[i];
845
846 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
847 ++mapped_valid_handles;
848 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
849 ++mapped_valid_handles;
850 }
851
Tony-LunarG99b880b2019-09-26 11:19:52 -0600852 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700853
854 static constexpr const VkDeviceSize kInstanceSize = 64;
855 const VkDeviceSize instance_buffer_size = kInstanceSize * pInfo->instanceCount;
856
Tony-LunarG1dce2392019-10-23 16:49:29 -0600857 result = desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool, debug_desc_layout,
858 &as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700859 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700860 ReportSetupProblem(device, "Unable to get descriptor set for acceleration structure build.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600861 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700862 return;
863 }
864
865 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
866 descriptor_buffer_infos[0].buffer = instanceData;
867 descriptor_buffer_infos[0].offset = instanceOffset;
868 descriptor_buffer_infos[0].range = instance_buffer_size;
869 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.validation_buffer;
870 descriptor_buffer_infos[1].offset = 0;
871 descriptor_buffer_infos[1].range = validation_buffer_size;
872
873 VkWriteDescriptorSet descriptor_set_writes[2] = {};
874 descriptor_set_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
875 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
876 descriptor_set_writes[0].dstBinding = 0;
877 descriptor_set_writes[0].descriptorCount = 1;
878 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
879 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
880 descriptor_set_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
881 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
882 descriptor_set_writes[1].dstBinding = 1;
883 descriptor_set_writes[1].descriptorCount = 1;
884 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
885 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
886
887 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
888
889 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
890 VkMemoryBarrier memory_barrier = {};
891 memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
892 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
893 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
894 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
895 &memory_barrier, 0, nullptr, 0, nullptr);
896
897 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600898 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700899 restorable_state.Create(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
900
901 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
902 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
903 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
904 &as_validation_buffer_info.descriptor_set, 0, nullptr);
905 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
906
907 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
908 // have been replaced by the validation compute shader before any builds take place.
909 VkBufferMemoryBarrier instance_buffer_barrier = {};
910 instance_buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
911 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
912 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
913 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
914 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
915 instance_buffer_barrier.buffer = instanceData;
916 instance_buffer_barrier.offset = instanceOffset;
917 instance_buffer_barrier.size = instance_buffer_size;
918 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
919 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
920 nullptr);
921
922 // Restore the previous compute pipeline state.
923 restorable_state.Restore(commandBuffer);
924
925 as_validation_state.validation_buffers[commandBuffer].push_back(std::move(as_validation_buffer_info));
926}
927
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600928void GpuAssisted::ProcessAccelerationStructureBuildValidationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700929 if (cb_node == nullptr || !cb_node->hasBuildAccelerationStructureCmd) {
930 return;
931 }
932
Tony-LunarG99b880b2019-09-26 11:19:52 -0600933 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700934 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[cb_node->commandBuffer];
935 for (const auto &as_validation_buffer_info : as_validation_buffer_infos) {
936 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
937
Tony-LunarG99b880b2019-09-26 11:19:52 -0600938 VkResult result =
939 vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700940 if (result == VK_SUCCESS) {
941 if (mapped_validation_buffer->invalid_handle_found > 0) {
942 uint64_t invalid_handle = 0;
943 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
944 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
945
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700946 LogError(as_validation_buffer_info.acceleration_structure, "UNASSIGNED-AccelerationStructure",
947 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
948 "handle (%" PRIu64 ")",
949 invalid_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700950 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600951 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700952 }
953 }
954}
955
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600956void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
957 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
958 VkResult result) {
959 if (VK_SUCCESS != result) return;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600960 ValidationStateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600961 for (uint32_t i = 0; i < bindInfoCount; i++) {
962 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
sourav parmarcd5fb182020-07-17 12:58:44 -0700963 ACCELERATION_STRUCTURE_STATE *as_state = GetAccelerationStructureStateNV(info.accelerationStructure);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600964 if (as_state) {
965 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
966 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600967 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600968}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700969
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600970// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
971void GpuAssisted::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
972 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
973 void *cpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600974 if (aborted) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600975 return;
976 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600977
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600978 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
979
Tony-LunarG99b880b2019-09-26 11:19:52 -0600980 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600981 std::ostringstream strm;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600982 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Karl Schultz7b024b42018-08-30 16:18:18 -0600983 << "Application has too many descriptor sets in the pipeline layout to continue with gpu validation. "
984 << "Validation is not modifying the pipeline layout. "
985 << "Instrumented shaders are replaced with non-instrumented shaders.";
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700986 ReportSetupProblem(device, strm.str().c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -0600987 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700988 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Karl Schultz7b024b42018-08-30 16:18:18 -0600989 }
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700990}
991
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600992void GpuAssisted::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
993 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
994 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600995 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
996
Karl Schultz7b024b42018-08-30 16:18:18 -0600997 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700998 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600999 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -06001000 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001001}
1002
Karl Schultz7b024b42018-08-30 16:18:18 -06001003// Free the device memory and descriptor set associated with a command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001004void GpuAssisted::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001005 if (aborted) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001006 return;
1007 }
Tony-LunarG1dce2392019-10-23 16:49:29 -06001008 auto gpuav_buffer_list = GetBufferInfo(commandBuffer);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001009 for (auto buffer_info : gpuav_buffer_list) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001010 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001011 if (buffer_info.di_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001012 vmaDestroyBuffer(vmaAllocator, buffer_info.di_input_mem_block.buffer, buffer_info.di_input_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001013 }
1014 if (buffer_info.bda_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001015 vmaDestroyBuffer(vmaAllocator, buffer_info.bda_input_mem_block.buffer, buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -06001016 }
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001017 if (buffer_info.desc_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001018 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001019 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001020 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001021 command_buffer_map.erase(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001022
Tony-LunarG99b880b2019-09-26 11:19:52 -06001023 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001024 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[commandBuffer];
1025 for (auto &as_validation_buffer_info : as_validation_buffer_infos) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001026 vmaDestroyBuffer(vmaAllocator, as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -07001027 as_validation_buffer_info.validation_buffer_allocation);
1028
1029 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001030 desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool,
1031 as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -07001032 }
1033 }
1034 as_validation_info.validation_buffers.erase(commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -06001035}
Karl Schultz7b024b42018-08-30 16:18:18 -06001036// Just gives a warning about a possible deadlock.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001037bool GpuAssisted::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
1038 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
1039 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1040 uint32_t bufferMemoryBarrierCount,
1041 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
Jeff Bolz5c801d12019-10-09 10:38:45 -05001042 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001043 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001044 ReportSetupProblem(commandBuffer,
Karl Schultz7b024b42018-08-30 16:18:18 -06001045 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1046 "GPU_Assisted validation waits on queue completion. "
1047 "This wait could block the host's signaling of this event, resulting in deadlock.");
1048 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001049 return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001050}
1051
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001052void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1053 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
1054 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -06001055 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001056 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
1057 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
1058 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001059 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1060 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001061 }
1062 }
1063}
1064
1065void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1066 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
1067 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -06001068 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001069 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
1070 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
1071 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001072 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1073 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001074 }
1075 }
1076}
1077
1078void GpuAssisted::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1079 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1080 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1081 void *cgpl_state_data) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001082 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001083 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001084 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
1085 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001086 cgpl_state->gpu_create_infos = new_pipeline_create_infos;
1087 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001088}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001089
1090void GpuAssisted::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1091 const VkComputePipelineCreateInfo *pCreateInfos,
1092 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1093 void *ccpl_state_data) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001094 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001095 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001096 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
1097 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001098 ccpl_state->gpu_create_infos = new_pipeline_create_infos;
1099 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
Jason Macnak67407e72019-07-11 11:05:09 -07001100}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001101
1102void GpuAssisted::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1103 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1104 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1105 void *crtpl_state_data) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001106 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001107 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001108 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1109 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001110 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1111 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001112}
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001113
sourav parmarcd5fb182020-07-17 12:58:44 -07001114void GpuAssisted::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
1115 VkPipelineCache pipelineCache, uint32_t count,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001116 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1117 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1118 void *crtpl_state_data) {
1119 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
1120 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001121 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1122 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001123 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1124 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->gpu_create_infos.data());
1125}
Karl Schultz7b024b42018-08-30 16:18:18 -06001126
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001127void GpuAssisted::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1128 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1129 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1130 VkResult result, void *cgpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001131 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
1132 pPipelines, result, cgpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001133 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
1134 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, cgpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001135 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001136}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001137
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001138void GpuAssisted::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1139 const VkComputePipelineCreateInfo *pCreateInfos,
1140 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1141 VkResult result, void *ccpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001142 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1143 result, ccpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001144 create_compute_pipeline_api_state *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
1145 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, ccpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001146 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001147}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001148
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001149void GpuAssisted::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1150 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1151 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1152 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001153 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001154 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
1155 pPipelines, result, crtpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001156 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001157 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Jason Macnak67407e72019-07-11 11:05:09 -07001158}
1159
sourav parmarcd5fb182020-07-17 12:58:44 -07001160void GpuAssisted::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
1161 VkPipelineCache pipelineCache, uint32_t count,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001162 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1163 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1164 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001165 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
sourav parmarcd5fb182020-07-17 12:58:44 -07001166 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesKHR(
1167 device, deferredOperation, pipelineCache, count, pCreateInfos, pAllocator, pPipelines, result, crtpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001168 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001169 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Karl Schultz7b024b42018-08-30 16:18:18 -06001170}
1171
1172// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001173void GpuAssisted::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001174 for (auto it = shader_map.begin(); it != shader_map.end();) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001175 if (it->second.pipeline == pipeline) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001176 it = shader_map.erase(it);
Karl Schultz7b024b42018-08-30 16:18:18 -06001177 } else {
1178 ++it;
1179 }
1180 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001181 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001182}
1183
1184// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001185bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
1186 uint32_t *unique_shader_id) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001187 if (aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001188 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
1189
Tony-LunarG79641702020-07-13 15:43:05 -06001190 const spvtools::MessageConsumer GpuConsoleMessageConsumer =
1191 [this](spv_message_level_t level, const char *, const spv_position_t &position, const char *message) -> void {
1192 switch (level) {
1193 case SPV_MSG_FATAL:
1194 case SPV_MSG_INTERNAL_ERROR:
1195 case SPV_MSG_ERROR:
1196 this->LogError(this->device, "UNASSIGNED-GPU-Assisted", "Error during shader instrumentation: line %zu: %s",
1197 position.index, message);
1198 break;
1199 default:
1200 break;
1201 }
1202 };
1203
Karl Schultz7b024b42018-08-30 16:18:18 -06001204 // Load original shader SPIR-V
1205 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
1206 new_pgm.clear();
1207 new_pgm.reserve(num_words);
1208 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
1209
1210 // Call the optimizer to instrument the shader.
1211 // Use the unique_shader_module_id as a shader ID so we can look up its handle later in the shader_map.
Tony-LunarGa77cade2019-03-06 10:49:22 -07001212 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Karl Schultz7b024b42018-08-30 16:18:18 -06001213 using namespace spvtools;
Tony-LunarG8a51b7d2020-07-01 15:57:23 -06001214 spv_target_env target_env = PickSpirvEnv(api_version, (device_extensions.vk_khr_spirv_1_4 != kNotEnabled));
Tony-LunarGf29f77f2020-08-26 15:48:00 -06001215 spvtools::ValidatorOptions val_options;
1216 AdjustValidatorOptions(device_extensions, enabled_features, val_options);
1217 spvtools::OptimizerOptions opt_options;
1218 opt_options.set_run_validator(true);
1219 opt_options.set_validator_options(val_options);
Karl Schultz7b024b42018-08-30 16:18:18 -06001220 Optimizer optimizer(target_env);
Tony-LunarG79641702020-07-13 15:43:05 -06001221 optimizer.SetMessageConsumer(GpuConsoleMessageConsumer);
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001222 optimizer.RegisterPass(CreateInstBindlessCheckPass(desc_set_bind_index, unique_shader_module_id, descriptor_indexing,
Tony-LunarGe8632e42020-11-18 17:03:12 -07001223 descriptor_indexing, buffer_oob_enabled, buffer_oob_enabled));
Karl Schultz7b024b42018-08-30 16:18:18 -06001224 optimizer.RegisterPass(CreateAggressiveDCEPass());
Tony-LunarG5c38b182020-06-10 16:15:32 -06001225 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) && shaderInt64 &&
1226 enabled_features.core12.bufferDeviceAddress)
Tony-LunarG99b880b2019-09-26 11:19:52 -06001227 optimizer.RegisterPass(CreateInstBuffAddrCheckPass(desc_set_bind_index, unique_shader_module_id));
Tony-LunarGf29f77f2020-08-26 15:48:00 -06001228 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm, opt_options);
Karl Schultz7b024b42018-08-30 16:18:18 -06001229 if (!pass) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001230 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Karl Schultz7b024b42018-08-30 16:18:18 -06001231 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001232 *unique_shader_id = unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -06001233 return pass;
1234}
Mark Lobodzinski01734072019-02-13 17:39:15 -07001235// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001236void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
1237 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
1238 void *csm_state_data) {
1239 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
1240 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -06001241 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001242 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
1243 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
Karl Schultz7b024b42018-08-30 16:18:18 -06001244 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001245}
1246
Karl Schultz7b024b42018-08-30 16:18:18 -06001247// Generate the part of the message describing the violation.
1248static void GenerateValidationMessage(const uint32_t *debug_record, std::string &msg, std::string &vuid_msg) {
1249 using namespace spvtools;
1250 std::ostringstream strm;
Tony-LunarGab47cac2019-12-20 15:28:01 -07001251 switch (debug_record[kInstValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001252 case kInstErrorBindlessBounds: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001253 strm << "Index of " << debug_record[kInstBindlessBoundsOutDescIndex] << " used to index descriptor array of length "
1254 << debug_record[kInstBindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001255 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -06001256 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001257 case kInstErrorBindlessUninit: {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001258 strm << "Descriptor index " << debug_record[kInstBindlessUninitOutDescIndex] << " is uninitialized.";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001259 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -06001260 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001261 case kInstErrorBuffAddrUnallocRef: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001262 uint64_t *ptr = (uint64_t *)&debug_record[kInstBuffAddrUnallocOutDescPtrLo];
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001263 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
1264 vuid_msg = "UNASSIGNED-Device address out of bounds";
1265 } break;
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001266 case kInstErrorBindlessBuffOOB: {
1267 auto size = debug_record[kInstBindlessBuffOOBOutBuffSize];
1268 if (size == 0) {
1269 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex] << " is uninitialized.";
1270 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
1271 } else {
1272 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex]
1273 << " access out of bounds. Descriptor size is " << debug_record[kInstBindlessBuffOOBOutBuffSize]
Tony-LunarGe8632e42020-11-18 17:03:12 -07001274 << " units (bytes or texels) and highest unit accessed was " << debug_record[kInstBindlessBuffOOBOutBuffOff];
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001275 vuid_msg = "UNASSIGNED-Descriptor access out of bounds";
1276 }
1277 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001278 default: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001279 strm << "Internal Error (unexpected error type = " << debug_record[kInstValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001280 vuid_msg = "UNASSIGNED-Internal Error";
1281 assert(false);
1282 } break;
1283 }
1284 msg = strm.str();
1285}
1286
Karl Schultz7b024b42018-08-30 16:18:18 -06001287// Pull together all the information from the debug record to build the error message strings,
1288// and then assemble them into a single message string.
1289// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
1290// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
1291// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
1292// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
1293//
Tony-LunarG1dce2392019-10-23 16:49:29 -06001294void GpuAssisted::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, VkPipelineBindPoint pipeline_bind_point,
1295 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001296 using namespace spvtools;
1297 const uint32_t total_words = debug_output_buffer[0];
1298 // A zero here means that the shader instrumentation didn't write anything.
1299 // If you have nothing to say, don't say it here.
1300 if (0 == total_words) {
1301 return;
1302 }
1303 // The first word in the debug output buffer is the number of words that would have
1304 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
1305 // The number of words actually written by the shaders is determined by the size of the buffer
1306 // we provide via the descriptor. So, we process only the number of words that can fit in the
1307 // buffer.
1308 // Each "report" written by the shader instrumentation is considered a "record". This function
1309 // is hard-coded to process only one record because it expects the buffer to be large enough to
1310 // hold only one record. If there is a desire to process more than one record, this function needs
1311 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06001312 std::string validation_message;
1313 std::string stage_message;
1314 std::string common_message;
1315 std::string filename_message;
1316 std::string source_message;
1317 std::string vuid_msg;
1318 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
1319 VkPipeline pipeline_handle = VK_NULL_HANDLE;
1320 std::vector<unsigned int> pgm;
1321 // The first record starts at this offset after the total_words.
1322 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
1323 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
1324 // by the instrumented shader.
Tony-LunarG99b880b2019-09-26 11:19:52 -06001325 auto it = shader_map.find(debug_record[kInstCommonOutShaderId]);
1326 if (it != shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001327 shader_module_handle = it->second.shader_module;
1328 pipeline_handle = it->second.pipeline;
1329 pgm = it->second.pgm;
1330 }
1331 GenerateValidationMessage(debug_record, validation_message, vuid_msg);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001332 UtilGenerateStageMessage(debug_record, stage_message);
1333 UtilGenerateCommonMessage(report_data, command_buffer, debug_record, shader_module_handle, pipeline_handle, pipeline_bind_point,
1334 operation_index, common_message);
1335 UtilGenerateSourceMessages(pgm, debug_record, false, filename_message, source_message);
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001336 LogError(queue, vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
1337 filename_message.c_str(), source_message.c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -06001338 // The debug record at word kInstCommonOutSize is the number of words in the record
1339 // written by the shader. Clear the entire record plus the total_words word at the start.
Tony-LunarGab47cac2019-12-20 15:28:01 -07001340 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], (uint32_t)kInstMaxOutCnt);
Karl Schultz7b024b42018-08-30 16:18:18 -06001341 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
1342}
1343
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001344void GpuAssisted::SetDescriptorInitialized(uint32_t *pData, uint32_t index, const cvdescriptorset::Descriptor *descriptor) {
1345 if (descriptor->GetClass() == cvdescriptorset::DescriptorClass::GeneralBuffer) {
1346 auto buffer = static_cast<const cvdescriptorset::BufferDescriptor *>(descriptor)->GetBuffer();
1347 if (buffer == VK_NULL_HANDLE)
1348 pData[index] = UINT_MAX;
1349 else {
1350 auto buffer_state = static_cast<const cvdescriptorset::BufferDescriptor *>(descriptor)->GetBufferState();
1351 pData[index] = static_cast<uint32_t>(buffer_state->createInfo.size);
1352 }
1353 } else if (descriptor->GetClass() == cvdescriptorset::DescriptorClass::TexelBuffer) {
1354 auto buffer_view = static_cast<const cvdescriptorset::TexelDescriptor *>(descriptor)->GetBufferView();
1355 if (buffer_view == VK_NULL_HANDLE)
1356 pData[index] = UINT_MAX;
1357 else {
1358 auto buffer_view_state = static_cast<const cvdescriptorset::TexelDescriptor *>(descriptor)->GetBufferViewState();
1359 pData[index] = static_cast<uint32_t>(buffer_view_state->buffer_state->createInfo.size);
1360 }
1361 } else {
1362 pData[index] = 1;
1363 }
1364}
1365
Tony-LunarG81efe392019-03-07 15:43:27 -07001366// For the given command buffer, map its debug data buffers and update the status of any update after bind descriptors
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001367void GpuAssisted::UpdateInstrumentationBuffer(CMD_BUFFER_STATE *cb_node) {
Tony-LunarG1dce2392019-10-23 16:49:29 -06001368 auto gpu_buffer_list = GetBufferInfo(cb_node->commandBuffer);
Tony-LunarG81efe392019-03-07 15:43:27 -07001369 uint32_t *pData;
1370 for (auto &buffer_info : gpu_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001371 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001372 VkResult result = vmaMapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation, (void **)&pData);
Tony-LunarG81efe392019-03-07 15:43:27 -07001373 if (result == VK_SUCCESS) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001374 for (auto update : buffer_info.di_input_mem_block.update_at_submit) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001375 if (update.second->updated) {
1376 SetDescriptorInitialized(pData, update.first, update.second);
1377 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001378 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001379 vmaUnmapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07001380 }
1381 }
1382 }
1383}
1384
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001385void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001386 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1387 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1388 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001389 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07001390 UpdateInstrumentationBuffer(cb_node);
1391 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
1392 UpdateInstrumentationBuffer(secondaryCmdBuffer);
1393 }
1394 }
1395 }
1396}
1397
Karl Schultz58674242019-01-22 15:35:02 -07001398// Issue a memory barrier to make GPU-written data available to host.
1399// Wait for the queue to complete execution.
1400// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001401void GpuAssisted::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
1402 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001403 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001404
Mark Lobodzinski09379db2020-05-07 08:22:01 -06001405 if (aborted || (result != VK_SUCCESS)) return;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001406 bool buffers_present = false;
1407 // Don't QueueWaitIdle if there's nothing to process
1408 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1409 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1410 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
1411 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG1dce2392019-10-23 16:49:29 -06001412 if (GetBufferInfo(cb_node->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd) buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001413 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarG1dce2392019-10-23 16:49:29 -06001414 if (GetBufferInfo(secondaryCmdBuffer->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd)
Jason Macnak83cfd582019-07-31 10:14:24 -07001415 buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001416 }
1417 }
1418 }
1419 if (!buffers_present) return;
Karl Schultz58674242019-01-22 15:35:02 -07001420
Tony-LunarGb5fae462020-03-05 12:43:25 -07001421 UtilSubmitBarrier(queue, this);
Karl Schultz58674242019-01-22 15:35:02 -07001422
Tony-LunarG152a88b2019-03-20 15:42:24 -06001423 DispatchQueueWaitIdle(queue);
Karl Schultz58674242019-01-22 15:35:02 -07001424
Karl Schultz7b024b42018-08-30 16:18:18 -06001425 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1426 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1427 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001428 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001429 UtilProcessInstrumentationBuffer(queue, cb_node, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001430 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06001431 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarGb5fae462020-03-05 12:43:25 -07001432 UtilProcessInstrumentationBuffer(queue, secondaryCmdBuffer, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001433 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06001434 }
1435 }
1436 }
1437}
Tony-LunarGb2501d22019-01-28 09:59:13 -07001438
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001439void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
1440 uint32_t firstVertex, uint32_t firstInstance) {
1441 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1442}
1443
1444void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
1445 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
1446 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1447}
1448
1449void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
1450 uint32_t stride) {
1451 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1452}
1453
1454void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1455 uint32_t count, uint32_t stride) {
1456 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1457}
1458
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001459void GpuAssisted::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1460 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1461 uint32_t stride) {
1462 ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1463 maxDrawCount, stride);
1464 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1465}
1466
1467void GpuAssisted::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1468 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1469 uint32_t stride) {
1470 ValidationStateTracker::PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1471 maxDrawCount, stride);
1472 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1473}
1474
Tony-LunarG54176fb2020-12-02 10:47:22 -07001475void GpuAssisted::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
1476 uint32_t firstInstance, VkBuffer counterBuffer,
1477 VkDeviceSize counterBufferOffset, uint32_t counterOffset,
1478 uint32_t vertexStride) {
1479 ValidationStateTracker::PreCallRecordCmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer,
1480 counterBufferOffset, counterOffset, vertexStride);
1481 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1482}
1483
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001484void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1485 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1486 uint32_t maxDrawCount, uint32_t stride) {
1487 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer,
1488 countBufferOffset, maxDrawCount, stride);
1489 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1490}
1491
1492void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1493 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1494 uint32_t maxDrawCount, uint32_t stride) {
1495 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1496 maxDrawCount, stride);
1497 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1498}
1499
1500void GpuAssisted::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
1501 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
1502 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1503}
1504
1505void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1506 uint32_t drawCount, uint32_t stride) {
1507 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
1508 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1509}
1510
1511void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1512 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1513 uint32_t maxDrawCount, uint32_t stride) {
1514 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer,
1515 countBufferOffset, maxDrawCount, stride);
1516 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1517}
1518
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001519void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
1520 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1521}
1522
1523void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
1524 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1525}
1526
Tony-LunarGd13f9b52020-09-08 15:45:45 -06001527void GpuAssisted::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1528 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1529 uint32_t groupCountZ) {
1530 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1531}
1532
Tony-LunarG52c8c602020-09-10 16:29:56 -06001533void GpuAssisted::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1534 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1535 uint32_t groupCountZ) {
1536 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1537}
1538
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001539void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1540 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1541 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1542 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1543 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1544 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1545 uint32_t width, uint32_t height, uint32_t depth) {
1546 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
1547}
1548
1549void GpuAssisted::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1550 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1551 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1552 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1553 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1554 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1555 uint32_t width, uint32_t height, uint32_t depth) {
1556 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1557 cb_state->hasTraceRaysCmd = true;
1558}
1559
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001560void GpuAssisted::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001561 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1562 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1563 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1564 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001565 uint32_t height, uint32_t depth) {
1566 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
1567}
1568
1569void GpuAssisted::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001570 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1571 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1572 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1573 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001574 uint32_t height, uint32_t depth) {
1575 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1576 cb_state->hasTraceRaysCmd = true;
1577}
1578
1579void GpuAssisted::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001580 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1581 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1582 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1583 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -07001584 VkDeviceAddress indirectDeviceAddress) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001585 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
1586}
1587
1588void GpuAssisted::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001589 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1590 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1591 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1592 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -07001593 VkDeviceAddress indirectDeviceAddress) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001594 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1595 cb_state->hasTraceRaysCmd = true;
1596}
1597
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001598void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Jason Macnak67407e72019-07-11 11:05:09 -07001599 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1600 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
andreygca287f22019-04-10 00:15:33 +03001601 return;
1602 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001603 VkResult result;
1604
Tony-LunarG99b880b2019-09-26 11:19:52 -06001605 if (aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001606
1607 std::vector<VkDescriptorSet> desc_sets;
1608 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -06001609 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001610 assert(result == VK_SUCCESS);
1611 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001612 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001613 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001614 return;
1615 }
1616
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001617 VkDescriptorBufferInfo output_desc_buffer_info = {};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001618 output_desc_buffer_info.range = output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001619
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001620 auto cb_node = GetCBState(cmd_buffer);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001621 if (!cb_node) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001622 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001623 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001624 return;
1625 }
1626
Tony-LunarG81efe392019-03-07 15:43:27 -07001627 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001628 GpuAssistedDeviceMemoryBlock output_block = {};
Tony-LunarG0e564722019-03-19 16:09:14 -06001629 VkBufferCreateInfo bufferInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001630 bufferInfo.size = output_buffer_size;
Tony-LunarG0e564722019-03-19 16:09:14 -06001631 bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1632 VmaAllocationCreateInfo allocInfo = {};
1633 allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001634 result = vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001635 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001636 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001637 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001638 return;
1639 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001640
Tony-LunarG81efe392019-03-07 15:43:27 -07001641 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001642 uint32_t *data_ptr;
1643 result = vmaMapMemory(vmaAllocator, output_block.allocation, (void **)&data_ptr);
Tony-LunarG0e564722019-03-19 16:09:14 -06001644 if (result == VK_SUCCESS) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001645 memset(data_ptr, 0, output_buffer_size);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001646 vmaUnmapMemory(vmaAllocator, output_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001647 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001648
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001649 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001650 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
1651 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
1652 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001653 uint32_t desc_count = 1;
locke-lunargb8d7a7a2020-10-25 16:01:52 -06001654 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
1655 auto const &state = cb_node->lastBound[lv_bind_point];
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001656 uint32_t number_of_sets = (uint32_t)state.per_set.size();
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001657
Tony-LunarGe29097a2020-12-03 10:59:19 -07001658 bool has_buffers = false;
Tony-LunarG81efe392019-03-07 15:43:27 -07001659 // Figure out how much memory we need for the input block based on how many sets and bindings there are
1660 // and how big each of the bindings is
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001661 if (number_of_sets > 0 && (descriptor_indexing || buffer_oob_enabled)) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001662 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
1663 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001664 for (auto s : state.per_set) {
1665 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06001666 if (desc && (desc->GetBindingCount() > 0)) {
1667 auto bindings = desc->GetLayout()->GetSortedBindingSet();
Tony-LunarGa77cade2019-03-06 10:49:22 -07001668 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
1669 for (auto binding : bindings) {
Tony-LunarG7564b382019-08-21 10:11:35 -06001670 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1671 // blocks
Tony-LunarGe29097a2020-12-03 10:59:19 -07001672 auto descriptor_type = desc->GetLayout()->GetTypeFromBinding(binding);
1673 if (descriptor_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
Tony-LunarG7564b382019-08-21 10:11:35 -06001674 descriptor_count++;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001675 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
1676 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
1677 "validation");
Tony-LunarG7564b382019-08-21 10:11:35 -06001678 } else if (binding == desc->GetLayout()->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001679 descriptor_count += desc->GetVariableDescriptorCount();
1680 } else {
1681 descriptor_count += desc->GetDescriptorCountFromBinding(binding);
1682 }
Tony-LunarGe29097a2020-12-03 10:59:19 -07001683 if (!has_buffers && (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
1684 descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC ||
1685 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
Tony-LunarGe8632e42020-11-18 17:03:12 -07001686 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
1687 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
1688 descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07001689 has_buffers = true;
Tony-LunarGa77cade2019-03-06 10:49:22 -07001690 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001691 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001692 }
1693 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001694
Tony-LunarGe29097a2020-12-03 10:59:19 -07001695 if (descriptor_indexing || has_buffers) {
1696 // Note that the size of the input buffer is dependent on the maximum binding number, which
1697 // can be very large. This is because for (set = s, binding = b, index = i), the validation
1698 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
1699 // see if descriptors have been written. In gpu_validation.md, we note this and advise
1700 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
1701 uint32_t words_needed;
1702 if (descriptor_indexing) {
1703 words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
1704 } else {
1705 words_needed = 1 + number_of_sets + binding_count + descriptor_count;
1706 }
1707 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
1708 bufferInfo.size = words_needed * 4;
1709 result =
1710 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &di_input_block.buffer, &di_input_block.allocation, nullptr);
1711 if (result != VK_SUCCESS) {
1712 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
1713 aborted = true;
1714 return;
1715 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001716
Tony-LunarGe29097a2020-12-03 10:59:19 -07001717 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
1718 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
1719 // outline of the input buffer format
1720 result = vmaMapMemory(vmaAllocator, di_input_block.allocation, (void **)&data_ptr);
1721 memset(data_ptr, 0, static_cast<size_t>(bufferInfo.size));
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001722
Tony-LunarGe29097a2020-12-03 10:59:19 -07001723 // Descriptor indexing needs the number of descriptors at each binding.
1724 if (descriptor_indexing) {
1725 // Pointer to a sets array that points into the sizes array
1726 uint32_t *sets_to_sizes = data_ptr + 1;
1727 // Pointer to the sizes array that contains the array size of the descriptor at each binding
1728 uint32_t *sizes = sets_to_sizes + number_of_sets;
1729 // Pointer to another sets array that points into the bindings array that points into the written array
1730 uint32_t *sets_to_bindings = sizes + binding_count;
1731 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
1732 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
1733 // Index of the next entry in the written array to be updated
1734 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
1735 uint32_t bind_counter = number_of_sets + 1;
1736 // Index of the start of the sets_to_bindings array
1737 data_ptr[0] = number_of_sets + binding_count + 1;
1738
1739 for (auto s : state.per_set) {
1740 auto desc = s.bound_descriptor_set;
1741 if (desc && (desc->GetBindingCount() > 0)) {
1742 auto layout = desc->GetLayout();
1743 auto bindings = layout->GetSortedBindingSet();
1744 // For each set, fill in index of its bindings sizes in the sizes array
1745 *sets_to_sizes++ = bind_counter;
1746 // For each set, fill in the index of its bindings in the bindings_to_written array
1747 *sets_to_bindings++ = bind_counter + number_of_sets + binding_count;
1748 for (auto binding : bindings) {
1749 // For each binding, fill in its size in the sizes array
1750 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
1751 // uniform blocks
1752 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1753 sizes[binding] = 1;
1754 } else if (binding == layout->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
1755 sizes[binding] = desc->GetVariableDescriptorCount();
1756 } else {
1757 sizes[binding] = desc->GetDescriptorCountFromBinding(binding);
1758 }
1759 // Fill in the starting index for this binding in the written array in the bindings_to_written array
1760 bindings_to_written[binding] = written_index;
1761
1762 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
1763 // uniform blocks
1764 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1765 data_ptr[written_index++] = UINT_MAX;
1766 continue;
1767 }
1768
1769 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
1770 // For each array element in the binding, update the written array with whether it has been written
1771 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
1772 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
1773 if (descriptor->updated) {
1774 SetDescriptorInitialized(data_ptr, written_index, descriptor);
1775 } else if (desc->IsUpdateAfterBind(binding)) {
1776 // If it hasn't been written now and it's update after bind, put it in a list to check at
1777 // QueueSubmit
1778 di_input_block.update_at_submit[written_index] = descriptor;
1779 }
1780 written_index++;
1781 }
1782 }
1783 auto last = desc->GetLayout()->GetMaxBinding();
1784 bindings_to_written += last + 1;
1785 bind_counter += last + 1;
1786 sizes += last + 1;
1787 } else {
1788 *sets_to_sizes++ = 0;
1789 *sets_to_bindings++ = 0;
1790 }
1791 }
1792 } else {
1793 // If no descriptor indexing, we don't need number of descriptors at each binding, so
1794 // no sets_to_sizes or sizes arrays, just sets_to_bindings, bindings_to_written and written_index
1795
1796 // Pointer to sets array that points into the bindings array that points into the written array
1797 uint32_t *sets_to_bindings = data_ptr + 1;
1798 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
1799 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
1800 // Index of the next entry in the written array to be updated
1801 uint32_t written_index = 1 + number_of_sets + binding_count;
1802 uint32_t bind_counter = number_of_sets + 1;
1803 data_ptr[0] = 1;
1804
1805 for (auto s : state.per_set) {
1806 auto desc = s.bound_descriptor_set;
1807 if (desc && (desc->GetBindingCount() > 0)) {
1808 auto layout = desc->GetLayout();
1809 auto bindings = layout->GetSortedBindingSet();
1810 *sets_to_bindings++ = bind_counter;
1811 for (auto binding : bindings) {
1812 // Fill in the starting index for this binding in the written array in the bindings_to_written array
1813 bindings_to_written[binding] = written_index;
1814
1815 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
1816 // uniform blocks
1817 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1818 data_ptr[written_index++] = UINT_MAX;
1819 continue;
1820 }
1821
1822 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
1823
1824 // For each array element in the binding, update the written array with whether it has been written
1825 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
1826 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
1827 if (descriptor->updated) {
1828 SetDescriptorInitialized(data_ptr, written_index, descriptor);
1829 } else if (desc->IsUpdateAfterBind(binding)) {
1830 // If it hasn't been written now and it's update after bind, put it in a list to check at
1831 // QueueSubmit
1832 di_input_block.update_at_submit[written_index] = descriptor;
1833 }
1834 written_index++;
1835 }
1836 }
1837 auto last = desc->GetLayout()->GetMaxBinding();
1838 bindings_to_written += last + 1;
1839 bind_counter += last + 1;
1840 } else {
1841 *sets_to_bindings++ = 0;
1842 }
1843 }
1844 }
1845 vmaUnmapMemory(vmaAllocator, di_input_block.allocation);
1846
1847 di_input_desc_buffer_info.range = (words_needed * 4);
1848 di_input_desc_buffer_info.buffer = di_input_block.buffer;
1849 di_input_desc_buffer_info.offset = 0;
1850
1851 desc_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1852 desc_writes[1].dstBinding = 1;
1853 desc_writes[1].descriptorCount = 1;
1854 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1855 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
1856 desc_writes[1].dstSet = desc_sets[0];
1857
1858 desc_count = 2;
1859 }
Tony-LunarG0e564722019-03-19 16:09:14 -06001860 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001861
Tony-LunarGc111b242020-06-30 14:43:45 -06001862 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) && buffer_map.size() &&
Tony-LunarG5c38b182020-06-10 16:15:32 -06001863 shaderInt64 && enabled_features.core12.bufferDeviceAddress) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001864 // Example BDA input buffer assuming 2 buffers using BDA:
1865 // Word 0 | Index of start of buffer sizes (in this case 5)
1866 // Word 1 | 0x0000000000000000
1867 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
1868 // Word 3 | Device Address of second buffer
1869 // Word 4 | 0xffffffffffffffff
1870 // Word 5 | 0 (size of pretend buffer at word 1)
1871 // Word 6 | Size in bytes of first buffer
1872 // Word 7 | Size in bytes of second buffer
1873 // Word 8 | 0 (size of pretend buffer in word 4)
1874
Tony-LunarG99b880b2019-09-26 11:19:52 -06001875 uint32_t num_buffers = static_cast<uint32_t>(buffer_map.size());
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001876 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
1877 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
1878 bufferInfo.size = words_needed * 8; // 64 bit words
Tony-LunarG99b880b2019-09-26 11:19:52 -06001879 result =
1880 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &bda_input_block.buffer, &bda_input_block.allocation, nullptr);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001881 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001882 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001883 aborted = true;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001884 return;
1885 }
1886 uint64_t *bda_data;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001887 result = vmaMapMemory(vmaAllocator, bda_input_block.allocation, (void **)&bda_data);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001888 uint32_t address_index = 1;
1889 uint32_t size_index = 3 + num_buffers;
1890 memset(bda_data, 0, static_cast<size_t>(bufferInfo.size));
1891 bda_data[0] = size_index; // Start of buffer sizes
1892 bda_data[address_index++] = 0; // NULL address
1893 bda_data[size_index++] = 0;
1894
Tony-LunarG99b880b2019-09-26 11:19:52 -06001895 for (auto const &value : buffer_map) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001896 bda_data[address_index++] = value.first;
1897 bda_data[size_index++] = value.second;
1898 }
1899 bda_data[address_index] = UINTPTR_MAX;
1900 bda_data[size_index] = 0;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001901 vmaUnmapMemory(vmaAllocator, bda_input_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001902
1903 bda_input_desc_buffer_info.range = (words_needed * 8);
1904 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
1905 bda_input_desc_buffer_info.offset = 0;
1906
1907 desc_writes[desc_count].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1908 desc_writes[desc_count].dstBinding = 2;
1909 desc_writes[desc_count].descriptorCount = 1;
1910 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1911 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
1912 desc_writes[desc_count].dstSet = desc_sets[0];
1913 desc_count++;
1914 }
1915
Tony-LunarGb2501d22019-01-28 09:59:13 -07001916 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001917 output_desc_buffer_info.buffer = output_block.buffer;
1918 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001919
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001920 desc_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1921 desc_writes[0].descriptorCount = 1;
1922 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1923 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
1924 desc_writes[0].dstSet = desc_sets[0];
1925 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001926
locke-lunargb8d7a7a2020-10-25 16:01:52 -06001927 const auto *pipeline_state = state.pipeline_state;
1928 if (pipeline_state) {
1929 if ((pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index) &&
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06001930 !pipeline_state->pipeline_layout->destroyed) {
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001931 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout, desc_set_bind_index, 1,
Tony-LunarG99b880b2019-09-26 11:19:52 -06001932 desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001933 }
locke-lunargb8d7a7a2020-10-25 16:01:52 -06001934 if (pipeline_state->pipeline_layout->destroyed) {
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06001935 ReportSetupProblem(device, "Pipeline layout has been destroyed, aborting GPU-AV");
1936 aborted = true;
1937 } else {
1938 // Record buffer and memory info in CB state tracking
1939 GetBufferInfo(cmd_buffer)
1940 .emplace_back(output_block, di_input_block, bda_input_block, desc_sets[0], desc_pool, bind_point);
1941 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001942 } else {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001943 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06001944 aborted = true;
1945 }
1946 if (aborted) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001947 vmaDestroyBuffer(vmaAllocator, di_input_block.buffer, di_input_block.allocation);
1948 vmaDestroyBuffer(vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
1949 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001950 return;
1951 }
1952}