blob: 31174013304f4bce5e396642ec59ecd63ca3943a [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 ||
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700246 device_gpu_assisted->enabled_features.robustness2_features.robustBufferAccess2) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600247 device_gpu_assisted->buffer_oob_enabled = false;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700248 } else {
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600249 device_gpu_assisted->buffer_oob_enabled = *bufferoob_string ? !strcmp(bufferoob_string, "true") : true;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700250 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600251
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600252 if (device_gpu_assisted->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700253 ReportSetupProblem(device, "GPU-Assisted validation requires Vulkan 1.1 or later. GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600254 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600255 return;
256 }
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600257
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600258 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700259 ReportSetupProblem(device,
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600260 "GPU-Assisted validation requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
261 "GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600262 device_gpu_assisted->aborted = true;
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600263 return;
264 }
265
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700266 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) &&
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600267 !supported_features.shaderInt64) {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700268 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
269 "shaderInt64 feature is not available. No buffer device address checking will be attempted");
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600270 }
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600271 device_gpu_assisted->shaderInt64 = supported_features.shaderInt64;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600272 device_gpu_assisted->physicalDevice = physicalDevice;
273 device_gpu_assisted->device = *pDevice;
Tony-LunarGbb145f32020-04-27 13:41:29 -0600274 device_gpu_assisted->output_buffer_size = sizeof(uint32_t) * (spvtools::kInstMaxOutCnt + 1);
Tony-LunarG5c38b182020-06-10 16:15:32 -0600275 device_gpu_assisted->descriptor_indexing = CheckForDescriptorIndexing(device_gpu_assisted->enabled_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600276 std::vector<VkDescriptorSetLayoutBinding> bindings;
277 VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
Tony-LunarGc7ed2082020-06-11 14:00:04 -0600278 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT |
279 VK_SHADER_STAGE_MESH_BIT_NV | VK_SHADER_STAGE_TASK_BIT_NV |
280 kShaderStageAllRayTracing,
Tony-LunarG1dce2392019-10-23 16:49:29 -0600281 NULL};
282 bindings.push_back(binding);
283 for (auto i = 1; i < 3; i++) {
284 binding.binding = i;
285 bindings.push_back(binding);
Karl Schultz7b024b42018-08-30 16:18:18 -0600286 }
Tony-LunarGb5fae462020-03-05 12:43:25 -0700287 UtilPostCallRecordCreateDevice(pCreateInfo, bindings, device_gpu_assisted, device_gpu_assisted->phys_dev_props);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600288 CreateAccelerationStructureBuildValidationState(device_gpu_assisted);
Karl Schultz7b024b42018-08-30 16:18:18 -0600289}
290
Mike Schuchardt2df08912020-12-15 16:28:09 -0800291void GpuAssisted::PostCallRecordGetBufferDeviceAddress(VkDevice device, const VkBufferDeviceAddressInfo *pInfo,
Tony-LunarG588c7052020-04-23 10:47:21 -0600292 VkDeviceAddress address) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600293 BUFFER_STATE *buffer_state = GetBufferState(pInfo->buffer);
294 // Validate against the size requested when the buffer was created
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600295 if (buffer_state) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600296 buffer_map[address] = buffer_state->createInfo.size;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600297 buffer_state->deviceAddress = address;
298 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600299}
300
Mike Schuchardt2df08912020-12-15 16:28:09 -0800301void GpuAssisted::PostCallRecordGetBufferDeviceAddressEXT(VkDevice device, const VkBufferDeviceAddressInfo *pInfo,
Tony-LunarG588c7052020-04-23 10:47:21 -0600302 VkDeviceAddress address) {
303 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
304}
305
Mike Schuchardt2df08912020-12-15 16:28:09 -0800306void GpuAssisted::PostCallRecordGetBufferDeviceAddressKHR(VkDevice device, const VkBufferDeviceAddressInfo *pInfo,
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700307 VkDeviceAddress address) {
Tony-LunarG588c7052020-04-23 10:47:21 -0600308 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700309}
310
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600311void GpuAssisted::PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600312 BUFFER_STATE *buffer_state = GetBufferState(buffer);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600313 if (buffer_state) buffer_map.erase(buffer_state->deviceAddress);
Tony-LunarG2966c732020-05-21 10:33:53 -0600314 ValidationStateTracker::PreCallRecordDestroyBuffer(device, buffer, pAllocator);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600315}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600316
Karl Schultz7b024b42018-08-30 16:18:18 -0600317// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600318void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600319 DestroyAccelerationStructureBuildValidationState();
Tony-LunarGb5fae462020-03-05 12:43:25 -0700320 UtilPreCallRecordDestroyDevice(this);
Tony-LunarG2966c732020-05-21 10:33:53 -0600321 ValidationStateTracker::PreCallRecordDestroyDevice(device, pAllocator);
Tony-LunarG0a863bc2020-09-16 09:50:04 -0600322 // State Tracker can end up making vma calls through callbacks - don't destroy allocator until ST is done
323 if (vmaAllocator) {
324 vmaDestroyAllocator(vmaAllocator);
325 }
326 desc_set_manager.reset();
Karl Schultz7b024b42018-08-30 16:18:18 -0600327}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600328
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600329void GpuAssisted::CreateAccelerationStructureBuildValidationState(GpuAssisted *device_gpuav) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600330 if (device_gpuav->aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700331 return;
332 }
333
Tony-LunarG99b880b2019-09-26 11:19:52 -0600334 auto &as_validation_state = device_gpuav->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700335 if (as_validation_state.initialized) {
336 return;
337 }
338
339 if (!device_extensions.vk_nv_ray_tracing) {
340 return;
341 }
342
343 // Outline:
344 // - Create valid bottom level acceleration structure which acts as replacement
345 // - Create and load vertex buffer
346 // - Create and load index buffer
347 // - Create, allocate memory for, and bind memory for acceleration structure
348 // - Query acceleration structure handle
349 // - Create command pool and command buffer
350 // - Record build acceleration structure command
351 // - Submit command buffer and wait for completion
352 // - Cleanup
353 // - Create compute pipeline for validating instance buffers
354 // - Create descriptor set layout
355 // - Create pipeline layout
356 // - Create pipeline
357 // - Cleanup
358
359 VkResult result = VK_SUCCESS;
360
361 VkBuffer vbo = VK_NULL_HANDLE;
362 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
363 if (result == VK_SUCCESS) {
364 VkBufferCreateInfo vbo_ci = {};
365 vbo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
366 vbo_ci.size = sizeof(float) * 9;
367 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
368
369 VmaAllocationCreateInfo vbo_ai = {};
370 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
371 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
372
Tony-LunarG99b880b2019-09-26 11:19:52 -0600373 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700374 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700375 ReportSetupProblem(device, "Failed to create vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700376 }
377 }
378
379 if (result == VK_SUCCESS) {
380 uint8_t *mapped_vbo_buffer = nullptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700381 result = vmaMapMemory(device_gpuav->vmaAllocator, vbo_allocation, reinterpret_cast<void **>(&mapped_vbo_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700382 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700383 ReportSetupProblem(device, "Failed to map vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700384 } else {
385 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
386 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600387 vmaUnmapMemory(device_gpuav->vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700388 }
389 }
390
391 VkBuffer ibo = VK_NULL_HANDLE;
392 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
393 if (result == VK_SUCCESS) {
394 VkBufferCreateInfo ibo_ci = {};
395 ibo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
396 ibo_ci.size = sizeof(uint32_t) * 3;
397 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
398
399 VmaAllocationCreateInfo ibo_ai = {};
400 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
401 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
402
Tony-LunarG99b880b2019-09-26 11:19:52 -0600403 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700404 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700405 ReportSetupProblem(device, "Failed to create index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700406 }
407 }
408
409 if (result == VK_SUCCESS) {
410 uint8_t *mapped_ibo_buffer = nullptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700411 result = vmaMapMemory(device_gpuav->vmaAllocator, ibo_allocation, reinterpret_cast<void **>(&mapped_ibo_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700412 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700413 ReportSetupProblem(device, "Failed to map index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700414 } else {
415 const std::vector<uint32_t> indicies = {0, 1, 2};
416 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600417 vmaUnmapMemory(device_gpuav->vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700418 }
419 }
420
421 VkGeometryNV geometry = {};
422 geometry.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
423 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
424 geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
425 geometry.geometry.triangles.vertexData = vbo;
426 geometry.geometry.triangles.vertexOffset = 0;
427 geometry.geometry.triangles.vertexCount = 3;
428 geometry.geometry.triangles.vertexStride = 12;
429 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
430 geometry.geometry.triangles.indexData = ibo;
431 geometry.geometry.triangles.indexOffset = 0;
432 geometry.geometry.triangles.indexCount = 3;
433 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
434 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
435 geometry.geometry.triangles.transformOffset = 0;
436 geometry.geometry.aabbs = {};
437 geometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
438
439 VkAccelerationStructureCreateInfoNV as_ci = {};
440 as_ci.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
441 as_ci.info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
442 as_ci.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV;
443 as_ci.info.instanceCount = 0;
444 as_ci.info.geometryCount = 1;
445 as_ci.info.pGeometries = &geometry;
446 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600447 result = DispatchCreateAccelerationStructureNV(device_gpuav->device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700448 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700449 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700450 "Failed to create acceleration structure for acceleration structure build validation.");
451 }
452 }
453
454 VkMemoryRequirements2 as_mem_requirements = {};
455 if (result == VK_SUCCESS) {
456 VkAccelerationStructureMemoryRequirementsInfoNV as_mem_requirements_info = {};
457 as_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
458 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
459 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
460
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600461 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700462 }
463
464 VmaAllocationInfo as_memory_ai = {};
465 if (result == VK_SUCCESS) {
466 VmaAllocationCreateInfo as_memory_aci = {};
467 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
468
Tony-LunarG99b880b2019-09-26 11:19:52 -0600469 result = vmaAllocateMemory(device_gpuav->vmaAllocator, &as_mem_requirements.memoryRequirements, &as_memory_aci,
470 &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700471 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700472 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700473 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
474 }
475 }
476
477 if (result == VK_SUCCESS) {
478 VkBindAccelerationStructureMemoryInfoNV as_bind_info = {};
479 as_bind_info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
480 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
481 as_bind_info.memory = as_memory_ai.deviceMemory;
482 as_bind_info.memoryOffset = as_memory_ai.offset;
483
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600484 result = DispatchBindAccelerationStructureMemoryNV(device_gpuav->device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700485 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700486 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700487 "Failed to bind acceleration structure memory for acceleration structure build validation.");
488 }
489 }
490
491 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600492 result = DispatchGetAccelerationStructureHandleNV(device_gpuav->device, as_validation_state.replacement_as,
493 sizeof(uint64_t), &as_validation_state.replacement_as_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700494 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700495 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700496 "Failed to get acceleration structure handle for acceleration structure build validation.");
497 }
498 }
499
500 VkMemoryRequirements2 scratch_mem_requirements = {};
501 if (result == VK_SUCCESS) {
502 VkAccelerationStructureMemoryRequirementsInfoNV scratch_mem_requirements_info = {};
503 scratch_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
504 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
505 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
506
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600507 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &scratch_mem_requirements_info,
508 &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700509 }
510
511 VkBuffer scratch = VK_NULL_HANDLE;
Tony-LunarG18900282020-05-20 12:34:33 -0600512 VmaAllocation scratch_allocation = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700513 if (result == VK_SUCCESS) {
514 VkBufferCreateInfo scratch_ci = {};
515 scratch_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
516 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
517 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
Jason Macnak83cfd582019-07-31 10:14:24 -0700518 VmaAllocationCreateInfo scratch_aci = {};
519 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
520
Tony-LunarG18900282020-05-20 12:34:33 -0600521 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &scratch_ci, &scratch_aci, &scratch, &scratch_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700522 if (result != VK_SUCCESS) {
Tony-LunarG18900282020-05-20 12:34:33 -0600523 ReportSetupProblem(device_gpuav->device,
524 "Failed to create scratch buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700525 }
526 }
527
528 VkCommandPool command_pool = VK_NULL_HANDLE;
529 if (result == VK_SUCCESS) {
530 VkCommandPoolCreateInfo command_pool_ci = {};
531 command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
532 command_pool_ci.queueFamilyIndex = 0;
533
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600534 result = DispatchCreateCommandPool(device_gpuav->device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700535 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700536 ReportSetupProblem(device_gpuav->device, "Failed to create command pool for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700537 }
538 }
539
540 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
541
542 if (result == VK_SUCCESS) {
543 VkCommandBufferAllocateInfo command_buffer_ai = {};
544 command_buffer_ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
545 command_buffer_ai.commandPool = command_pool;
546 command_buffer_ai.commandBufferCount = 1;
547 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
548
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600549 result = DispatchAllocateCommandBuffers(device_gpuav->device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700550 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700551 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700552 "Failed to create command buffer for acceleration structure build validation.");
553 }
554
555 // Hook up command buffer dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600556 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700557 }
558
559 if (result == VK_SUCCESS) {
560 VkCommandBufferBeginInfo command_buffer_bi = {};
561 command_buffer_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
562
563 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
564 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700565 ReportSetupProblem(device_gpuav->device, "Failed to begin command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700566 }
567 }
568
569 if (result == VK_SUCCESS) {
570 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
571 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
572 DispatchEndCommandBuffer(command_buffer);
573 }
574
575 VkQueue queue = VK_NULL_HANDLE;
576 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600577 DispatchGetDeviceQueue(device_gpuav->device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700578
579 // Hook up queue dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600580 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700581
582 VkSubmitInfo submit_info = {};
583 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
584 submit_info.commandBufferCount = 1;
585 submit_info.pCommandBuffers = &command_buffer;
586 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
587 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700588 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700589 "Failed to submit command buffer for acceleration structure build validation.");
590 }
591 }
592
593 if (result == VK_SUCCESS) {
594 result = DispatchQueueWaitIdle(queue);
595 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700596 ReportSetupProblem(device_gpuav->device, "Failed to wait for queue idle for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700597 }
598 }
599
600 if (vbo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600601 vmaDestroyBuffer(device_gpuav->vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700602 }
603 if (ibo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600604 vmaDestroyBuffer(device_gpuav->vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700605 }
606 if (scratch != VK_NULL_HANDLE) {
Tony-LunarG18900282020-05-20 12:34:33 -0600607 vmaDestroyBuffer(device_gpuav->vmaAllocator, scratch, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700608 }
609 if (command_pool != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600610 DispatchDestroyCommandPool(device_gpuav->device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700611 }
612
Tony-LunarG99b880b2019-09-26 11:19:52 -0600613 if (device_gpuav->debug_desc_layout == VK_NULL_HANDLE) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700614 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700615 "Failed to find descriptor set layout for acceleration structure build validation.");
616 result = VK_INCOMPLETE;
617 }
618
619 if (result == VK_SUCCESS) {
620 VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
621 pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
622 pipeline_layout_ci.setLayoutCount = 1;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600623 pipeline_layout_ci.pSetLayouts = &device_gpuav->debug_desc_layout;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600624 result = DispatchCreatePipelineLayout(device_gpuav->device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700625 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700626 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700627 "Failed to create pipeline layout for acceleration structure build validation.");
628 }
629 }
630
631 VkShaderModule shader_module = VK_NULL_HANDLE;
632 if (result == VK_SUCCESS) {
633 VkShaderModuleCreateInfo shader_module_ci = {};
634 shader_module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
635 shader_module_ci.codeSize = sizeof(kComputeShaderSpirv);
636 shader_module_ci.pCode = (uint32_t *)kComputeShaderSpirv;
637
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600638 result = DispatchCreateShaderModule(device_gpuav->device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700639 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700640 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700641 "Failed to create compute shader module for acceleration structure build validation.");
642 }
643 }
644
645 if (result == VK_SUCCESS) {
646 VkPipelineShaderStageCreateInfo pipeline_stage_ci = {};
647 pipeline_stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
648 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
649 pipeline_stage_ci.module = shader_module;
650 pipeline_stage_ci.pName = "main";
651
652 VkComputePipelineCreateInfo pipeline_ci = {};
653 pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
654 pipeline_ci.stage = pipeline_stage_ci;
655 pipeline_ci.layout = as_validation_state.pipeline_layout;
656
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600657 result = DispatchCreateComputePipelines(device_gpuav->device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr,
658 &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700659 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700660 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700661 "Failed to create compute pipeline for acceleration structure build validation.");
662 }
663 }
664
665 if (shader_module != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600666 DispatchDestroyShaderModule(device_gpuav->device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700667 }
668
669 if (result == VK_SUCCESS) {
670 as_validation_state.initialized = true;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700671 LogInfo(device_gpuav->device, "UNASSIGNED-GPU-Assisted Validation.",
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600672 "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700673 } else {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600674 device_gpuav->aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700675 }
676}
677
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600678void GpuAssisted::DestroyAccelerationStructureBuildValidationState() {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600679 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700680 if (as_validation_state.pipeline != VK_NULL_HANDLE) {
681 DispatchDestroyPipeline(device, as_validation_state.pipeline, nullptr);
682 }
683 if (as_validation_state.pipeline_layout != VK_NULL_HANDLE) {
684 DispatchDestroyPipelineLayout(device, as_validation_state.pipeline_layout, nullptr);
685 }
686 if (as_validation_state.replacement_as != VK_NULL_HANDLE) {
687 DispatchDestroyAccelerationStructureNV(device, as_validation_state.replacement_as, nullptr);
688 }
689 if (as_validation_state.replacement_as_allocation != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600690 vmaFreeMemory(vmaAllocator, as_validation_state.replacement_as_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700691 }
692}
693
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600694struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700695 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
696 VkPipeline pipeline = VK_NULL_HANDLE;
697 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
698 std::vector<VkDescriptorSet> descriptor_sets;
699 std::vector<std::vector<uint32_t>> dynamic_offsets;
700 uint32_t push_descriptor_set_index = 0;
701 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
702 std::vector<uint8_t> push_constants_data;
703 PushConstantRangesId push_constants_ranges;
704
705 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
706 pipeline_bind_point = bind_point;
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600707 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
Jason Macnak83cfd582019-07-31 10:14:24 -0700708
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600709 LAST_BOUND_STATE &last_bound = cb_state->lastBound[lv_bind_point];
Jason Macnak83cfd582019-07-31 10:14:24 -0700710 if (last_bound.pipeline_state) {
711 pipeline = last_bound.pipeline_state->pipeline;
712 pipeline_layout = last_bound.pipeline_layout;
713 descriptor_sets.reserve(last_bound.per_set.size());
714 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
715 const auto *bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
716
717 descriptor_sets.push_back(bound_descriptor_set->GetSet());
718 if (bound_descriptor_set->IsPushDescriptor()) {
719 push_descriptor_set_index = static_cast<uint32_t>(i);
720 }
721 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
722 }
723
724 if (last_bound.push_descriptor_set) {
725 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
726 }
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500727 if (last_bound.pipeline_state->pipeline_layout->push_constant_ranges == cb_state->push_constant_data_ranges) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700728 push_constants_data = cb_state->push_constant_data;
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500729 push_constants_ranges = last_bound.pipeline_state->pipeline_layout->push_constant_ranges;
Jason Macnak83cfd582019-07-31 10:14:24 -0700730 }
731 }
732 }
733
734 void Restore(VkCommandBuffer command_buffer) const {
735 if (pipeline != VK_NULL_HANDLE) {
736 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
737 if (!descriptor_sets.empty()) {
738 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
739 VkDescriptorSet descriptor_set = descriptor_sets[i];
740 if (descriptor_set != VK_NULL_HANDLE) {
741 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
742 static_cast<uint32_t>(i), 1, &descriptor_set,
743 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
744 }
745 }
746 }
747 if (!push_descriptor_set_writes.empty()) {
748 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
749 static_cast<uint32_t>(push_descriptor_set_writes.size()),
750 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
751 }
752 for (const auto &push_constant_range : *push_constants_ranges) {
753 if (push_constant_range.size == 0) continue;
754 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
755 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
756 }
757 }
758 }
759};
760
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600761void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
762 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
763 VkDeviceSize instanceOffset, VkBool32 update,
764 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
765 VkBuffer scratch, VkDeviceSize scratchOffset) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700766 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
767 return;
768 }
769
Tony-LunarG99b880b2019-09-26 11:19:52 -0600770 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700771 if (!as_validation_state.initialized) {
772 return;
773 }
774
775 // Empty acceleration structure is valid according to the spec.
776 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
777 return;
778 }
779
780 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
781 assert(cb_state != nullptr);
782
783 std::vector<uint64_t> current_valid_handles;
784 for (const auto &as_state_kv : accelerationStructureMap) {
785 const ACCELERATION_STRUCTURE_STATE &as_state = *as_state_kv.second;
Jeff Bolz95176d02020-04-01 00:36:16 -0500786 if (as_state.built && as_state.create_infoNV.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700787 current_valid_handles.push_back(as_state.opaque_handle);
788 }
789 }
790
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600791 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700792 as_validation_buffer_info.acceleration_structure = dst;
793
794 const VkDeviceSize validation_buffer_size =
795 // One uint for number of instances to validate
796 4 +
797 // Two uint for the replacement acceleration structure handle
798 8 +
799 // One uint for number of invalid handles found
800 4 +
801 // Two uint for the first invalid handle found
802 8 +
803 // One uint for the number of current valid handles
804 4 +
805 // Two uint for each current valid handle
806 (8 * current_valid_handles.size());
807
808 VkBufferCreateInfo validation_buffer_create_info = {};
809 validation_buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
810 validation_buffer_create_info.size = validation_buffer_size;
811 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
812
813 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
814 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
815
Tony-LunarG99b880b2019-09-26 11:19:52 -0600816 VkResult result = vmaCreateBuffer(vmaAllocator, &validation_buffer_create_info, &validation_buffer_alloc_info,
817 &as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -0700818 &as_validation_buffer_info.validation_buffer_allocation, nullptr);
819 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700820 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600821 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700822 return;
823 }
824
825 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700826 result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation,
827 reinterpret_cast<void **>(&mapped_validation_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700828 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700829 ReportSetupProblem(device, "Unable to allocate device memory for acceleration structure build val buffer.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600830 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700831 return;
832 }
833
834 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
835 mapped_validation_buffer->replacement_handle_bits_0 =
836 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
837 mapped_validation_buffer->replacement_handle_bits_1 =
838 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
839 mapped_validation_buffer->invalid_handle_found = 0;
840 mapped_validation_buffer->invalid_handle_bits_0 = 0;
841 mapped_validation_buffer->invalid_handle_bits_1 = 0;
842 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
843
844 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
845 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
846 const uint64_t current_valid_handle = current_valid_handles[i];
847
848 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
849 ++mapped_valid_handles;
850 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
851 ++mapped_valid_handles;
852 }
853
Tony-LunarG99b880b2019-09-26 11:19:52 -0600854 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700855
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700856 static constexpr const VkDeviceSize k_instance_size = 64;
857 const VkDeviceSize instance_buffer_size = k_instance_size * pInfo->instanceCount;
Jason Macnak83cfd582019-07-31 10:14:24 -0700858
Tony-LunarG1dce2392019-10-23 16:49:29 -0600859 result = desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool, debug_desc_layout,
860 &as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700861 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700862 ReportSetupProblem(device, "Unable to get descriptor set for acceleration structure build.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600863 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700864 return;
865 }
866
867 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
868 descriptor_buffer_infos[0].buffer = instanceData;
869 descriptor_buffer_infos[0].offset = instanceOffset;
870 descriptor_buffer_infos[0].range = instance_buffer_size;
871 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.validation_buffer;
872 descriptor_buffer_infos[1].offset = 0;
873 descriptor_buffer_infos[1].range = validation_buffer_size;
874
875 VkWriteDescriptorSet descriptor_set_writes[2] = {};
876 descriptor_set_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
877 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
878 descriptor_set_writes[0].dstBinding = 0;
879 descriptor_set_writes[0].descriptorCount = 1;
880 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
881 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
882 descriptor_set_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
883 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
884 descriptor_set_writes[1].dstBinding = 1;
885 descriptor_set_writes[1].descriptorCount = 1;
886 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
887 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
888
889 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
890
891 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
892 VkMemoryBarrier memory_barrier = {};
893 memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
894 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
895 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
896 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
897 &memory_barrier, 0, nullptr, 0, nullptr);
898
899 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600900 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700901 restorable_state.Create(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
902
903 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
904 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
905 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
906 &as_validation_buffer_info.descriptor_set, 0, nullptr);
907 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
908
909 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
910 // have been replaced by the validation compute shader before any builds take place.
911 VkBufferMemoryBarrier instance_buffer_barrier = {};
912 instance_buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
913 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
914 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
915 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
916 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
917 instance_buffer_barrier.buffer = instanceData;
918 instance_buffer_barrier.offset = instanceOffset;
919 instance_buffer_barrier.size = instance_buffer_size;
920 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
921 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
922 nullptr);
923
924 // Restore the previous compute pipeline state.
925 restorable_state.Restore(commandBuffer);
926
927 as_validation_state.validation_buffers[commandBuffer].push_back(std::move(as_validation_buffer_info));
928}
929
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600930void GpuAssisted::ProcessAccelerationStructureBuildValidationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700931 if (cb_node == nullptr || !cb_node->hasBuildAccelerationStructureCmd) {
932 return;
933 }
934
Tony-LunarG99b880b2019-09-26 11:19:52 -0600935 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700936 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[cb_node->commandBuffer];
937 for (const auto &as_validation_buffer_info : as_validation_buffer_infos) {
938 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
939
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700940 VkResult result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation,
941 reinterpret_cast<void **>(&mapped_validation_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700942 if (result == VK_SUCCESS) {
943 if (mapped_validation_buffer->invalid_handle_found > 0) {
944 uint64_t invalid_handle = 0;
945 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
946 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
947
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700948 LogError(as_validation_buffer_info.acceleration_structure, "UNASSIGNED-AccelerationStructure",
949 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
950 "handle (%" PRIu64 ")",
951 invalid_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700952 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600953 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700954 }
955 }
956}
957
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600958void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
959 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
960 VkResult result) {
961 if (VK_SUCCESS != result) return;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600962 ValidationStateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600963 for (uint32_t i = 0; i < bindInfoCount; i++) {
964 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
sourav parmarcd5fb182020-07-17 12:58:44 -0700965 ACCELERATION_STRUCTURE_STATE *as_state = GetAccelerationStructureStateNV(info.accelerationStructure);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600966 if (as_state) {
967 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
968 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600969 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600970}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700971
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600972// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
973void GpuAssisted::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
974 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
975 void *cpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600976 if (aborted) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600977 return;
978 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600979
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600980 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
981
Tony-LunarG99b880b2019-09-26 11:19:52 -0600982 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600983 std::ostringstream strm;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600984 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Karl Schultz7b024b42018-08-30 16:18:18 -0600985 << "Application has too many descriptor sets in the pipeline layout to continue with gpu validation. "
986 << "Validation is not modifying the pipeline layout. "
987 << "Instrumented shaders are replaced with non-instrumented shaders.";
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700988 ReportSetupProblem(device, strm.str().c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -0600989 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700990 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Karl Schultz7b024b42018-08-30 16:18:18 -0600991 }
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700992}
993
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600994void GpuAssisted::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
995 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
996 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600997 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
998
Karl Schultz7b024b42018-08-30 16:18:18 -0600999 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001000 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001001 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -06001002 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001003}
1004
Karl Schultz7b024b42018-08-30 16:18:18 -06001005// Free the device memory and descriptor set associated with a command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001006void GpuAssisted::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001007 if (aborted) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001008 return;
1009 }
Tony-LunarG1dce2392019-10-23 16:49:29 -06001010 auto gpuav_buffer_list = GetBufferInfo(commandBuffer);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001011 for (auto buffer_info : gpuav_buffer_list) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001012 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001013 if (buffer_info.di_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001014 vmaDestroyBuffer(vmaAllocator, buffer_info.di_input_mem_block.buffer, buffer_info.di_input_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001015 }
1016 if (buffer_info.bda_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001017 vmaDestroyBuffer(vmaAllocator, buffer_info.bda_input_mem_block.buffer, buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -06001018 }
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001019 if (buffer_info.desc_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001020 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001021 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001022 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001023 command_buffer_map.erase(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001024
Tony-LunarG99b880b2019-09-26 11:19:52 -06001025 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001026 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[commandBuffer];
1027 for (auto &as_validation_buffer_info : as_validation_buffer_infos) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001028 vmaDestroyBuffer(vmaAllocator, as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -07001029 as_validation_buffer_info.validation_buffer_allocation);
1030
1031 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001032 desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool,
1033 as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -07001034 }
1035 }
1036 as_validation_info.validation_buffers.erase(commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -06001037}
Karl Schultz7b024b42018-08-30 16:18:18 -06001038// Just gives a warning about a possible deadlock.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001039bool GpuAssisted::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
1040 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
1041 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1042 uint32_t bufferMemoryBarrierCount,
1043 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
Jeff Bolz5c801d12019-10-09 10:38:45 -05001044 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001045 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001046 ReportSetupProblem(commandBuffer,
Karl Schultz7b024b42018-08-30 16:18:18 -06001047 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1048 "GPU_Assisted validation waits on queue completion. "
1049 "This wait could block the host's signaling of this event, resulting in deadlock.");
1050 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001051 return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001052}
1053
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001054void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1055 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
1056 // 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 -06001057 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001058 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
1059 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
1060 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001061 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1062 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001063 }
1064 }
1065}
1066
1067void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1068 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
1069 // 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 -06001070 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001071 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
1072 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
1073 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001074 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1075 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001076 }
1077 }
1078}
1079
1080void GpuAssisted::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1081 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1082 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1083 void *cgpl_state_data) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001084 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001085 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001086 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
1087 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001088 cgpl_state->gpu_create_infos = new_pipeline_create_infos;
1089 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001090}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001091
1092void GpuAssisted::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1093 const VkComputePipelineCreateInfo *pCreateInfos,
1094 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1095 void *ccpl_state_data) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001096 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001097 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001098 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
1099 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001100 ccpl_state->gpu_create_infos = new_pipeline_create_infos;
1101 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
Jason Macnak67407e72019-07-11 11:05:09 -07001102}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001103
1104void GpuAssisted::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1105 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1106 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1107 void *crtpl_state_data) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001108 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001109 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001110 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1111 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001112 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1113 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001114}
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001115
sourav parmarcd5fb182020-07-17 12:58:44 -07001116void GpuAssisted::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
1117 VkPipelineCache pipelineCache, uint32_t count,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001118 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1119 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1120 void *crtpl_state_data) {
1121 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
1122 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001123 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1124 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001125 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1126 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->gpu_create_infos.data());
1127}
Karl Schultz7b024b42018-08-30 16:18:18 -06001128
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001129void GpuAssisted::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1130 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1131 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1132 VkResult result, void *cgpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001133 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
1134 pPipelines, result, cgpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001135 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
1136 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, cgpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001137 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001138}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001139
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001140void GpuAssisted::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1141 const VkComputePipelineCreateInfo *pCreateInfos,
1142 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1143 VkResult result, void *ccpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001144 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1145 result, ccpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001146 create_compute_pipeline_api_state *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
1147 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, ccpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001148 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001149}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001150
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001151void GpuAssisted::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1152 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1153 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1154 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001155 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001156 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
1157 pPipelines, result, crtpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001158 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001159 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Jason Macnak67407e72019-07-11 11:05:09 -07001160}
1161
sourav parmarcd5fb182020-07-17 12:58:44 -07001162void GpuAssisted::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
1163 VkPipelineCache pipelineCache, uint32_t count,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001164 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1165 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1166 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001167 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
sourav parmarcd5fb182020-07-17 12:58:44 -07001168 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesKHR(
1169 device, deferredOperation, pipelineCache, count, pCreateInfos, pAllocator, pPipelines, result, crtpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001170 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001171 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Karl Schultz7b024b42018-08-30 16:18:18 -06001172}
1173
1174// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001175void GpuAssisted::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001176 for (auto it = shader_map.begin(); it != shader_map.end();) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001177 if (it->second.pipeline == pipeline) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001178 it = shader_map.erase(it);
Karl Schultz7b024b42018-08-30 16:18:18 -06001179 } else {
1180 ++it;
1181 }
1182 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001183 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001184}
1185
1186// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001187bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
1188 uint32_t *unique_shader_id) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001189 if (aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001190 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
1191
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001192 const spvtools::MessageConsumer gpu_console_message_consumer =
Tony-LunarG79641702020-07-13 15:43:05 -06001193 [this](spv_message_level_t level, const char *, const spv_position_t &position, const char *message) -> void {
1194 switch (level) {
1195 case SPV_MSG_FATAL:
1196 case SPV_MSG_INTERNAL_ERROR:
1197 case SPV_MSG_ERROR:
1198 this->LogError(this->device, "UNASSIGNED-GPU-Assisted", "Error during shader instrumentation: line %zu: %s",
1199 position.index, message);
1200 break;
1201 default:
1202 break;
1203 }
1204 };
1205
Karl Schultz7b024b42018-08-30 16:18:18 -06001206 // Load original shader SPIR-V
1207 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
1208 new_pgm.clear();
1209 new_pgm.reserve(num_words);
1210 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
1211
1212 // Call the optimizer to instrument the shader.
1213 // 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 -07001214 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Karl Schultz7b024b42018-08-30 16:18:18 -06001215 using namespace spvtools;
Tony-LunarG8a51b7d2020-07-01 15:57:23 -06001216 spv_target_env target_env = PickSpirvEnv(api_version, (device_extensions.vk_khr_spirv_1_4 != kNotEnabled));
Tony-LunarGf29f77f2020-08-26 15:48:00 -06001217 spvtools::ValidatorOptions val_options;
1218 AdjustValidatorOptions(device_extensions, enabled_features, val_options);
1219 spvtools::OptimizerOptions opt_options;
1220 opt_options.set_run_validator(true);
1221 opt_options.set_validator_options(val_options);
Karl Schultz7b024b42018-08-30 16:18:18 -06001222 Optimizer optimizer(target_env);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001223 optimizer.SetMessageConsumer(gpu_console_message_consumer);
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001224 optimizer.RegisterPass(CreateInstBindlessCheckPass(desc_set_bind_index, unique_shader_module_id, descriptor_indexing,
Tony-LunarGe8632e42020-11-18 17:03:12 -07001225 descriptor_indexing, buffer_oob_enabled, buffer_oob_enabled));
Karl Schultz7b024b42018-08-30 16:18:18 -06001226 optimizer.RegisterPass(CreateAggressiveDCEPass());
Tony-LunarG5c38b182020-06-10 16:15:32 -06001227 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) && shaderInt64 &&
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001228 enabled_features.core12.bufferDeviceAddress) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001229 optimizer.RegisterPass(CreateInstBuffAddrCheckPass(desc_set_bind_index, unique_shader_module_id));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001230 }
Tony-LunarGf29f77f2020-08-26 15:48:00 -06001231 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm, opt_options);
Karl Schultz7b024b42018-08-30 16:18:18 -06001232 if (!pass) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001233 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Karl Schultz7b024b42018-08-30 16:18:18 -06001234 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001235 *unique_shader_id = unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -06001236 return pass;
1237}
Mark Lobodzinski01734072019-02-13 17:39:15 -07001238// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001239void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
1240 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
1241 void *csm_state_data) {
1242 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
1243 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -06001244 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001245 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
1246 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
Karl Schultz7b024b42018-08-30 16:18:18 -06001247 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001248}
1249
Karl Schultz7b024b42018-08-30 16:18:18 -06001250// Generate the part of the message describing the violation.
1251static void GenerateValidationMessage(const uint32_t *debug_record, std::string &msg, std::string &vuid_msg) {
1252 using namespace spvtools;
1253 std::ostringstream strm;
Tony-LunarGab47cac2019-12-20 15:28:01 -07001254 switch (debug_record[kInstValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001255 case kInstErrorBindlessBounds: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001256 strm << "Index of " << debug_record[kInstBindlessBoundsOutDescIndex] << " used to index descriptor array of length "
1257 << debug_record[kInstBindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001258 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -06001259 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001260 case kInstErrorBindlessUninit: {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001261 strm << "Descriptor index " << debug_record[kInstBindlessUninitOutDescIndex] << " is uninitialized.";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001262 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -06001263 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001264 case kInstErrorBuffAddrUnallocRef: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001265 uint64_t *ptr = (uint64_t *)&debug_record[kInstBuffAddrUnallocOutDescPtrLo];
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001266 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
1267 vuid_msg = "UNASSIGNED-Device address out of bounds";
1268 } break;
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001269 case kInstErrorBindlessBuffOOB: {
1270 auto size = debug_record[kInstBindlessBuffOOBOutBuffSize];
1271 if (size == 0) {
1272 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex] << " is uninitialized.";
1273 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
1274 } else {
1275 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex]
1276 << " access out of bounds. Descriptor size is " << debug_record[kInstBindlessBuffOOBOutBuffSize]
Tony-LunarGe8632e42020-11-18 17:03:12 -07001277 << " units (bytes or texels) and highest unit accessed was " << debug_record[kInstBindlessBuffOOBOutBuffOff];
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001278 vuid_msg = "UNASSIGNED-Descriptor access out of bounds";
1279 }
1280 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001281 default: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001282 strm << "Internal Error (unexpected error type = " << debug_record[kInstValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001283 vuid_msg = "UNASSIGNED-Internal Error";
1284 assert(false);
1285 } break;
1286 }
1287 msg = strm.str();
1288}
1289
Karl Schultz7b024b42018-08-30 16:18:18 -06001290// Pull together all the information from the debug record to build the error message strings,
1291// and then assemble them into a single message string.
1292// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
1293// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
1294// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
1295// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
1296//
Tony-LunarG1dce2392019-10-23 16:49:29 -06001297void GpuAssisted::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, VkPipelineBindPoint pipeline_bind_point,
1298 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001299 using namespace spvtools;
1300 const uint32_t total_words = debug_output_buffer[0];
1301 // A zero here means that the shader instrumentation didn't write anything.
1302 // If you have nothing to say, don't say it here.
1303 if (0 == total_words) {
1304 return;
1305 }
1306 // The first word in the debug output buffer is the number of words that would have
1307 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
1308 // The number of words actually written by the shaders is determined by the size of the buffer
1309 // we provide via the descriptor. So, we process only the number of words that can fit in the
1310 // buffer.
1311 // Each "report" written by the shader instrumentation is considered a "record". This function
1312 // is hard-coded to process only one record because it expects the buffer to be large enough to
1313 // hold only one record. If there is a desire to process more than one record, this function needs
1314 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06001315 std::string validation_message;
1316 std::string stage_message;
1317 std::string common_message;
1318 std::string filename_message;
1319 std::string source_message;
1320 std::string vuid_msg;
1321 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
1322 VkPipeline pipeline_handle = VK_NULL_HANDLE;
1323 std::vector<unsigned int> pgm;
1324 // The first record starts at this offset after the total_words.
1325 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
1326 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
1327 // by the instrumented shader.
Tony-LunarG99b880b2019-09-26 11:19:52 -06001328 auto it = shader_map.find(debug_record[kInstCommonOutShaderId]);
1329 if (it != shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001330 shader_module_handle = it->second.shader_module;
1331 pipeline_handle = it->second.pipeline;
1332 pgm = it->second.pgm;
1333 }
1334 GenerateValidationMessage(debug_record, validation_message, vuid_msg);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001335 UtilGenerateStageMessage(debug_record, stage_message);
1336 UtilGenerateCommonMessage(report_data, command_buffer, debug_record, shader_module_handle, pipeline_handle, pipeline_bind_point,
1337 operation_index, common_message);
1338 UtilGenerateSourceMessages(pgm, debug_record, false, filename_message, source_message);
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001339 LogError(queue, vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
1340 filename_message.c_str(), source_message.c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -06001341 // The debug record at word kInstCommonOutSize is the number of words in the record
1342 // written by the shader. Clear the entire record plus the total_words word at the start.
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001343 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], static_cast<uint32_t>(kInstMaxOutCnt));
Karl Schultz7b024b42018-08-30 16:18:18 -06001344 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
1345}
1346
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001347void GpuAssisted::SetDescriptorInitialized(uint32_t *pData, uint32_t index, const cvdescriptorset::Descriptor *descriptor) {
1348 if (descriptor->GetClass() == cvdescriptorset::DescriptorClass::GeneralBuffer) {
1349 auto buffer = static_cast<const cvdescriptorset::BufferDescriptor *>(descriptor)->GetBuffer();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001350 if (buffer == VK_NULL_HANDLE) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001351 pData[index] = UINT_MAX;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001352 } else {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001353 auto buffer_state = static_cast<const cvdescriptorset::BufferDescriptor *>(descriptor)->GetBufferState();
1354 pData[index] = static_cast<uint32_t>(buffer_state->createInfo.size);
1355 }
1356 } else if (descriptor->GetClass() == cvdescriptorset::DescriptorClass::TexelBuffer) {
1357 auto buffer_view = static_cast<const cvdescriptorset::TexelDescriptor *>(descriptor)->GetBufferView();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001358 if (buffer_view == VK_NULL_HANDLE) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001359 pData[index] = UINT_MAX;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001360 } else {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001361 auto buffer_view_state = static_cast<const cvdescriptorset::TexelDescriptor *>(descriptor)->GetBufferViewState();
1362 pData[index] = static_cast<uint32_t>(buffer_view_state->buffer_state->createInfo.size);
1363 }
1364 } else {
1365 pData[index] = 1;
1366 }
1367}
1368
Tony-LunarG81efe392019-03-07 15:43:27 -07001369// 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 -06001370void GpuAssisted::UpdateInstrumentationBuffer(CMD_BUFFER_STATE *cb_node) {
Tony-LunarG1dce2392019-10-23 16:49:29 -06001371 auto gpu_buffer_list = GetBufferInfo(cb_node->commandBuffer);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001372 uint32_t *data;
Tony-LunarG81efe392019-03-07 15:43:27 -07001373 for (auto &buffer_info : gpu_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001374 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001375 VkResult result =
1376 vmaMapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation, reinterpret_cast<void **>(&data));
Tony-LunarG81efe392019-03-07 15:43:27 -07001377 if (result == VK_SUCCESS) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001378 for (auto update : buffer_info.di_input_mem_block.update_at_submit) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001379 if (update.second->updated) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001380 SetDescriptorInitialized(data, update.first, update.second);
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001381 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001382 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001383 vmaUnmapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07001384 }
1385 }
1386 }
1387}
1388
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001389void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001390 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1391 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1392 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001393 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07001394 UpdateInstrumentationBuffer(cb_node);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001395 for (auto secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
1396 UpdateInstrumentationBuffer(secondary_cmd_buffer);
Tony-LunarG81efe392019-03-07 15:43:27 -07001397 }
1398 }
1399 }
1400}
1401
Karl Schultz58674242019-01-22 15:35:02 -07001402// Issue a memory barrier to make GPU-written data available to host.
1403// Wait for the queue to complete execution.
1404// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001405void GpuAssisted::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
1406 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001407 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001408
Mark Lobodzinski09379db2020-05-07 08:22:01 -06001409 if (aborted || (result != VK_SUCCESS)) return;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001410 bool buffers_present = false;
1411 // Don't QueueWaitIdle if there's nothing to process
1412 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1413 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1414 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
1415 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG1dce2392019-10-23 16:49:29 -06001416 if (GetBufferInfo(cb_node->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd) buffers_present = true;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001417 for (auto secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
1418 if (GetBufferInfo(secondary_cmd_buffer->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd) {
Jason Macnak83cfd582019-07-31 10:14:24 -07001419 buffers_present = true;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001420 }
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001421 }
1422 }
1423 }
1424 if (!buffers_present) return;
Karl Schultz58674242019-01-22 15:35:02 -07001425
Tony-LunarGb5fae462020-03-05 12:43:25 -07001426 UtilSubmitBarrier(queue, this);
Karl Schultz58674242019-01-22 15:35:02 -07001427
Tony-LunarG152a88b2019-03-20 15:42:24 -06001428 DispatchQueueWaitIdle(queue);
Karl Schultz58674242019-01-22 15:35:02 -07001429
Karl Schultz7b024b42018-08-30 16:18:18 -06001430 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1431 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1432 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001433 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001434 UtilProcessInstrumentationBuffer(queue, cb_node, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001435 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001436 for (auto secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
1437 UtilProcessInstrumentationBuffer(queue, secondary_cmd_buffer, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001438 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06001439 }
1440 }
1441 }
1442}
Tony-LunarGb2501d22019-01-28 09:59:13 -07001443
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001444void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
1445 uint32_t firstVertex, uint32_t firstInstance) {
1446 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1447}
1448
1449void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
1450 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
1451 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1452}
1453
1454void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
1455 uint32_t stride) {
1456 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1457}
1458
1459void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1460 uint32_t count, uint32_t stride) {
1461 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1462}
1463
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001464void GpuAssisted::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1465 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1466 uint32_t stride) {
1467 ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1468 maxDrawCount, stride);
1469 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1470}
1471
1472void GpuAssisted::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1473 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1474 uint32_t stride) {
1475 ValidationStateTracker::PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1476 maxDrawCount, stride);
1477 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1478}
1479
Tony-LunarG54176fb2020-12-02 10:47:22 -07001480void GpuAssisted::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
1481 uint32_t firstInstance, VkBuffer counterBuffer,
1482 VkDeviceSize counterBufferOffset, uint32_t counterOffset,
1483 uint32_t vertexStride) {
1484 ValidationStateTracker::PreCallRecordCmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer,
1485 counterBufferOffset, counterOffset, vertexStride);
1486 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1487}
1488
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001489void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1490 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1491 uint32_t maxDrawCount, uint32_t stride) {
1492 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer,
1493 countBufferOffset, maxDrawCount, stride);
1494 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1495}
1496
1497void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1498 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1499 uint32_t maxDrawCount, uint32_t stride) {
1500 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1501 maxDrawCount, stride);
1502 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1503}
1504
1505void GpuAssisted::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
1506 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
1507 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1508}
1509
1510void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1511 uint32_t drawCount, uint32_t stride) {
1512 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
1513 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1514}
1515
1516void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1517 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1518 uint32_t maxDrawCount, uint32_t stride) {
1519 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer,
1520 countBufferOffset, maxDrawCount, stride);
1521 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1522}
1523
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001524void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
1525 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1526}
1527
1528void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
1529 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1530}
1531
Tony-LunarGd13f9b52020-09-08 15:45:45 -06001532void GpuAssisted::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1533 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1534 uint32_t groupCountZ) {
1535 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1536}
1537
Tony-LunarG52c8c602020-09-10 16:29:56 -06001538void GpuAssisted::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1539 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1540 uint32_t groupCountZ) {
1541 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1542}
1543
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001544void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1545 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1546 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1547 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1548 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1549 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1550 uint32_t width, uint32_t height, uint32_t depth) {
1551 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
1552}
1553
1554void GpuAssisted::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1555 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1556 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1557 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1558 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1559 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1560 uint32_t width, uint32_t height, uint32_t depth) {
1561 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1562 cb_state->hasTraceRaysCmd = true;
1563}
1564
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001565void GpuAssisted::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001566 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1567 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1568 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1569 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001570 uint32_t height, uint32_t depth) {
1571 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
1572}
1573
1574void GpuAssisted::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001575 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1576 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1577 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1578 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001579 uint32_t height, uint32_t depth) {
1580 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1581 cb_state->hasTraceRaysCmd = true;
1582}
1583
1584void GpuAssisted::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001585 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1586 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1587 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1588 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -07001589 VkDeviceAddress indirectDeviceAddress) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001590 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
1591}
1592
1593void GpuAssisted::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001594 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1595 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1596 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1597 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -07001598 VkDeviceAddress indirectDeviceAddress) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001599 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1600 cb_state->hasTraceRaysCmd = true;
1601}
1602
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001603void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Jason Macnak67407e72019-07-11 11:05:09 -07001604 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1605 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
andreygca287f22019-04-10 00:15:33 +03001606 return;
1607 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001608 VkResult result;
1609
Tony-LunarG99b880b2019-09-26 11:19:52 -06001610 if (aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001611
1612 std::vector<VkDescriptorSet> desc_sets;
1613 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -06001614 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001615 assert(result == VK_SUCCESS);
1616 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001617 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001618 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001619 return;
1620 }
1621
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001622 VkDescriptorBufferInfo output_desc_buffer_info = {};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001623 output_desc_buffer_info.range = output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001624
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001625 auto cb_node = GetCBState(cmd_buffer);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001626 if (!cb_node) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001627 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001628 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001629 return;
1630 }
1631
Tony-LunarG81efe392019-03-07 15:43:27 -07001632 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001633 GpuAssistedDeviceMemoryBlock output_block = {};
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001634 VkBufferCreateInfo buffer_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
1635 buffer_info.size = output_buffer_size;
1636 buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1637 VmaAllocationCreateInfo alloc_info = {};
1638 alloc_info.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
1639 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001640 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001641 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001642 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001643 return;
1644 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001645
Tony-LunarG81efe392019-03-07 15:43:27 -07001646 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001647 uint32_t *data_ptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001648 result = vmaMapMemory(vmaAllocator, output_block.allocation, reinterpret_cast<void **>(&data_ptr));
Tony-LunarG0e564722019-03-19 16:09:14 -06001649 if (result == VK_SUCCESS) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001650 memset(data_ptr, 0, output_buffer_size);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001651 vmaUnmapMemory(vmaAllocator, output_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001652 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001653
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001654 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001655 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
1656 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
1657 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001658 uint32_t desc_count = 1;
locke-lunargb8d7a7a2020-10-25 16:01:52 -06001659 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
1660 auto const &state = cb_node->lastBound[lv_bind_point];
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001661 uint32_t number_of_sets = static_cast<uint32_t>(state.per_set.size());
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001662
Tony-LunarGe29097a2020-12-03 10:59:19 -07001663 bool has_buffers = false;
Tony-LunarG81efe392019-03-07 15:43:27 -07001664 // Figure out how much memory we need for the input block based on how many sets and bindings there are
1665 // and how big each of the bindings is
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001666 if (number_of_sets > 0 && (descriptor_indexing || buffer_oob_enabled)) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001667 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
1668 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001669 for (auto s : state.per_set) {
1670 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06001671 if (desc && (desc->GetBindingCount() > 0)) {
1672 auto bindings = desc->GetLayout()->GetSortedBindingSet();
Tony-LunarGa77cade2019-03-06 10:49:22 -07001673 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
1674 for (auto binding : bindings) {
Tony-LunarG7564b382019-08-21 10:11:35 -06001675 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1676 // blocks
Tony-LunarGe29097a2020-12-03 10:59:19 -07001677 auto descriptor_type = desc->GetLayout()->GetTypeFromBinding(binding);
1678 if (descriptor_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
Tony-LunarG7564b382019-08-21 10:11:35 -06001679 descriptor_count++;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001680 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
1681 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
1682 "validation");
Tony-LunarG7564b382019-08-21 10:11:35 -06001683 } else if (binding == desc->GetLayout()->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001684 descriptor_count += desc->GetVariableDescriptorCount();
1685 } else {
1686 descriptor_count += desc->GetDescriptorCountFromBinding(binding);
1687 }
Tony-LunarGe29097a2020-12-03 10:59:19 -07001688 if (!has_buffers && (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
1689 descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC ||
1690 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
Tony-LunarGe8632e42020-11-18 17:03:12 -07001691 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
1692 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
1693 descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07001694 has_buffers = true;
Tony-LunarGa77cade2019-03-06 10:49:22 -07001695 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001696 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001697 }
1698 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001699
Tony-LunarGe29097a2020-12-03 10:59:19 -07001700 if (descriptor_indexing || has_buffers) {
1701 // Note that the size of the input buffer is dependent on the maximum binding number, which
1702 // can be very large. This is because for (set = s, binding = b, index = i), the validation
1703 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
1704 // see if descriptors have been written. In gpu_validation.md, we note this and advise
1705 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
1706 uint32_t words_needed;
1707 if (descriptor_indexing) {
1708 words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
1709 } else {
1710 words_needed = 1 + number_of_sets + binding_count + descriptor_count;
1711 }
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001712 alloc_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
1713 buffer_info.size = words_needed * 4;
1714 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &di_input_block.buffer, &di_input_block.allocation,
1715 nullptr);
Tony-LunarGe29097a2020-12-03 10:59:19 -07001716 if (result != VK_SUCCESS) {
1717 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
1718 aborted = true;
1719 return;
1720 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001721
Tony-LunarGe29097a2020-12-03 10:59:19 -07001722 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
1723 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
1724 // outline of the input buffer format
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001725 result = vmaMapMemory(vmaAllocator, di_input_block.allocation, reinterpret_cast<void **>(&data_ptr));
1726 memset(data_ptr, 0, static_cast<size_t>(buffer_info.size));
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001727
Tony-LunarGe29097a2020-12-03 10:59:19 -07001728 // Descriptor indexing needs the number of descriptors at each binding.
1729 if (descriptor_indexing) {
1730 // Pointer to a sets array that points into the sizes array
1731 uint32_t *sets_to_sizes = data_ptr + 1;
1732 // Pointer to the sizes array that contains the array size of the descriptor at each binding
1733 uint32_t *sizes = sets_to_sizes + number_of_sets;
1734 // Pointer to another sets array that points into the bindings array that points into the written array
1735 uint32_t *sets_to_bindings = sizes + binding_count;
1736 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
1737 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
1738 // Index of the next entry in the written array to be updated
1739 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
1740 uint32_t bind_counter = number_of_sets + 1;
1741 // Index of the start of the sets_to_bindings array
1742 data_ptr[0] = number_of_sets + binding_count + 1;
1743
1744 for (auto s : state.per_set) {
1745 auto desc = s.bound_descriptor_set;
1746 if (desc && (desc->GetBindingCount() > 0)) {
1747 auto layout = desc->GetLayout();
1748 auto bindings = layout->GetSortedBindingSet();
1749 // For each set, fill in index of its bindings sizes in the sizes array
1750 *sets_to_sizes++ = bind_counter;
1751 // For each set, fill in the index of its bindings in the bindings_to_written array
1752 *sets_to_bindings++ = bind_counter + number_of_sets + binding_count;
1753 for (auto binding : bindings) {
1754 // For each binding, fill in its size in the sizes array
1755 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
1756 // uniform blocks
1757 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1758 sizes[binding] = 1;
1759 } else if (binding == layout->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
1760 sizes[binding] = desc->GetVariableDescriptorCount();
1761 } else {
1762 sizes[binding] = desc->GetDescriptorCountFromBinding(binding);
1763 }
1764 // Fill in the starting index for this binding in the written array in the bindings_to_written array
1765 bindings_to_written[binding] = written_index;
1766
1767 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
1768 // uniform blocks
1769 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1770 data_ptr[written_index++] = UINT_MAX;
1771 continue;
1772 }
1773
1774 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
1775 // For each array element in the binding, update the written array with whether it has been written
1776 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
1777 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
1778 if (descriptor->updated) {
1779 SetDescriptorInitialized(data_ptr, written_index, descriptor);
1780 } else if (desc->IsUpdateAfterBind(binding)) {
1781 // If it hasn't been written now and it's update after bind, put it in a list to check at
1782 // QueueSubmit
1783 di_input_block.update_at_submit[written_index] = descriptor;
1784 }
1785 written_index++;
1786 }
1787 }
1788 auto last = desc->GetLayout()->GetMaxBinding();
1789 bindings_to_written += last + 1;
1790 bind_counter += last + 1;
1791 sizes += last + 1;
1792 } else {
1793 *sets_to_sizes++ = 0;
1794 *sets_to_bindings++ = 0;
1795 }
1796 }
1797 } else {
1798 // If no descriptor indexing, we don't need number of descriptors at each binding, so
1799 // no sets_to_sizes or sizes arrays, just sets_to_bindings, bindings_to_written and written_index
1800
1801 // Pointer to sets array that points into the bindings array that points into the written array
1802 uint32_t *sets_to_bindings = data_ptr + 1;
1803 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
1804 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
1805 // Index of the next entry in the written array to be updated
1806 uint32_t written_index = 1 + number_of_sets + binding_count;
1807 uint32_t bind_counter = number_of_sets + 1;
1808 data_ptr[0] = 1;
1809
1810 for (auto s : state.per_set) {
1811 auto desc = s.bound_descriptor_set;
1812 if (desc && (desc->GetBindingCount() > 0)) {
1813 auto layout = desc->GetLayout();
1814 auto bindings = layout->GetSortedBindingSet();
1815 *sets_to_bindings++ = bind_counter;
1816 for (auto binding : bindings) {
1817 // Fill in the starting index for this binding in the written array in the bindings_to_written array
1818 bindings_to_written[binding] = written_index;
1819
1820 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
1821 // uniform blocks
1822 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1823 data_ptr[written_index++] = UINT_MAX;
1824 continue;
1825 }
1826
1827 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
1828
1829 // For each array element in the binding, update the written array with whether it has been written
1830 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
1831 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
1832 if (descriptor->updated) {
1833 SetDescriptorInitialized(data_ptr, written_index, descriptor);
1834 } else if (desc->IsUpdateAfterBind(binding)) {
1835 // If it hasn't been written now and it's update after bind, put it in a list to check at
1836 // QueueSubmit
1837 di_input_block.update_at_submit[written_index] = descriptor;
1838 }
1839 written_index++;
1840 }
1841 }
1842 auto last = desc->GetLayout()->GetMaxBinding();
1843 bindings_to_written += last + 1;
1844 bind_counter += last + 1;
1845 } else {
1846 *sets_to_bindings++ = 0;
1847 }
1848 }
1849 }
1850 vmaUnmapMemory(vmaAllocator, di_input_block.allocation);
1851
1852 di_input_desc_buffer_info.range = (words_needed * 4);
1853 di_input_desc_buffer_info.buffer = di_input_block.buffer;
1854 di_input_desc_buffer_info.offset = 0;
1855
1856 desc_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1857 desc_writes[1].dstBinding = 1;
1858 desc_writes[1].descriptorCount = 1;
1859 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1860 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
1861 desc_writes[1].dstSet = desc_sets[0];
1862
1863 desc_count = 2;
1864 }
Tony-LunarG0e564722019-03-19 16:09:14 -06001865 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001866
Tony-LunarGc111b242020-06-30 14:43:45 -06001867 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 -06001868 shaderInt64 && enabled_features.core12.bufferDeviceAddress) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001869 // Example BDA input buffer assuming 2 buffers using BDA:
1870 // Word 0 | Index of start of buffer sizes (in this case 5)
1871 // Word 1 | 0x0000000000000000
1872 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
1873 // Word 3 | Device Address of second buffer
1874 // Word 4 | 0xffffffffffffffff
1875 // Word 5 | 0 (size of pretend buffer at word 1)
1876 // Word 6 | Size in bytes of first buffer
1877 // Word 7 | Size in bytes of second buffer
1878 // Word 8 | 0 (size of pretend buffer in word 4)
1879
Tony-LunarG99b880b2019-09-26 11:19:52 -06001880 uint32_t num_buffers = static_cast<uint32_t>(buffer_map.size());
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001881 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001882 alloc_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
1883 buffer_info.size = words_needed * 8; // 64 bit words
Tony-LunarG99b880b2019-09-26 11:19:52 -06001884 result =
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001885 vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &bda_input_block.buffer, &bda_input_block.allocation, nullptr);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001886 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001887 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001888 aborted = true;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001889 return;
1890 }
1891 uint64_t *bda_data;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001892 result = vmaMapMemory(vmaAllocator, bda_input_block.allocation, reinterpret_cast<void **>(&bda_data));
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001893 uint32_t address_index = 1;
1894 uint32_t size_index = 3 + num_buffers;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001895 memset(bda_data, 0, static_cast<size_t>(buffer_info.size));
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001896 bda_data[0] = size_index; // Start of buffer sizes
1897 bda_data[address_index++] = 0; // NULL address
1898 bda_data[size_index++] = 0;
1899
Tony-LunarG99b880b2019-09-26 11:19:52 -06001900 for (auto const &value : buffer_map) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001901 bda_data[address_index++] = value.first;
1902 bda_data[size_index++] = value.second;
1903 }
1904 bda_data[address_index] = UINTPTR_MAX;
1905 bda_data[size_index] = 0;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001906 vmaUnmapMemory(vmaAllocator, bda_input_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001907
1908 bda_input_desc_buffer_info.range = (words_needed * 8);
1909 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
1910 bda_input_desc_buffer_info.offset = 0;
1911
1912 desc_writes[desc_count].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1913 desc_writes[desc_count].dstBinding = 2;
1914 desc_writes[desc_count].descriptorCount = 1;
1915 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1916 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
1917 desc_writes[desc_count].dstSet = desc_sets[0];
1918 desc_count++;
1919 }
1920
Tony-LunarGb2501d22019-01-28 09:59:13 -07001921 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001922 output_desc_buffer_info.buffer = output_block.buffer;
1923 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001924
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001925 desc_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1926 desc_writes[0].descriptorCount = 1;
1927 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1928 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
1929 desc_writes[0].dstSet = desc_sets[0];
1930 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001931
locke-lunargb8d7a7a2020-10-25 16:01:52 -06001932 const auto *pipeline_state = state.pipeline_state;
1933 if (pipeline_state) {
1934 if ((pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index) &&
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06001935 !pipeline_state->pipeline_layout->destroyed) {
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001936 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout, desc_set_bind_index, 1,
Tony-LunarG99b880b2019-09-26 11:19:52 -06001937 desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001938 }
locke-lunargb8d7a7a2020-10-25 16:01:52 -06001939 if (pipeline_state->pipeline_layout->destroyed) {
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06001940 ReportSetupProblem(device, "Pipeline layout has been destroyed, aborting GPU-AV");
1941 aborted = true;
1942 } else {
1943 // Record buffer and memory info in CB state tracking
1944 GetBufferInfo(cmd_buffer)
1945 .emplace_back(output_block, di_input_block, bda_input_block, desc_sets[0], desc_pool, bind_point);
1946 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001947 } else {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001948 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06001949 aborted = true;
1950 }
1951 if (aborted) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001952 vmaDestroyBuffer(vmaAllocator, di_input_block.buffer, di_input_block.allocation);
1953 vmaDestroyBuffer(vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
1954 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001955 return;
1956 }
1957}