blob: cc9d0ec8055d9aaac96a5639e6a170b79472b848 [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
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -070021#include "gpu_validation.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060022#include "spirv-tools/optimizer.hpp"
23#include "spirv-tools/instrument.hpp"
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060024#include "layer_chassis_dispatch.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060025
Jason Macnak67407e72019-07-11 11:05:09 -070026static const VkShaderStageFlags kShaderStageAllRayTracing =
27 VK_SHADER_STAGE_ANY_HIT_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV | VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV |
28 VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV | VK_SHADER_STAGE_RAYGEN_BIT_NV;
29
Jason Macnak83cfd582019-07-31 10:14:24 -070030// Keep in sync with the GLSL shader below.
31struct GpuAccelerationStructureBuildValidationBuffer {
32 uint32_t instances_to_validate;
33 uint32_t replacement_handle_bits_0;
34 uint32_t replacement_handle_bits_1;
35 uint32_t invalid_handle_found;
36 uint32_t invalid_handle_bits_0;
37 uint32_t invalid_handle_bits_1;
38 uint32_t valid_handles_count;
39};
40
41// This is the GLSL source for the compute shader that is used during ray tracing acceleration structure
42// building validation which inspects instance buffers for top level acceleration structure builds and
43// reports and replaces invalid bottom level acceleration structure handles with good bottom level
44// acceleration structure handle so that applications can continue without undefined behavior long enough
45// to report errors.
46//
47// #version 450
48// layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
49// struct VkGeometryInstanceNV {
50// uint unused[14];
51// uint handle_bits_0;
52// uint handle_bits_1;
53// };
54// layout(set=0, binding=0, std430) buffer InstanceBuffer {
55// VkGeometryInstanceNV instances[];
56// };
57// layout(set=0, binding=1, std430) buffer ValidationBuffer {
58// uint instances_to_validate;
59// uint replacement_handle_bits_0;
60// uint replacement_handle_bits_1;
61// uint invalid_handle_found;
62// uint invalid_handle_bits_0;
63// uint invalid_handle_bits_1;
64// uint valid_handles_count;
65// uint valid_handles[];
66// };
67// void main() {
68// for (uint instance_index = 0; instance_index < instances_to_validate; instance_index++) {
69// uint instance_handle_bits_0 = instances[instance_index].handle_bits_0;
70// uint instance_handle_bits_1 = instances[instance_index].handle_bits_1;
71// bool valid = false;
72// for (uint valid_handle_index = 0; valid_handle_index < valid_handles_count; valid_handle_index++) {
73// if (instance_handle_bits_0 == valid_handles[2*valid_handle_index+0] &&
74// instance_handle_bits_1 == valid_handles[2*valid_handle_index+1]) {
75// valid = true;
76// break;
77// }
78// }
79// if (!valid) {
80// invalid_handle_found += 1;
81// invalid_handle_bits_0 = instance_handle_bits_0;
82// invalid_handle_bits_1 = instance_handle_bits_1;
83// instances[instance_index].handle_bits_0 = replacement_handle_bits_0;
84// instances[instance_index].handle_bits_1 = replacement_handle_bits_1;
85// }
86// }
87// }
88//
89// To regenerate the spirv below:
90// 1. Save the above GLSL source to a file called validation_shader.comp.
91// 2. Run in terminal
92//
93// glslangValidator.exe -x -V validation_shader.comp -o validation_shader.comp.spv
94//
95// 4. Copy-paste the contents of validation_shader.comp.spv here (clang-format will fix up the alignment).
96static const uint32_t kComputeShaderSpirv[] = {
97 0x07230203, 0x00010000, 0x00080007, 0x0000006d, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, 0x00000001, 0x4c534c47,
98 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0005000f, 0x00000005, 0x00000004, 0x6e69616d,
99 0x00000000, 0x00060010, 0x00000004, 0x00000011, 0x00000001, 0x00000001, 0x00000001, 0x00030003, 0x00000002, 0x000001c2,
100 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00060005, 0x00000008, 0x74736e69, 0x65636e61, 0x646e695f, 0x00007865,
101 0x00070005, 0x00000011, 0x696c6156, 0x69746164, 0x75426e6f, 0x72656666, 0x00000000, 0x00090006, 0x00000011, 0x00000000,
102 0x74736e69, 0x65636e61, 0x6f745f73, 0x6c61765f, 0x74616469, 0x00000065, 0x000a0006, 0x00000011, 0x00000001, 0x6c706572,
103 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x000a0006, 0x00000011, 0x00000002, 0x6c706572,
104 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00090006, 0x00000011, 0x00000003, 0x61766e69,
105 0x5f64696c, 0x646e6168, 0x665f656c, 0x646e756f, 0x00000000, 0x00090006, 0x00000011, 0x00000004, 0x61766e69, 0x5f64696c,
106 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00090006, 0x00000011, 0x00000005, 0x61766e69, 0x5f64696c, 0x646e6168,
107 0x625f656c, 0x5f737469, 0x00000031, 0x00080006, 0x00000011, 0x00000006, 0x696c6176, 0x61685f64, 0x656c646e, 0x6f635f73,
108 0x00746e75, 0x00070006, 0x00000011, 0x00000007, 0x696c6176, 0x61685f64, 0x656c646e, 0x00000073, 0x00030005, 0x00000013,
109 0x00000000, 0x00080005, 0x0000001b, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000305f, 0x00080005,
110 0x0000001e, 0x65476b56, 0x74656d6f, 0x6e497972, 0x6e617473, 0x564e6563, 0x00000000, 0x00050006, 0x0000001e, 0x00000000,
111 0x73756e75, 0x00006465, 0x00070006, 0x0000001e, 0x00000001, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00070006,
112 0x0000001e, 0x00000002, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00060005, 0x00000020, 0x74736e49, 0x65636e61,
113 0x66667542, 0x00007265, 0x00060006, 0x00000020, 0x00000000, 0x74736e69, 0x65636e61, 0x00000073, 0x00030005, 0x00000022,
114 0x00000000, 0x00080005, 0x00000027, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000315f, 0x00040005,
115 0x0000002d, 0x696c6176, 0x00000064, 0x00070005, 0x0000002f, 0x696c6176, 0x61685f64, 0x656c646e, 0x646e695f, 0x00007865,
116 0x00040047, 0x00000010, 0x00000006, 0x00000004, 0x00050048, 0x00000011, 0x00000000, 0x00000023, 0x00000000, 0x00050048,
117 0x00000011, 0x00000001, 0x00000023, 0x00000004, 0x00050048, 0x00000011, 0x00000002, 0x00000023, 0x00000008, 0x00050048,
118 0x00000011, 0x00000003, 0x00000023, 0x0000000c, 0x00050048, 0x00000011, 0x00000004, 0x00000023, 0x00000010, 0x00050048,
119 0x00000011, 0x00000005, 0x00000023, 0x00000014, 0x00050048, 0x00000011, 0x00000006, 0x00000023, 0x00000018, 0x00050048,
120 0x00000011, 0x00000007, 0x00000023, 0x0000001c, 0x00030047, 0x00000011, 0x00000003, 0x00040047, 0x00000013, 0x00000022,
121 0x00000000, 0x00040047, 0x00000013, 0x00000021, 0x00000001, 0x00040047, 0x0000001d, 0x00000006, 0x00000004, 0x00050048,
122 0x0000001e, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x0000001e, 0x00000001, 0x00000023, 0x00000038, 0x00050048,
123 0x0000001e, 0x00000002, 0x00000023, 0x0000003c, 0x00040047, 0x0000001f, 0x00000006, 0x00000040, 0x00050048, 0x00000020,
124 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x00000020, 0x00000003, 0x00040047, 0x00000022, 0x00000022, 0x00000000,
125 0x00040047, 0x00000022, 0x00000021, 0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00040015,
126 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, 0x00000006, 0x0004002b, 0x00000006, 0x00000009,
127 0x00000000, 0x0003001d, 0x00000010, 0x00000006, 0x000a001e, 0x00000011, 0x00000006, 0x00000006, 0x00000006, 0x00000006,
128 0x00000006, 0x00000006, 0x00000006, 0x00000010, 0x00040020, 0x00000012, 0x00000002, 0x00000011, 0x0004003b, 0x00000012,
129 0x00000013, 0x00000002, 0x00040015, 0x00000014, 0x00000020, 0x00000001, 0x0004002b, 0x00000014, 0x00000015, 0x00000000,
130 0x00040020, 0x00000016, 0x00000002, 0x00000006, 0x00020014, 0x00000019, 0x0004002b, 0x00000006, 0x0000001c, 0x0000000e,
131 0x0004001c, 0x0000001d, 0x00000006, 0x0000001c, 0x0005001e, 0x0000001e, 0x0000001d, 0x00000006, 0x00000006, 0x0003001d,
132 0x0000001f, 0x0000001e, 0x0003001e, 0x00000020, 0x0000001f, 0x00040020, 0x00000021, 0x00000002, 0x00000020, 0x0004003b,
133 0x00000021, 0x00000022, 0x00000002, 0x0004002b, 0x00000014, 0x00000024, 0x00000001, 0x0004002b, 0x00000014, 0x00000029,
134 0x00000002, 0x00040020, 0x0000002c, 0x00000007, 0x00000019, 0x0003002a, 0x00000019, 0x0000002e, 0x0004002b, 0x00000014,
135 0x00000036, 0x00000006, 0x0004002b, 0x00000014, 0x0000003b, 0x00000007, 0x0004002b, 0x00000006, 0x0000003c, 0x00000002,
136 0x0004002b, 0x00000006, 0x00000048, 0x00000001, 0x00030029, 0x00000019, 0x00000050, 0x0004002b, 0x00000014, 0x00000058,
137 0x00000003, 0x0004002b, 0x00000014, 0x0000005d, 0x00000004, 0x0004002b, 0x00000014, 0x00000060, 0x00000005, 0x00050036,
138 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007,
139 0x0004003b, 0x00000007, 0x0000001b, 0x00000007, 0x0004003b, 0x00000007, 0x00000027, 0x00000007, 0x0004003b, 0x0000002c,
140 0x0000002d, 0x00000007, 0x0004003b, 0x00000007, 0x0000002f, 0x00000007, 0x0003003e, 0x00000008, 0x00000009, 0x000200f9,
141 0x0000000a, 0x000200f8, 0x0000000a, 0x000400f6, 0x0000000c, 0x0000000d, 0x00000000, 0x000200f9, 0x0000000e, 0x000200f8,
142 0x0000000e, 0x0004003d, 0x00000006, 0x0000000f, 0x00000008, 0x00050041, 0x00000016, 0x00000017, 0x00000013, 0x00000015,
143 0x0004003d, 0x00000006, 0x00000018, 0x00000017, 0x000500b0, 0x00000019, 0x0000001a, 0x0000000f, 0x00000018, 0x000400fa,
144 0x0000001a, 0x0000000b, 0x0000000c, 0x000200f8, 0x0000000b, 0x0004003d, 0x00000006, 0x00000023, 0x00000008, 0x00070041,
145 0x00000016, 0x00000025, 0x00000022, 0x00000015, 0x00000023, 0x00000024, 0x0004003d, 0x00000006, 0x00000026, 0x00000025,
146 0x0003003e, 0x0000001b, 0x00000026, 0x0004003d, 0x00000006, 0x00000028, 0x00000008, 0x00070041, 0x00000016, 0x0000002a,
147 0x00000022, 0x00000015, 0x00000028, 0x00000029, 0x0004003d, 0x00000006, 0x0000002b, 0x0000002a, 0x0003003e, 0x00000027,
148 0x0000002b, 0x0003003e, 0x0000002d, 0x0000002e, 0x0003003e, 0x0000002f, 0x00000009, 0x000200f9, 0x00000030, 0x000200f8,
149 0x00000030, 0x000400f6, 0x00000032, 0x00000033, 0x00000000, 0x000200f9, 0x00000034, 0x000200f8, 0x00000034, 0x0004003d,
150 0x00000006, 0x00000035, 0x0000002f, 0x00050041, 0x00000016, 0x00000037, 0x00000013, 0x00000036, 0x0004003d, 0x00000006,
151 0x00000038, 0x00000037, 0x000500b0, 0x00000019, 0x00000039, 0x00000035, 0x00000038, 0x000400fa, 0x00000039, 0x00000031,
152 0x00000032, 0x000200f8, 0x00000031, 0x0004003d, 0x00000006, 0x0000003a, 0x0000001b, 0x0004003d, 0x00000006, 0x0000003d,
153 0x0000002f, 0x00050084, 0x00000006, 0x0000003e, 0x0000003c, 0x0000003d, 0x00050080, 0x00000006, 0x0000003f, 0x0000003e,
154 0x00000009, 0x00060041, 0x00000016, 0x00000040, 0x00000013, 0x0000003b, 0x0000003f, 0x0004003d, 0x00000006, 0x00000041,
155 0x00000040, 0x000500aa, 0x00000019, 0x00000042, 0x0000003a, 0x00000041, 0x000300f7, 0x00000044, 0x00000000, 0x000400fa,
156 0x00000042, 0x00000043, 0x00000044, 0x000200f8, 0x00000043, 0x0004003d, 0x00000006, 0x00000045, 0x00000027, 0x0004003d,
157 0x00000006, 0x00000046, 0x0000002f, 0x00050084, 0x00000006, 0x00000047, 0x0000003c, 0x00000046, 0x00050080, 0x00000006,
158 0x00000049, 0x00000047, 0x00000048, 0x00060041, 0x00000016, 0x0000004a, 0x00000013, 0x0000003b, 0x00000049, 0x0004003d,
159 0x00000006, 0x0000004b, 0x0000004a, 0x000500aa, 0x00000019, 0x0000004c, 0x00000045, 0x0000004b, 0x000200f9, 0x00000044,
160 0x000200f8, 0x00000044, 0x000700f5, 0x00000019, 0x0000004d, 0x00000042, 0x00000031, 0x0000004c, 0x00000043, 0x000300f7,
161 0x0000004f, 0x00000000, 0x000400fa, 0x0000004d, 0x0000004e, 0x0000004f, 0x000200f8, 0x0000004e, 0x0003003e, 0x0000002d,
162 0x00000050, 0x000200f9, 0x00000032, 0x000200f8, 0x0000004f, 0x000200f9, 0x00000033, 0x000200f8, 0x00000033, 0x0004003d,
163 0x00000006, 0x00000052, 0x0000002f, 0x00050080, 0x00000006, 0x00000053, 0x00000052, 0x00000024, 0x0003003e, 0x0000002f,
164 0x00000053, 0x000200f9, 0x00000030, 0x000200f8, 0x00000032, 0x0004003d, 0x00000019, 0x00000054, 0x0000002d, 0x000400a8,
165 0x00000019, 0x00000055, 0x00000054, 0x000300f7, 0x00000057, 0x00000000, 0x000400fa, 0x00000055, 0x00000056, 0x00000057,
166 0x000200f8, 0x00000056, 0x00050041, 0x00000016, 0x00000059, 0x00000013, 0x00000058, 0x0004003d, 0x00000006, 0x0000005a,
167 0x00000059, 0x00050080, 0x00000006, 0x0000005b, 0x0000005a, 0x00000048, 0x00050041, 0x00000016, 0x0000005c, 0x00000013,
168 0x00000058, 0x0003003e, 0x0000005c, 0x0000005b, 0x0004003d, 0x00000006, 0x0000005e, 0x0000001b, 0x00050041, 0x00000016,
169 0x0000005f, 0x00000013, 0x0000005d, 0x0003003e, 0x0000005f, 0x0000005e, 0x0004003d, 0x00000006, 0x00000061, 0x00000027,
170 0x00050041, 0x00000016, 0x00000062, 0x00000013, 0x00000060, 0x0003003e, 0x00000062, 0x00000061, 0x0004003d, 0x00000006,
171 0x00000063, 0x00000008, 0x00050041, 0x00000016, 0x00000064, 0x00000013, 0x00000024, 0x0004003d, 0x00000006, 0x00000065,
172 0x00000064, 0x00070041, 0x00000016, 0x00000066, 0x00000022, 0x00000015, 0x00000063, 0x00000024, 0x0003003e, 0x00000066,
173 0x00000065, 0x0004003d, 0x00000006, 0x00000067, 0x00000008, 0x00050041, 0x00000016, 0x00000068, 0x00000013, 0x00000029,
174 0x0004003d, 0x00000006, 0x00000069, 0x00000068, 0x00070041, 0x00000016, 0x0000006a, 0x00000022, 0x00000015, 0x00000067,
175 0x00000029, 0x0003003e, 0x0000006a, 0x00000069, 0x000200f9, 0x00000057, 0x000200f8, 0x00000057, 0x000200f9, 0x0000000d,
176 0x000200f8, 0x0000000d, 0x0004003d, 0x00000006, 0x0000006b, 0x00000008, 0x00050080, 0x00000006, 0x0000006c, 0x0000006b,
177 0x00000024, 0x0003003e, 0x00000008, 0x0000006c, 0x000200f9, 0x0000000a, 0x000200f8, 0x0000000c, 0x000100fd, 0x00010038};
178
Karl Schultz7b024b42018-08-30 16:18:18 -0600179// Convenience function for reporting problems with setting up GPU Validation.
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700180template <typename T>
181void GpuAssisted::ReportSetupProblem(T object, const char *const specific_message) const {
182 LogError(object, "UNASSIGNED-GPU-Assisted Validation Error. ", "Detail: (%s)", specific_message);
Karl Schultz7b024b42018-08-30 16:18:18 -0600183}
184
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600185void GpuAssisted::PreCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
186 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer, void *cb_state_data) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700187 // Ray tracing acceleration structure instance buffers also need the storage buffer usage as
188 // acceleration structure build validation will find and replace invalid acceleration structure
189 // handles inside of a compute shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600190 create_buffer_api_state *cb_state = reinterpret_cast<create_buffer_api_state *>(cb_state_data);
191 if (cb_state && cb_state->modified_create_info.usage & VK_BUFFER_USAGE_RAY_TRACING_BIT_NV) {
192 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
Jason Macnak83cfd582019-07-31 10:14:24 -0700193 }
194}
195
Karl Schultz7b024b42018-08-30 16:18:18 -0600196// Turn on necessary device features.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600197void GpuAssisted::PreCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info,
198 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
199 safe_VkDeviceCreateInfo *modified_create_info) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600200 DispatchGetPhysicalDeviceFeatures(gpu, &supported_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600201 VkPhysicalDeviceFeatures features = {};
202 features.vertexPipelineStoresAndAtomics = true;
203 features.fragmentStoresAndAtomics = true;
204 features.shaderInt64 = true;
Tony-LunarGb5fae462020-03-05 12:43:25 -0700205 UtilPreCallRecordCreateDevice(gpu, modified_create_info, supported_features, features);
Karl Schultz7b024b42018-08-30 16:18:18 -0600206}
Karl Schultz7b024b42018-08-30 16:18:18 -0600207// Perform initializations that can be done at Create Device time.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600208void GpuAssisted::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
209 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result) {
210 // The state tracker sets up the device state
Tony-LunarG99b880b2019-09-26 11:19:52 -0600211 ValidationStateTracker::PostCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski5dc3dcd2019-04-23 14:26:28 -0600212
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600213 ValidationObject *device_object = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
214 ValidationObject *validation_data = GetValidationObject(device_object->object_dispatch, this->container_type);
215 GpuAssisted *device_gpu_assisted = static_cast<GpuAssisted *>(validation_data);
Tony-LunarG65f9c492019-01-17 14:24:42 -0700216
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600217 if (device_gpu_assisted->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700218 ReportSetupProblem(device, "GPU-Assisted validation requires Vulkan 1.1 or later. GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600219 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600220 return;
221 }
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600222
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600223 if (!device_gpu_assisted->enabled_features.core.fragmentStoresAndAtomics ||
224 !device_gpu_assisted->enabled_features.core.vertexPipelineStoresAndAtomics) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700225 ReportSetupProblem(device,
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600226 "GPU-Assisted validation requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
227 "GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600228 device_gpu_assisted->aborted = true;
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600229 return;
230 }
231
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700232 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) &&
233 !device_gpu_assisted->enabled_features.core.shaderInt64) {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700234 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
235 "shaderInt64 feature is not available. No buffer device address checking will be attempted");
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600236 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600237 device_gpu_assisted->shaderInt64 = device_gpu_assisted->enabled_features.core.shaderInt64;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600238 device_gpu_assisted->physicalDevice = physicalDevice;
239 device_gpu_assisted->device = *pDevice;
Tony-LunarGbb145f32020-04-27 13:41:29 -0600240 device_gpu_assisted->output_buffer_size = sizeof(uint32_t) * (spvtools::kInstMaxOutCnt + 1);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600241 std::vector<VkDescriptorSetLayoutBinding> bindings;
242 VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
243 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT | kShaderStageAllRayTracing,
244 NULL};
245 bindings.push_back(binding);
246 for (auto i = 1; i < 3; i++) {
247 binding.binding = i;
248 bindings.push_back(binding);
Karl Schultz7b024b42018-08-30 16:18:18 -0600249 }
Tony-LunarGb5fae462020-03-05 12:43:25 -0700250 UtilPostCallRecordCreateDevice(pCreateInfo, bindings, device_gpu_assisted, device_gpu_assisted->phys_dev_props);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600251 CreateAccelerationStructureBuildValidationState(device_gpu_assisted);
Karl Schultz7b024b42018-08-30 16:18:18 -0600252}
253
Tony-LunarG588c7052020-04-23 10:47:21 -0600254void GpuAssisted::PostCallRecordGetBufferDeviceAddress(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
255 VkDeviceAddress address) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600256 BUFFER_STATE *buffer_state = GetBufferState(pInfo->buffer);
257 // Validate against the size requested when the buffer was created
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600258 if (buffer_state) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600259 buffer_map[address] = buffer_state->createInfo.size;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600260 buffer_state->deviceAddress = address;
261 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600262}
263
Tony-LunarG588c7052020-04-23 10:47:21 -0600264void GpuAssisted::PostCallRecordGetBufferDeviceAddressEXT(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
265 VkDeviceAddress address) {
266 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
267}
268
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700269void GpuAssisted::PostCallRecordGetBufferDeviceAddressKHR(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
270 VkDeviceAddress address) {
Tony-LunarG588c7052020-04-23 10:47:21 -0600271 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700272}
273
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600274void GpuAssisted::PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600275 BUFFER_STATE *buffer_state = GetBufferState(buffer);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600276 if (buffer_state) buffer_map.erase(buffer_state->deviceAddress);
Tony-LunarG2966c732020-05-21 10:33:53 -0600277 ValidationStateTracker::PreCallRecordDestroyBuffer(device, buffer, pAllocator);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600278}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600279
Karl Schultz7b024b42018-08-30 16:18:18 -0600280// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600281void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600282 DestroyAccelerationStructureBuildValidationState();
Tony-LunarGb5fae462020-03-05 12:43:25 -0700283 UtilPreCallRecordDestroyDevice(this);
Tony-LunarG2966c732020-05-21 10:33:53 -0600284 ValidationStateTracker::PreCallRecordDestroyDevice(device, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -0600285}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600286
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600287void GpuAssisted::CreateAccelerationStructureBuildValidationState(GpuAssisted *device_gpuav) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600288 if (device_gpuav->aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700289 return;
290 }
291
Tony-LunarG99b880b2019-09-26 11:19:52 -0600292 auto &as_validation_state = device_gpuav->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700293 if (as_validation_state.initialized) {
294 return;
295 }
296
297 if (!device_extensions.vk_nv_ray_tracing) {
298 return;
299 }
300
301 // Outline:
302 // - Create valid bottom level acceleration structure which acts as replacement
303 // - Create and load vertex buffer
304 // - Create and load index buffer
305 // - Create, allocate memory for, and bind memory for acceleration structure
306 // - Query acceleration structure handle
307 // - Create command pool and command buffer
308 // - Record build acceleration structure command
309 // - Submit command buffer and wait for completion
310 // - Cleanup
311 // - Create compute pipeline for validating instance buffers
312 // - Create descriptor set layout
313 // - Create pipeline layout
314 // - Create pipeline
315 // - Cleanup
316
317 VkResult result = VK_SUCCESS;
318
319 VkBuffer vbo = VK_NULL_HANDLE;
320 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
321 if (result == VK_SUCCESS) {
322 VkBufferCreateInfo vbo_ci = {};
323 vbo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
324 vbo_ci.size = sizeof(float) * 9;
325 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
326
327 VmaAllocationCreateInfo vbo_ai = {};
328 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
329 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
330
Tony-LunarG99b880b2019-09-26 11:19:52 -0600331 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700332 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700333 ReportSetupProblem(device, "Failed to create vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700334 }
335 }
336
337 if (result == VK_SUCCESS) {
338 uint8_t *mapped_vbo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600339 result = vmaMapMemory(device_gpuav->vmaAllocator, vbo_allocation, (void **)&mapped_vbo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700340 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700341 ReportSetupProblem(device, "Failed to map vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700342 } else {
343 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
344 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600345 vmaUnmapMemory(device_gpuav->vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700346 }
347 }
348
349 VkBuffer ibo = VK_NULL_HANDLE;
350 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
351 if (result == VK_SUCCESS) {
352 VkBufferCreateInfo ibo_ci = {};
353 ibo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
354 ibo_ci.size = sizeof(uint32_t) * 3;
355 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
356
357 VmaAllocationCreateInfo ibo_ai = {};
358 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
359 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
360
Tony-LunarG99b880b2019-09-26 11:19:52 -0600361 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700362 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700363 ReportSetupProblem(device, "Failed to create index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700364 }
365 }
366
367 if (result == VK_SUCCESS) {
368 uint8_t *mapped_ibo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600369 result = vmaMapMemory(device_gpuav->vmaAllocator, ibo_allocation, (void **)&mapped_ibo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700370 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700371 ReportSetupProblem(device, "Failed to map index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700372 } else {
373 const std::vector<uint32_t> indicies = {0, 1, 2};
374 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600375 vmaUnmapMemory(device_gpuav->vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700376 }
377 }
378
379 VkGeometryNV geometry = {};
380 geometry.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
381 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
382 geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
383 geometry.geometry.triangles.vertexData = vbo;
384 geometry.geometry.triangles.vertexOffset = 0;
385 geometry.geometry.triangles.vertexCount = 3;
386 geometry.geometry.triangles.vertexStride = 12;
387 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
388 geometry.geometry.triangles.indexData = ibo;
389 geometry.geometry.triangles.indexOffset = 0;
390 geometry.geometry.triangles.indexCount = 3;
391 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
392 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
393 geometry.geometry.triangles.transformOffset = 0;
394 geometry.geometry.aabbs = {};
395 geometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
396
397 VkAccelerationStructureCreateInfoNV as_ci = {};
398 as_ci.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
399 as_ci.info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
400 as_ci.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV;
401 as_ci.info.instanceCount = 0;
402 as_ci.info.geometryCount = 1;
403 as_ci.info.pGeometries = &geometry;
404 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600405 result = DispatchCreateAccelerationStructureNV(device_gpuav->device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700406 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700407 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700408 "Failed to create acceleration structure for acceleration structure build validation.");
409 }
410 }
411
412 VkMemoryRequirements2 as_mem_requirements = {};
413 if (result == VK_SUCCESS) {
414 VkAccelerationStructureMemoryRequirementsInfoNV as_mem_requirements_info = {};
415 as_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
416 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
417 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
418
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600419 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700420 }
421
422 VmaAllocationInfo as_memory_ai = {};
423 if (result == VK_SUCCESS) {
424 VmaAllocationCreateInfo as_memory_aci = {};
425 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
426
Tony-LunarG99b880b2019-09-26 11:19:52 -0600427 result = vmaAllocateMemory(device_gpuav->vmaAllocator, &as_mem_requirements.memoryRequirements, &as_memory_aci,
428 &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700429 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700430 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700431 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
432 }
433 }
434
435 if (result == VK_SUCCESS) {
436 VkBindAccelerationStructureMemoryInfoNV as_bind_info = {};
437 as_bind_info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
438 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
439 as_bind_info.memory = as_memory_ai.deviceMemory;
440 as_bind_info.memoryOffset = as_memory_ai.offset;
441
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600442 result = DispatchBindAccelerationStructureMemoryNV(device_gpuav->device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700443 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700444 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700445 "Failed to bind acceleration structure memory for acceleration structure build validation.");
446 }
447 }
448
449 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600450 result = DispatchGetAccelerationStructureHandleNV(device_gpuav->device, as_validation_state.replacement_as,
451 sizeof(uint64_t), &as_validation_state.replacement_as_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700452 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700453 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700454 "Failed to get acceleration structure handle for acceleration structure build validation.");
455 }
456 }
457
458 VkMemoryRequirements2 scratch_mem_requirements = {};
459 if (result == VK_SUCCESS) {
460 VkAccelerationStructureMemoryRequirementsInfoNV scratch_mem_requirements_info = {};
461 scratch_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
462 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
463 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
464
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600465 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &scratch_mem_requirements_info,
466 &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700467 }
468
469 VkBuffer scratch = VK_NULL_HANDLE;
Tony-LunarG18900282020-05-20 12:34:33 -0600470 VmaAllocation scratch_allocation = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700471 if (result == VK_SUCCESS) {
472 VkBufferCreateInfo scratch_ci = {};
473 scratch_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
474 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
475 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
Jason Macnak83cfd582019-07-31 10:14:24 -0700476 VmaAllocationCreateInfo scratch_aci = {};
477 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
478
Tony-LunarG18900282020-05-20 12:34:33 -0600479 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &scratch_ci, &scratch_aci, &scratch, &scratch_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700480 if (result != VK_SUCCESS) {
Tony-LunarG18900282020-05-20 12:34:33 -0600481 ReportSetupProblem(device_gpuav->device,
482 "Failed to create scratch buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700483 }
484 }
485
486 VkCommandPool command_pool = VK_NULL_HANDLE;
487 if (result == VK_SUCCESS) {
488 VkCommandPoolCreateInfo command_pool_ci = {};
489 command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
490 command_pool_ci.queueFamilyIndex = 0;
491
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600492 result = DispatchCreateCommandPool(device_gpuav->device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700493 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700494 ReportSetupProblem(device_gpuav->device, "Failed to create command pool for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700495 }
496 }
497
498 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
499
500 if (result == VK_SUCCESS) {
501 VkCommandBufferAllocateInfo command_buffer_ai = {};
502 command_buffer_ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
503 command_buffer_ai.commandPool = command_pool;
504 command_buffer_ai.commandBufferCount = 1;
505 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
506
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600507 result = DispatchAllocateCommandBuffers(device_gpuav->device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700508 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700509 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700510 "Failed to create command buffer for acceleration structure build validation.");
511 }
512
513 // Hook up command buffer dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600514 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700515 }
516
517 if (result == VK_SUCCESS) {
518 VkCommandBufferBeginInfo command_buffer_bi = {};
519 command_buffer_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
520
521 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
522 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700523 ReportSetupProblem(device_gpuav->device, "Failed to begin command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700524 }
525 }
526
527 if (result == VK_SUCCESS) {
528 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
529 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
530 DispatchEndCommandBuffer(command_buffer);
531 }
532
533 VkQueue queue = VK_NULL_HANDLE;
534 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600535 DispatchGetDeviceQueue(device_gpuav->device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700536
537 // Hook up queue dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600538 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700539
540 VkSubmitInfo submit_info = {};
541 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
542 submit_info.commandBufferCount = 1;
543 submit_info.pCommandBuffers = &command_buffer;
544 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
545 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700546 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700547 "Failed to submit command buffer for acceleration structure build validation.");
548 }
549 }
550
551 if (result == VK_SUCCESS) {
552 result = DispatchQueueWaitIdle(queue);
553 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700554 ReportSetupProblem(device_gpuav->device, "Failed to wait for queue idle for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700555 }
556 }
557
558 if (vbo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600559 vmaDestroyBuffer(device_gpuav->vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700560 }
561 if (ibo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600562 vmaDestroyBuffer(device_gpuav->vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700563 }
564 if (scratch != VK_NULL_HANDLE) {
Tony-LunarG18900282020-05-20 12:34:33 -0600565 vmaDestroyBuffer(device_gpuav->vmaAllocator, scratch, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700566 }
567 if (command_pool != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600568 DispatchDestroyCommandPool(device_gpuav->device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700569 }
570
Tony-LunarG99b880b2019-09-26 11:19:52 -0600571 if (device_gpuav->debug_desc_layout == VK_NULL_HANDLE) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700572 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700573 "Failed to find descriptor set layout for acceleration structure build validation.");
574 result = VK_INCOMPLETE;
575 }
576
577 if (result == VK_SUCCESS) {
578 VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
579 pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
580 pipeline_layout_ci.setLayoutCount = 1;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600581 pipeline_layout_ci.pSetLayouts = &device_gpuav->debug_desc_layout;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600582 result = DispatchCreatePipelineLayout(device_gpuav->device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700583 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700584 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700585 "Failed to create pipeline layout for acceleration structure build validation.");
586 }
587 }
588
589 VkShaderModule shader_module = VK_NULL_HANDLE;
590 if (result == VK_SUCCESS) {
591 VkShaderModuleCreateInfo shader_module_ci = {};
592 shader_module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
593 shader_module_ci.codeSize = sizeof(kComputeShaderSpirv);
594 shader_module_ci.pCode = (uint32_t *)kComputeShaderSpirv;
595
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600596 result = DispatchCreateShaderModule(device_gpuav->device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700597 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700598 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700599 "Failed to create compute shader module for acceleration structure build validation.");
600 }
601 }
602
603 if (result == VK_SUCCESS) {
604 VkPipelineShaderStageCreateInfo pipeline_stage_ci = {};
605 pipeline_stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
606 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
607 pipeline_stage_ci.module = shader_module;
608 pipeline_stage_ci.pName = "main";
609
610 VkComputePipelineCreateInfo pipeline_ci = {};
611 pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
612 pipeline_ci.stage = pipeline_stage_ci;
613 pipeline_ci.layout = as_validation_state.pipeline_layout;
614
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600615 result = DispatchCreateComputePipelines(device_gpuav->device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr,
616 &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700617 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700618 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700619 "Failed to create compute pipeline for acceleration structure build validation.");
620 }
621 }
622
623 if (shader_module != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600624 DispatchDestroyShaderModule(device_gpuav->device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700625 }
626
627 if (result == VK_SUCCESS) {
628 as_validation_state.initialized = true;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700629 LogInfo(device_gpuav->device, "UNASSIGNED-GPU-Assisted Validation.",
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600630 "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700631 } else {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600632 device_gpuav->aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700633 }
634}
635
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600636void GpuAssisted::DestroyAccelerationStructureBuildValidationState() {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600637 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700638 if (as_validation_state.pipeline != VK_NULL_HANDLE) {
639 DispatchDestroyPipeline(device, as_validation_state.pipeline, nullptr);
640 }
641 if (as_validation_state.pipeline_layout != VK_NULL_HANDLE) {
642 DispatchDestroyPipelineLayout(device, as_validation_state.pipeline_layout, nullptr);
643 }
644 if (as_validation_state.replacement_as != VK_NULL_HANDLE) {
645 DispatchDestroyAccelerationStructureNV(device, as_validation_state.replacement_as, nullptr);
646 }
647 if (as_validation_state.replacement_as_allocation != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600648 vmaFreeMemory(vmaAllocator, as_validation_state.replacement_as_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700649 }
650}
651
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600652struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700653 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
654 VkPipeline pipeline = VK_NULL_HANDLE;
655 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
656 std::vector<VkDescriptorSet> descriptor_sets;
657 std::vector<std::vector<uint32_t>> dynamic_offsets;
658 uint32_t push_descriptor_set_index = 0;
659 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
660 std::vector<uint8_t> push_constants_data;
661 PushConstantRangesId push_constants_ranges;
662
663 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
664 pipeline_bind_point = bind_point;
665
666 LAST_BOUND_STATE &last_bound = cb_state->lastBound[bind_point];
667 if (last_bound.pipeline_state) {
668 pipeline = last_bound.pipeline_state->pipeline;
669 pipeline_layout = last_bound.pipeline_layout;
670 descriptor_sets.reserve(last_bound.per_set.size());
671 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
672 const auto *bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
673
674 descriptor_sets.push_back(bound_descriptor_set->GetSet());
675 if (bound_descriptor_set->IsPushDescriptor()) {
676 push_descriptor_set_index = static_cast<uint32_t>(i);
677 }
678 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
679 }
680
681 if (last_bound.push_descriptor_set) {
682 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
683 }
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500684 if (last_bound.pipeline_state->pipeline_layout->push_constant_ranges == cb_state->push_constant_data_ranges) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700685 push_constants_data = cb_state->push_constant_data;
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500686 push_constants_ranges = last_bound.pipeline_state->pipeline_layout->push_constant_ranges;
Jason Macnak83cfd582019-07-31 10:14:24 -0700687 }
688 }
689 }
690
691 void Restore(VkCommandBuffer command_buffer) const {
692 if (pipeline != VK_NULL_HANDLE) {
693 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
694 if (!descriptor_sets.empty()) {
695 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
696 VkDescriptorSet descriptor_set = descriptor_sets[i];
697 if (descriptor_set != VK_NULL_HANDLE) {
698 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
699 static_cast<uint32_t>(i), 1, &descriptor_set,
700 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
701 }
702 }
703 }
704 if (!push_descriptor_set_writes.empty()) {
705 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
706 static_cast<uint32_t>(push_descriptor_set_writes.size()),
707 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
708 }
709 for (const auto &push_constant_range : *push_constants_ranges) {
710 if (push_constant_range.size == 0) continue;
711 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
712 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
713 }
714 }
715 }
716};
717
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600718void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
719 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
720 VkDeviceSize instanceOffset, VkBool32 update,
721 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
722 VkBuffer scratch, VkDeviceSize scratchOffset) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700723 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
724 return;
725 }
726
Tony-LunarG99b880b2019-09-26 11:19:52 -0600727 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700728 if (!as_validation_state.initialized) {
729 return;
730 }
731
732 // Empty acceleration structure is valid according to the spec.
733 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
734 return;
735 }
736
737 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
738 assert(cb_state != nullptr);
739
740 std::vector<uint64_t> current_valid_handles;
741 for (const auto &as_state_kv : accelerationStructureMap) {
742 const ACCELERATION_STRUCTURE_STATE &as_state = *as_state_kv.second;
Jeff Bolz95176d02020-04-01 00:36:16 -0500743 if (as_state.built && as_state.create_infoNV.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700744 current_valid_handles.push_back(as_state.opaque_handle);
745 }
746 }
747
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600748 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700749 as_validation_buffer_info.acceleration_structure = dst;
750
751 const VkDeviceSize validation_buffer_size =
752 // One uint for number of instances to validate
753 4 +
754 // Two uint for the replacement acceleration structure handle
755 8 +
756 // One uint for number of invalid handles found
757 4 +
758 // Two uint for the first invalid handle found
759 8 +
760 // One uint for the number of current valid handles
761 4 +
762 // Two uint for each current valid handle
763 (8 * current_valid_handles.size());
764
765 VkBufferCreateInfo validation_buffer_create_info = {};
766 validation_buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
767 validation_buffer_create_info.size = validation_buffer_size;
768 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
769
770 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
771 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
772
Tony-LunarG99b880b2019-09-26 11:19:52 -0600773 VkResult result = vmaCreateBuffer(vmaAllocator, &validation_buffer_create_info, &validation_buffer_alloc_info,
774 &as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -0700775 &as_validation_buffer_info.validation_buffer_allocation, nullptr);
776 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700777 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600778 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700779 return;
780 }
781
782 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600783 result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700784 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700785 ReportSetupProblem(device, "Unable to allocate device memory for acceleration structure build val buffer.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600786 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700787 return;
788 }
789
790 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
791 mapped_validation_buffer->replacement_handle_bits_0 =
792 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
793 mapped_validation_buffer->replacement_handle_bits_1 =
794 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
795 mapped_validation_buffer->invalid_handle_found = 0;
796 mapped_validation_buffer->invalid_handle_bits_0 = 0;
797 mapped_validation_buffer->invalid_handle_bits_1 = 0;
798 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
799
800 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
801 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
802 const uint64_t current_valid_handle = current_valid_handles[i];
803
804 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
805 ++mapped_valid_handles;
806 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
807 ++mapped_valid_handles;
808 }
809
Tony-LunarG99b880b2019-09-26 11:19:52 -0600810 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700811
812 static constexpr const VkDeviceSize kInstanceSize = 64;
813 const VkDeviceSize instance_buffer_size = kInstanceSize * pInfo->instanceCount;
814
Tony-LunarG1dce2392019-10-23 16:49:29 -0600815 result = desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool, debug_desc_layout,
816 &as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700817 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700818 ReportSetupProblem(device, "Unable to get descriptor set for acceleration structure build.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600819 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700820 return;
821 }
822
823 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
824 descriptor_buffer_infos[0].buffer = instanceData;
825 descriptor_buffer_infos[0].offset = instanceOffset;
826 descriptor_buffer_infos[0].range = instance_buffer_size;
827 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.validation_buffer;
828 descriptor_buffer_infos[1].offset = 0;
829 descriptor_buffer_infos[1].range = validation_buffer_size;
830
831 VkWriteDescriptorSet descriptor_set_writes[2] = {};
832 descriptor_set_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
833 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
834 descriptor_set_writes[0].dstBinding = 0;
835 descriptor_set_writes[0].descriptorCount = 1;
836 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
837 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
838 descriptor_set_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
839 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
840 descriptor_set_writes[1].dstBinding = 1;
841 descriptor_set_writes[1].descriptorCount = 1;
842 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
843 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
844
845 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
846
847 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
848 VkMemoryBarrier memory_barrier = {};
849 memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
850 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
851 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
852 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
853 &memory_barrier, 0, nullptr, 0, nullptr);
854
855 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600856 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700857 restorable_state.Create(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
858
859 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
860 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
861 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
862 &as_validation_buffer_info.descriptor_set, 0, nullptr);
863 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
864
865 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
866 // have been replaced by the validation compute shader before any builds take place.
867 VkBufferMemoryBarrier instance_buffer_barrier = {};
868 instance_buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
869 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
870 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
871 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
872 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
873 instance_buffer_barrier.buffer = instanceData;
874 instance_buffer_barrier.offset = instanceOffset;
875 instance_buffer_barrier.size = instance_buffer_size;
876 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
877 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
878 nullptr);
879
880 // Restore the previous compute pipeline state.
881 restorable_state.Restore(commandBuffer);
882
883 as_validation_state.validation_buffers[commandBuffer].push_back(std::move(as_validation_buffer_info));
884}
885
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600886void GpuAssisted::ProcessAccelerationStructureBuildValidationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700887 if (cb_node == nullptr || !cb_node->hasBuildAccelerationStructureCmd) {
888 return;
889 }
890
Tony-LunarG99b880b2019-09-26 11:19:52 -0600891 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700892 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[cb_node->commandBuffer];
893 for (const auto &as_validation_buffer_info : as_validation_buffer_infos) {
894 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
895
Tony-LunarG99b880b2019-09-26 11:19:52 -0600896 VkResult result =
897 vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700898 if (result == VK_SUCCESS) {
899 if (mapped_validation_buffer->invalid_handle_found > 0) {
900 uint64_t invalid_handle = 0;
901 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
902 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
903
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700904 LogError(as_validation_buffer_info.acceleration_structure, "UNASSIGNED-AccelerationStructure",
905 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
906 "handle (%" PRIu64 ")",
907 invalid_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700908 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600909 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700910 }
911 }
912}
913
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600914void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
915 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
916 VkResult result) {
917 if (VK_SUCCESS != result) return;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600918 ValidationStateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600919 for (uint32_t i = 0; i < bindInfoCount; i++) {
920 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
921 ACCELERATION_STRUCTURE_STATE *as_state = GetAccelerationStructureState(info.accelerationStructure);
922 if (as_state) {
923 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
924 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600925 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600926}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700927
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600928// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
929void GpuAssisted::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
930 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
931 void *cpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600932 if (aborted) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600933 return;
934 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600935
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600936 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
937
Tony-LunarG99b880b2019-09-26 11:19:52 -0600938 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600939 std::ostringstream strm;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600940 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Karl Schultz7b024b42018-08-30 16:18:18 -0600941 << "Application has too many descriptor sets in the pipeline layout to continue with gpu validation. "
942 << "Validation is not modifying the pipeline layout. "
943 << "Instrumented shaders are replaced with non-instrumented shaders.";
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700944 ReportSetupProblem(device, strm.str().c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -0600945 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700946 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Karl Schultz7b024b42018-08-30 16:18:18 -0600947 }
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700948}
949
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600950void GpuAssisted::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
951 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
952 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600953 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
954
Karl Schultz7b024b42018-08-30 16:18:18 -0600955 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700956 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600957 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600958 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600959}
960
Karl Schultz7b024b42018-08-30 16:18:18 -0600961// Free the device memory and descriptor set associated with a command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600962void GpuAssisted::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600963 if (aborted) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600964 return;
965 }
Tony-LunarG1dce2392019-10-23 16:49:29 -0600966 auto gpuav_buffer_list = GetBufferInfo(commandBuffer);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600967 for (auto buffer_info : gpuav_buffer_list) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600968 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600969 if (buffer_info.di_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600970 vmaDestroyBuffer(vmaAllocator, buffer_info.di_input_mem_block.buffer, buffer_info.di_input_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600971 }
972 if (buffer_info.bda_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600973 vmaDestroyBuffer(vmaAllocator, buffer_info.bda_input_mem_block.buffer, buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -0600974 }
Tony-LunarGdcbc2c32019-05-06 10:17:44 -0600975 if (buffer_info.desc_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600976 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Tony-LunarGdcbc2c32019-05-06 10:17:44 -0600977 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600978 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600979 command_buffer_map.erase(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700980
Tony-LunarG99b880b2019-09-26 11:19:52 -0600981 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700982 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[commandBuffer];
983 for (auto &as_validation_buffer_info : as_validation_buffer_infos) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600984 vmaDestroyBuffer(vmaAllocator, as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -0700985 as_validation_buffer_info.validation_buffer_allocation);
986
987 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600988 desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool,
989 as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700990 }
991 }
992 as_validation_info.validation_buffers.erase(commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -0600993}
Karl Schultz7b024b42018-08-30 16:18:18 -0600994// Just gives a warning about a possible deadlock.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600995bool GpuAssisted::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
996 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
997 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
998 uint32_t bufferMemoryBarrierCount,
999 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
Jeff Bolz5c801d12019-10-09 10:38:45 -05001000 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001001 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001002 ReportSetupProblem(commandBuffer,
Karl Schultz7b024b42018-08-30 16:18:18 -06001003 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1004 "GPU_Assisted validation waits on queue completion. "
1005 "This wait could block the host's signaling of this event, resulting in deadlock.");
1006 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001007 return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001008}
1009
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001010void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1011 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
1012 // 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 -06001013 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001014 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
1015 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
1016 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001017 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1018 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001019 }
1020 }
1021}
1022
1023void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1024 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
1025 // 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 -06001026 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001027 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
1028 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
1029 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001030 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1031 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001032 }
1033 }
1034}
1035
1036void GpuAssisted::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1037 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1038 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1039 void *cgpl_state_data) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001040 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001041 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001042 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
1043 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001044 cgpl_state->gpu_create_infos = new_pipeline_create_infos;
1045 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001046}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001047
1048void GpuAssisted::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1049 const VkComputePipelineCreateInfo *pCreateInfos,
1050 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1051 void *ccpl_state_data) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001052 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001053 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001054 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
1055 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001056 ccpl_state->gpu_create_infos = new_pipeline_create_infos;
1057 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
Jason Macnak67407e72019-07-11 11:05:09 -07001058}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001059
1060void GpuAssisted::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1061 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1062 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1063 void *crtpl_state_data) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001064 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001065 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001066 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1067 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001068 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1069 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001070}
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001071
1072void GpuAssisted::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1073 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1074 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1075 void *crtpl_state_data) {
1076 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
1077 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001078 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1079 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001080 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1081 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->gpu_create_infos.data());
1082}
Karl Schultz7b024b42018-08-30 16:18:18 -06001083
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001084void GpuAssisted::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1085 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1086 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1087 VkResult result, void *cgpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001088 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
1089 pPipelines, result, cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001090 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001091}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001092
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001093void GpuAssisted::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1094 const VkComputePipelineCreateInfo *pCreateInfos,
1095 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1096 VkResult result, void *ccpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001097 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1098 result, ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001099 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001100}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001101
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001102void GpuAssisted::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1103 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1104 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1105 VkResult result, void *crtpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001106 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
1107 pPipelines, result, crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001108 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Jason Macnak67407e72019-07-11 11:05:09 -07001109}
1110
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001111void GpuAssisted::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1112 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1113 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1114 VkResult result, void *crtpl_state_data) {
1115 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesKHR(device, pipelineCache, count, pCreateInfos, pAllocator,
1116 pPipelines, result, crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001117 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Karl Schultz7b024b42018-08-30 16:18:18 -06001118}
1119
1120// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001121void GpuAssisted::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001122 for (auto it = shader_map.begin(); it != shader_map.end();) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001123 if (it->second.pipeline == pipeline) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001124 it = shader_map.erase(it);
Karl Schultz7b024b42018-08-30 16:18:18 -06001125 } else {
1126 ++it;
1127 }
1128 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001129 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001130}
1131
1132// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001133bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
1134 uint32_t *unique_shader_id) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001135 if (aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001136 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
1137
1138 // Load original shader SPIR-V
1139 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
1140 new_pgm.clear();
1141 new_pgm.reserve(num_words);
1142 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
1143
1144 // Call the optimizer to instrument the shader.
1145 // 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 -07001146 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Tony-LunarG2ec96bb2019-11-26 13:43:02 -07001147 const bool descriptor_indexing = IsExtEnabled(device_extensions.vk_ext_descriptor_indexing);
Karl Schultz7b024b42018-08-30 16:18:18 -06001148 using namespace spvtools;
1149 spv_target_env target_env = SPV_ENV_VULKAN_1_1;
1150 Optimizer optimizer(target_env);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001151 optimizer.RegisterPass(
Tony-LunarGab47cac2019-12-20 15:28:01 -07001152 CreateInstBindlessCheckPass(desc_set_bind_index, unique_shader_module_id, descriptor_indexing, descriptor_indexing));
Karl Schultz7b024b42018-08-30 16:18:18 -06001153 optimizer.RegisterPass(CreateAggressiveDCEPass());
Tony-LunarG7e0842f2019-12-10 09:26:34 -07001154 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) && shaderInt64)
Tony-LunarG99b880b2019-09-26 11:19:52 -06001155 optimizer.RegisterPass(CreateInstBuffAddrCheckPass(desc_set_bind_index, unique_shader_module_id));
Karl Schultz7b024b42018-08-30 16:18:18 -06001156 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm);
1157 if (!pass) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001158 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Karl Schultz7b024b42018-08-30 16:18:18 -06001159 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001160 *unique_shader_id = unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -06001161 return pass;
1162}
Mark Lobodzinski01734072019-02-13 17:39:15 -07001163// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001164void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
1165 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
1166 void *csm_state_data) {
1167 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
1168 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -06001169 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001170 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
1171 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
Karl Schultz7b024b42018-08-30 16:18:18 -06001172 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001173}
1174
Karl Schultz7b024b42018-08-30 16:18:18 -06001175// Generate the part of the message describing the violation.
1176static void GenerateValidationMessage(const uint32_t *debug_record, std::string &msg, std::string &vuid_msg) {
1177 using namespace spvtools;
1178 std::ostringstream strm;
Tony-LunarGab47cac2019-12-20 15:28:01 -07001179 switch (debug_record[kInstValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001180 case kInstErrorBindlessBounds: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001181 strm << "Index of " << debug_record[kInstBindlessBoundsOutDescIndex] << " used to index descriptor array of length "
1182 << debug_record[kInstBindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001183 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -06001184 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001185 case kInstErrorBindlessUninit: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001186 strm << "Descriptor index " << debug_record[kInstBindlessUninitOutDescIndex] << " is uninitialized. ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001187 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -06001188 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001189 case kInstErrorBuffAddrUnallocRef: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001190 uint64_t *ptr = (uint64_t *)&debug_record[kInstBuffAddrUnallocOutDescPtrLo];
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001191 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
1192 vuid_msg = "UNASSIGNED-Device address out of bounds";
1193 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001194 default: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001195 strm << "Internal Error (unexpected error type = " << debug_record[kInstValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001196 vuid_msg = "UNASSIGNED-Internal Error";
1197 assert(false);
1198 } break;
1199 }
1200 msg = strm.str();
1201}
1202
Karl Schultz7b024b42018-08-30 16:18:18 -06001203// Pull together all the information from the debug record to build the error message strings,
1204// and then assemble them into a single message string.
1205// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
1206// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
1207// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
1208// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
1209//
Tony-LunarG1dce2392019-10-23 16:49:29 -06001210void GpuAssisted::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, VkPipelineBindPoint pipeline_bind_point,
1211 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001212 using namespace spvtools;
1213 const uint32_t total_words = debug_output_buffer[0];
1214 // A zero here means that the shader instrumentation didn't write anything.
1215 // If you have nothing to say, don't say it here.
1216 if (0 == total_words) {
1217 return;
1218 }
1219 // The first word in the debug output buffer is the number of words that would have
1220 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
1221 // The number of words actually written by the shaders is determined by the size of the buffer
1222 // we provide via the descriptor. So, we process only the number of words that can fit in the
1223 // buffer.
1224 // Each "report" written by the shader instrumentation is considered a "record". This function
1225 // is hard-coded to process only one record because it expects the buffer to be large enough to
1226 // hold only one record. If there is a desire to process more than one record, this function needs
1227 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06001228 std::string validation_message;
1229 std::string stage_message;
1230 std::string common_message;
1231 std::string filename_message;
1232 std::string source_message;
1233 std::string vuid_msg;
1234 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
1235 VkPipeline pipeline_handle = VK_NULL_HANDLE;
1236 std::vector<unsigned int> pgm;
1237 // The first record starts at this offset after the total_words.
1238 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
1239 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
1240 // by the instrumented shader.
Tony-LunarG99b880b2019-09-26 11:19:52 -06001241 auto it = shader_map.find(debug_record[kInstCommonOutShaderId]);
1242 if (it != shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001243 shader_module_handle = it->second.shader_module;
1244 pipeline_handle = it->second.pipeline;
1245 pgm = it->second.pgm;
1246 }
1247 GenerateValidationMessage(debug_record, validation_message, vuid_msg);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001248 UtilGenerateStageMessage(debug_record, stage_message);
1249 UtilGenerateCommonMessage(report_data, command_buffer, debug_record, shader_module_handle, pipeline_handle, pipeline_bind_point,
1250 operation_index, common_message);
1251 UtilGenerateSourceMessages(pgm, debug_record, false, filename_message, source_message);
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001252 LogError(queue, vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
1253 filename_message.c_str(), source_message.c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -06001254 // The debug record at word kInstCommonOutSize is the number of words in the record
1255 // written by the shader. Clear the entire record plus the total_words word at the start.
Tony-LunarGab47cac2019-12-20 15:28:01 -07001256 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], (uint32_t)kInstMaxOutCnt);
Karl Schultz7b024b42018-08-30 16:18:18 -06001257 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
1258}
1259
Tony-LunarG81efe392019-03-07 15:43:27 -07001260// 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 -06001261void GpuAssisted::UpdateInstrumentationBuffer(CMD_BUFFER_STATE *cb_node) {
Tony-LunarG1dce2392019-10-23 16:49:29 -06001262 auto gpu_buffer_list = GetBufferInfo(cb_node->commandBuffer);
Tony-LunarG81efe392019-03-07 15:43:27 -07001263 uint32_t *pData;
1264 for (auto &buffer_info : gpu_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001265 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001266 VkResult result = vmaMapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation, (void **)&pData);
Tony-LunarG81efe392019-03-07 15:43:27 -07001267 if (result == VK_SUCCESS) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001268 for (auto update : buffer_info.di_input_mem_block.update_at_submit) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001269 if (update.second->updated) pData[update.first] = 1;
1270 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001271 vmaUnmapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07001272 }
1273 }
1274 }
1275}
1276
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001277void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001278 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1279 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1280 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001281 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07001282 UpdateInstrumentationBuffer(cb_node);
1283 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
1284 UpdateInstrumentationBuffer(secondaryCmdBuffer);
1285 }
1286 }
1287 }
1288}
1289
Karl Schultz58674242019-01-22 15:35:02 -07001290// Issue a memory barrier to make GPU-written data available to host.
1291// Wait for the queue to complete execution.
1292// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001293void GpuAssisted::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
1294 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001295 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001296
Mark Lobodzinski09379db2020-05-07 08:22:01 -06001297 if (aborted || (result != VK_SUCCESS)) return;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001298 bool buffers_present = false;
1299 // Don't QueueWaitIdle if there's nothing to process
1300 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1301 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1302 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
1303 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG1dce2392019-10-23 16:49:29 -06001304 if (GetBufferInfo(cb_node->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd) buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001305 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarG1dce2392019-10-23 16:49:29 -06001306 if (GetBufferInfo(secondaryCmdBuffer->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd)
Jason Macnak83cfd582019-07-31 10:14:24 -07001307 buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001308 }
1309 }
1310 }
1311 if (!buffers_present) return;
Karl Schultz58674242019-01-22 15:35:02 -07001312
Tony-LunarGb5fae462020-03-05 12:43:25 -07001313 UtilSubmitBarrier(queue, this);
Karl Schultz58674242019-01-22 15:35:02 -07001314
Tony-LunarG152a88b2019-03-20 15:42:24 -06001315 DispatchQueueWaitIdle(queue);
Karl Schultz58674242019-01-22 15:35:02 -07001316
Karl Schultz7b024b42018-08-30 16:18:18 -06001317 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1318 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1319 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001320 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001321 UtilProcessInstrumentationBuffer(queue, cb_node, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001322 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06001323 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarGb5fae462020-03-05 12:43:25 -07001324 UtilProcessInstrumentationBuffer(queue, secondaryCmdBuffer, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001325 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06001326 }
1327 }
1328 }
1329}
Tony-LunarGb2501d22019-01-28 09:59:13 -07001330
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001331void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
1332 uint32_t firstVertex, uint32_t firstInstance) {
1333 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1334}
1335
1336void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
1337 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
1338 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1339}
1340
1341void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
1342 uint32_t stride) {
1343 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1344}
1345
1346void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1347 uint32_t count, uint32_t stride) {
1348 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1349}
1350
1351void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
1352 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1353}
1354
1355void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
1356 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1357}
1358
1359void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1360 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1361 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1362 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1363 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1364 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1365 uint32_t width, uint32_t height, uint32_t depth) {
1366 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
1367}
1368
1369void GpuAssisted::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1370 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1371 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1372 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1373 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1374 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1375 uint32_t width, uint32_t height, uint32_t depth) {
1376 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1377 cb_state->hasTraceRaysCmd = true;
1378}
1379
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001380void GpuAssisted::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
1381 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1382 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1383 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1384 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, uint32_t width,
1385 uint32_t height, uint32_t depth) {
1386 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
1387}
1388
1389void GpuAssisted::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
1390 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1391 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1392 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1393 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, uint32_t width,
1394 uint32_t height, uint32_t depth) {
1395 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1396 cb_state->hasTraceRaysCmd = true;
1397}
1398
1399void GpuAssisted::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
1400 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1401 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1402 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1403 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, VkBuffer buffer,
1404 VkDeviceSize offset) {
1405 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
1406}
1407
1408void GpuAssisted::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
1409 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1410 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1411 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1412 const VkStridedBufferRegionKHR *pCallableShaderBindingTable,
1413 VkBuffer buffer, VkDeviceSize offset) {
1414 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1415 cb_state->hasTraceRaysCmd = true;
1416}
1417
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001418void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Jason Macnak67407e72019-07-11 11:05:09 -07001419 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1420 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
andreygca287f22019-04-10 00:15:33 +03001421 return;
1422 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001423 VkResult result;
1424
Tony-LunarG99b880b2019-09-26 11:19:52 -06001425 if (aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001426
1427 std::vector<VkDescriptorSet> desc_sets;
1428 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -06001429 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001430 assert(result == VK_SUCCESS);
1431 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001432 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001433 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001434 return;
1435 }
1436
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001437 VkDescriptorBufferInfo output_desc_buffer_info = {};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001438 output_desc_buffer_info.range = output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001439
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001440 auto cb_node = GetCBState(cmd_buffer);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001441 if (!cb_node) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001442 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001443 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001444 return;
1445 }
1446
Tony-LunarG81efe392019-03-07 15:43:27 -07001447 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001448 GpuAssistedDeviceMemoryBlock output_block = {};
Tony-LunarG0e564722019-03-19 16:09:14 -06001449 VkBufferCreateInfo bufferInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001450 bufferInfo.size = output_buffer_size;
Tony-LunarG0e564722019-03-19 16:09:14 -06001451 bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1452 VmaAllocationCreateInfo allocInfo = {};
1453 allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001454 result = vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001455 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001456 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001457 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001458 return;
1459 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001460
Tony-LunarG81efe392019-03-07 15:43:27 -07001461 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGa77cade2019-03-06 10:49:22 -07001462 uint32_t *pData;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001463 result = vmaMapMemory(vmaAllocator, output_block.allocation, (void **)&pData);
Tony-LunarG0e564722019-03-19 16:09:14 -06001464 if (result == VK_SUCCESS) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001465 memset(pData, 0, output_buffer_size);
1466 vmaUnmapMemory(vmaAllocator, output_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001467 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001468
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001469 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001470 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
1471 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
1472 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001473 uint32_t desc_count = 1;
1474 auto const &state = cb_node->lastBound[bind_point];
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001475 uint32_t number_of_sets = (uint32_t)state.per_set.size();
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001476
Tony-LunarG81efe392019-03-07 15:43:27 -07001477 // Figure out how much memory we need for the input block based on how many sets and bindings there are
1478 // and how big each of the bindings is
Mark Lobodzinskif45e45f2019-04-19 14:15:39 -06001479 if (number_of_sets > 0 && device_extensions.vk_ext_descriptor_indexing) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001480 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
1481 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001482 for (auto s : state.per_set) {
1483 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06001484 if (desc && (desc->GetBindingCount() > 0)) {
1485 auto bindings = desc->GetLayout()->GetSortedBindingSet();
Tony-LunarGa77cade2019-03-06 10:49:22 -07001486 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
1487 for (auto binding : bindings) {
Tony-LunarG7564b382019-08-21 10:11:35 -06001488 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1489 // blocks
1490 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1491 descriptor_count++;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001492 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
1493 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
1494 "validation");
Tony-LunarG7564b382019-08-21 10:11:35 -06001495 } else if (binding == desc->GetLayout()->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001496 descriptor_count += desc->GetVariableDescriptorCount();
1497 } else {
1498 descriptor_count += desc->GetDescriptorCountFromBinding(binding);
1499 }
1500 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001501 }
1502 }
1503
Tony-LunarGa77cade2019-03-06 10:49:22 -07001504 // Note that the size of the input buffer is dependent on the maximum binding number, which
1505 // can be very large. This is because for (set = s, binding = b, index = i), the validation
1506 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
1507 // see if descriptors have been written. In gpu_validation.md, we note this and advise
1508 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
1509 uint32_t words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001510 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
1511 bufferInfo.size = words_needed * 4;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001512 result =
1513 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &di_input_block.buffer, &di_input_block.allocation, nullptr);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001514 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001515 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001516 aborted = true;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001517 return;
1518 }
1519
Tony-LunarGa77cade2019-03-06 10:49:22 -07001520 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
1521 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
1522 // outline of the input buffer format
Tony-LunarG99b880b2019-09-26 11:19:52 -06001523 result = vmaMapMemory(vmaAllocator, di_input_block.allocation, (void **)&pData);
Tony-LunarG76cdcac2019-05-22 16:13:12 -06001524 memset(pData, 0, static_cast<size_t>(bufferInfo.size));
Tony-LunarGa77cade2019-03-06 10:49:22 -07001525 // Pointer to a sets array that points into the sizes array
1526 uint32_t *sets_to_sizes = pData + 1;
1527 // Pointer to the sizes array that contains the array size of the descriptor at each binding
1528 uint32_t *sizes = sets_to_sizes + number_of_sets;
1529 // Pointer to another sets array that points into the bindings array that points into the written array
1530 uint32_t *sets_to_bindings = sizes + binding_count;
1531 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
1532 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
1533 // Index of the next entry in the written array to be updated
1534 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001535 uint32_t bindCounter = number_of_sets + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07001536 // Index of the start of the sets_to_bindings array
1537 pData[0] = number_of_sets + binding_count + 1;
1538
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001539 for (auto s : state.per_set) {
1540 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06001541 if (desc && (desc->GetBindingCount() > 0)) {
1542 auto layout = desc->GetLayout();
1543 auto bindings = layout->GetSortedBindingSet();
Tony-LunarG81efe392019-03-07 15:43:27 -07001544 // For each set, fill in index of its bindings sizes in the sizes array
Tony-LunarGa77cade2019-03-06 10:49:22 -07001545 *sets_to_sizes++ = bindCounter;
Tony-LunarG81efe392019-03-07 15:43:27 -07001546 // For each set, fill in the index of its bindings in the bindings_to_written array
Tony-LunarGa77cade2019-03-06 10:49:22 -07001547 *sets_to_bindings++ = bindCounter + number_of_sets + binding_count;
Tony-LunarG81efe392019-03-07 15:43:27 -07001548 for (auto binding : bindings) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001549 // For each binding, fill in its size in the sizes array
Tony-LunarG7564b382019-08-21 10:11:35 -06001550 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1551 // blocks
1552 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1553 sizes[binding] = 1;
1554 } else if (binding == layout->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001555 sizes[binding] = desc->GetVariableDescriptorCount();
1556 } else {
1557 sizes[binding] = desc->GetDescriptorCountFromBinding(binding);
1558 }
1559 // Fill in the starting index for this binding in the written array in the bindings_to_written array
1560 bindings_to_written[binding] = written_index;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001561
Tony-LunarG7564b382019-08-21 10:11:35 -06001562 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1563 // blocks
1564 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1565 pData[written_index++] = 1;
1566 continue;
1567 }
1568
Tony-LunarGa77cade2019-03-06 10:49:22 -07001569 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
1570 // For each array element in the binding, update the written array with whether it has been written
1571 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
1572 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
Tony-LunarG81efe392019-03-07 15:43:27 -07001573 if (descriptor->updated) {
1574 pData[written_index] = 1;
1575 } else if (desc->IsUpdateAfterBind(binding)) {
1576 // If it hasn't been written now and it's update after bind, put it in a list to check at QueueSubmit
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001577 di_input_block.update_at_submit[written_index] = descriptor;
Tony-LunarG81efe392019-03-07 15:43:27 -07001578 }
Tony-LunarGa77cade2019-03-06 10:49:22 -07001579 written_index++;
1580 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001581 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001582 auto last = desc->GetLayout()->GetMaxBinding();
1583 bindings_to_written += last + 1;
1584 bindCounter += last + 1;
1585 sizes += last + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07001586 } else {
1587 *sets_to_sizes++ = 0;
1588 *sets_to_bindings++ = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001589 }
1590 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001591 vmaUnmapMemory(vmaAllocator, di_input_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001592
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001593 di_input_desc_buffer_info.range = (words_needed * 4);
1594 di_input_desc_buffer_info.buffer = di_input_block.buffer;
1595 di_input_desc_buffer_info.offset = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001596
1597 desc_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1598 desc_writes[1].dstBinding = 1;
1599 desc_writes[1].descriptorCount = 1;
1600 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001601 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001602 desc_writes[1].dstSet = desc_sets[0];
1603
1604 desc_count = 2;
Tony-LunarG0e564722019-03-19 16:09:14 -06001605 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001606
Tony-LunarG7e0842f2019-12-10 09:26:34 -07001607 if (number_of_sets > 0 && (device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) &&
1608 buffer_map.size() && shaderInt64) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001609 // Example BDA input buffer assuming 2 buffers using BDA:
1610 // Word 0 | Index of start of buffer sizes (in this case 5)
1611 // Word 1 | 0x0000000000000000
1612 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
1613 // Word 3 | Device Address of second buffer
1614 // Word 4 | 0xffffffffffffffff
1615 // Word 5 | 0 (size of pretend buffer at word 1)
1616 // Word 6 | Size in bytes of first buffer
1617 // Word 7 | Size in bytes of second buffer
1618 // Word 8 | 0 (size of pretend buffer in word 4)
1619
Tony-LunarG99b880b2019-09-26 11:19:52 -06001620 uint32_t num_buffers = static_cast<uint32_t>(buffer_map.size());
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001621 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
1622 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
1623 bufferInfo.size = words_needed * 8; // 64 bit words
Tony-LunarG99b880b2019-09-26 11:19:52 -06001624 result =
1625 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &bda_input_block.buffer, &bda_input_block.allocation, nullptr);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001626 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001627 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001628 aborted = true;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001629 return;
1630 }
1631 uint64_t *bda_data;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001632 result = vmaMapMemory(vmaAllocator, bda_input_block.allocation, (void **)&bda_data);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001633 uint32_t address_index = 1;
1634 uint32_t size_index = 3 + num_buffers;
1635 memset(bda_data, 0, static_cast<size_t>(bufferInfo.size));
1636 bda_data[0] = size_index; // Start of buffer sizes
1637 bda_data[address_index++] = 0; // NULL address
1638 bda_data[size_index++] = 0;
1639
Tony-LunarG99b880b2019-09-26 11:19:52 -06001640 for (auto const &value : buffer_map) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001641 bda_data[address_index++] = value.first;
1642 bda_data[size_index++] = value.second;
1643 }
1644 bda_data[address_index] = UINTPTR_MAX;
1645 bda_data[size_index] = 0;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001646 vmaUnmapMemory(vmaAllocator, bda_input_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001647
1648 bda_input_desc_buffer_info.range = (words_needed * 8);
1649 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
1650 bda_input_desc_buffer_info.offset = 0;
1651
1652 desc_writes[desc_count].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1653 desc_writes[desc_count].dstBinding = 2;
1654 desc_writes[desc_count].descriptorCount = 1;
1655 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1656 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
1657 desc_writes[desc_count].dstSet = desc_sets[0];
1658 desc_count++;
1659 }
1660
Tony-LunarGb2501d22019-01-28 09:59:13 -07001661 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001662 output_desc_buffer_info.buffer = output_block.buffer;
1663 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001664
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001665 desc_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1666 desc_writes[0].descriptorCount = 1;
1667 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1668 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
1669 desc_writes[0].dstSet = desc_sets[0];
1670 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001671
andreyg25ce2622019-04-05 23:07:59 +03001672 auto iter = cb_node->lastBound.find(bind_point); // find() allows read-only access to cb_state
Tony-LunarGb2501d22019-01-28 09:59:13 -07001673 if (iter != cb_node->lastBound.end()) {
1674 auto pipeline_state = iter->second.pipeline_state;
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001675 if (pipeline_state && (pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index)) {
1676 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout, desc_set_bind_index, 1,
Tony-LunarG99b880b2019-09-26 11:19:52 -06001677 desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001678 }
Tony-LunarG0e564722019-03-19 16:09:14 -06001679 // Record buffer and memory info in CB state tracking
Tony-LunarG1dce2392019-10-23 16:49:29 -06001680 GetBufferInfo(cmd_buffer).emplace_back(output_block, di_input_block, bda_input_block, desc_sets[0], desc_pool, bind_point);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001681 } else {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001682 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001683 vmaDestroyBuffer(vmaAllocator, di_input_block.buffer, di_input_block.allocation);
1684 vmaDestroyBuffer(vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
1685 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
1686 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001687 return;
1688 }
1689}