blob: ab539c3ef24ca5ab93ef4d3cc8f80e8968d3030b [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-LunarG8eb5a002019-07-25 16:49:00 -0600277}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600278
Karl Schultz7b024b42018-08-30 16:18:18 -0600279// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600280void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600281 DestroyAccelerationStructureBuildValidationState();
Tony-LunarGb5fae462020-03-05 12:43:25 -0700282 UtilPreCallRecordDestroyDevice(this);
Karl Schultz7b024b42018-08-30 16:18:18 -0600283}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600284
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600285void GpuAssisted::CreateAccelerationStructureBuildValidationState(GpuAssisted *device_gpuav) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600286 if (device_gpuav->aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700287 return;
288 }
289
Tony-LunarG99b880b2019-09-26 11:19:52 -0600290 auto &as_validation_state = device_gpuav->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700291 if (as_validation_state.initialized) {
292 return;
293 }
294
295 if (!device_extensions.vk_nv_ray_tracing) {
296 return;
297 }
298
299 // Outline:
300 // - Create valid bottom level acceleration structure which acts as replacement
301 // - Create and load vertex buffer
302 // - Create and load index buffer
303 // - Create, allocate memory for, and bind memory for acceleration structure
304 // - Query acceleration structure handle
305 // - Create command pool and command buffer
306 // - Record build acceleration structure command
307 // - Submit command buffer and wait for completion
308 // - Cleanup
309 // - Create compute pipeline for validating instance buffers
310 // - Create descriptor set layout
311 // - Create pipeline layout
312 // - Create pipeline
313 // - Cleanup
314
315 VkResult result = VK_SUCCESS;
316
317 VkBuffer vbo = VK_NULL_HANDLE;
318 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
319 if (result == VK_SUCCESS) {
320 VkBufferCreateInfo vbo_ci = {};
321 vbo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
322 vbo_ci.size = sizeof(float) * 9;
323 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
324
325 VmaAllocationCreateInfo vbo_ai = {};
326 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
327 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
328
Tony-LunarG99b880b2019-09-26 11:19:52 -0600329 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700330 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700331 ReportSetupProblem(device, "Failed to create vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700332 }
333 }
334
335 if (result == VK_SUCCESS) {
336 uint8_t *mapped_vbo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600337 result = vmaMapMemory(device_gpuav->vmaAllocator, vbo_allocation, (void **)&mapped_vbo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700338 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700339 ReportSetupProblem(device, "Failed to map vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700340 } else {
341 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
342 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600343 vmaUnmapMemory(device_gpuav->vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700344 }
345 }
346
347 VkBuffer ibo = VK_NULL_HANDLE;
348 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
349 if (result == VK_SUCCESS) {
350 VkBufferCreateInfo ibo_ci = {};
351 ibo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
352 ibo_ci.size = sizeof(uint32_t) * 3;
353 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
354
355 VmaAllocationCreateInfo ibo_ai = {};
356 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
357 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
358
Tony-LunarG99b880b2019-09-26 11:19:52 -0600359 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700360 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700361 ReportSetupProblem(device, "Failed to create index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700362 }
363 }
364
365 if (result == VK_SUCCESS) {
366 uint8_t *mapped_ibo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600367 result = vmaMapMemory(device_gpuav->vmaAllocator, ibo_allocation, (void **)&mapped_ibo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700368 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700369 ReportSetupProblem(device, "Failed to map index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700370 } else {
371 const std::vector<uint32_t> indicies = {0, 1, 2};
372 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600373 vmaUnmapMemory(device_gpuav->vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700374 }
375 }
376
377 VkGeometryNV geometry = {};
378 geometry.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
379 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
380 geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
381 geometry.geometry.triangles.vertexData = vbo;
382 geometry.geometry.triangles.vertexOffset = 0;
383 geometry.geometry.triangles.vertexCount = 3;
384 geometry.geometry.triangles.vertexStride = 12;
385 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
386 geometry.geometry.triangles.indexData = ibo;
387 geometry.geometry.triangles.indexOffset = 0;
388 geometry.geometry.triangles.indexCount = 3;
389 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
390 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
391 geometry.geometry.triangles.transformOffset = 0;
392 geometry.geometry.aabbs = {};
393 geometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
394
395 VkAccelerationStructureCreateInfoNV as_ci = {};
396 as_ci.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
397 as_ci.info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
398 as_ci.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV;
399 as_ci.info.instanceCount = 0;
400 as_ci.info.geometryCount = 1;
401 as_ci.info.pGeometries = &geometry;
402 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600403 result = DispatchCreateAccelerationStructureNV(device_gpuav->device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700404 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700405 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700406 "Failed to create acceleration structure for acceleration structure build validation.");
407 }
408 }
409
410 VkMemoryRequirements2 as_mem_requirements = {};
411 if (result == VK_SUCCESS) {
412 VkAccelerationStructureMemoryRequirementsInfoNV as_mem_requirements_info = {};
413 as_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
414 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
415 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
416
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600417 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700418 }
419
420 VmaAllocationInfo as_memory_ai = {};
421 if (result == VK_SUCCESS) {
422 VmaAllocationCreateInfo as_memory_aci = {};
423 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
424
Tony-LunarG99b880b2019-09-26 11:19:52 -0600425 result = vmaAllocateMemory(device_gpuav->vmaAllocator, &as_mem_requirements.memoryRequirements, &as_memory_aci,
426 &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700427 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700428 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700429 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
430 }
431 }
432
433 if (result == VK_SUCCESS) {
434 VkBindAccelerationStructureMemoryInfoNV as_bind_info = {};
435 as_bind_info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
436 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
437 as_bind_info.memory = as_memory_ai.deviceMemory;
438 as_bind_info.memoryOffset = as_memory_ai.offset;
439
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600440 result = DispatchBindAccelerationStructureMemoryNV(device_gpuav->device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700441 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700442 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700443 "Failed to bind acceleration structure memory for acceleration structure build validation.");
444 }
445 }
446
447 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600448 result = DispatchGetAccelerationStructureHandleNV(device_gpuav->device, as_validation_state.replacement_as,
449 sizeof(uint64_t), &as_validation_state.replacement_as_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700450 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700451 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700452 "Failed to get acceleration structure handle for acceleration structure build validation.");
453 }
454 }
455
456 VkMemoryRequirements2 scratch_mem_requirements = {};
457 if (result == VK_SUCCESS) {
458 VkAccelerationStructureMemoryRequirementsInfoNV scratch_mem_requirements_info = {};
459 scratch_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
460 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
461 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
462
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600463 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &scratch_mem_requirements_info,
464 &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700465 }
466
467 VkBuffer scratch = VK_NULL_HANDLE;
Tony-LunarG18900282020-05-20 12:34:33 -0600468 VmaAllocation scratch_allocation = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700469 if (result == VK_SUCCESS) {
470 VkBufferCreateInfo scratch_ci = {};
471 scratch_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
472 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
473 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
Jason Macnak83cfd582019-07-31 10:14:24 -0700474 VmaAllocationCreateInfo scratch_aci = {};
475 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
476
Tony-LunarG18900282020-05-20 12:34:33 -0600477 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &scratch_ci, &scratch_aci, &scratch, &scratch_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700478 if (result != VK_SUCCESS) {
Tony-LunarG18900282020-05-20 12:34:33 -0600479 ReportSetupProblem(device_gpuav->device,
480 "Failed to create scratch buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700481 }
482 }
483
484 VkCommandPool command_pool = VK_NULL_HANDLE;
485 if (result == VK_SUCCESS) {
486 VkCommandPoolCreateInfo command_pool_ci = {};
487 command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
488 command_pool_ci.queueFamilyIndex = 0;
489
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600490 result = DispatchCreateCommandPool(device_gpuav->device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700491 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700492 ReportSetupProblem(device_gpuav->device, "Failed to create command pool for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700493 }
494 }
495
496 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
497
498 if (result == VK_SUCCESS) {
499 VkCommandBufferAllocateInfo command_buffer_ai = {};
500 command_buffer_ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
501 command_buffer_ai.commandPool = command_pool;
502 command_buffer_ai.commandBufferCount = 1;
503 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
504
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600505 result = DispatchAllocateCommandBuffers(device_gpuav->device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700506 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700507 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700508 "Failed to create command buffer for acceleration structure build validation.");
509 }
510
511 // Hook up command buffer dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600512 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700513 }
514
515 if (result == VK_SUCCESS) {
516 VkCommandBufferBeginInfo command_buffer_bi = {};
517 command_buffer_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
518
519 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
520 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700521 ReportSetupProblem(device_gpuav->device, "Failed to begin command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700522 }
523 }
524
525 if (result == VK_SUCCESS) {
526 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
527 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
528 DispatchEndCommandBuffer(command_buffer);
529 }
530
531 VkQueue queue = VK_NULL_HANDLE;
532 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600533 DispatchGetDeviceQueue(device_gpuav->device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700534
535 // Hook up queue dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600536 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700537
538 VkSubmitInfo submit_info = {};
539 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
540 submit_info.commandBufferCount = 1;
541 submit_info.pCommandBuffers = &command_buffer;
542 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
543 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700544 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700545 "Failed to submit command buffer for acceleration structure build validation.");
546 }
547 }
548
549 if (result == VK_SUCCESS) {
550 result = DispatchQueueWaitIdle(queue);
551 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700552 ReportSetupProblem(device_gpuav->device, "Failed to wait for queue idle for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700553 }
554 }
555
556 if (vbo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600557 vmaDestroyBuffer(device_gpuav->vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700558 }
559 if (ibo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600560 vmaDestroyBuffer(device_gpuav->vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700561 }
562 if (scratch != VK_NULL_HANDLE) {
Tony-LunarG18900282020-05-20 12:34:33 -0600563 vmaDestroyBuffer(device_gpuav->vmaAllocator, scratch, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700564 }
565 if (command_pool != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600566 DispatchDestroyCommandPool(device_gpuav->device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700567 }
568
Tony-LunarG99b880b2019-09-26 11:19:52 -0600569 if (device_gpuav->debug_desc_layout == VK_NULL_HANDLE) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700570 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700571 "Failed to find descriptor set layout for acceleration structure build validation.");
572 result = VK_INCOMPLETE;
573 }
574
575 if (result == VK_SUCCESS) {
576 VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
577 pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
578 pipeline_layout_ci.setLayoutCount = 1;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600579 pipeline_layout_ci.pSetLayouts = &device_gpuav->debug_desc_layout;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600580 result = DispatchCreatePipelineLayout(device_gpuav->device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700581 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700582 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700583 "Failed to create pipeline layout for acceleration structure build validation.");
584 }
585 }
586
587 VkShaderModule shader_module = VK_NULL_HANDLE;
588 if (result == VK_SUCCESS) {
589 VkShaderModuleCreateInfo shader_module_ci = {};
590 shader_module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
591 shader_module_ci.codeSize = sizeof(kComputeShaderSpirv);
592 shader_module_ci.pCode = (uint32_t *)kComputeShaderSpirv;
593
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600594 result = DispatchCreateShaderModule(device_gpuav->device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700595 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700596 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700597 "Failed to create compute shader module for acceleration structure build validation.");
598 }
599 }
600
601 if (result == VK_SUCCESS) {
602 VkPipelineShaderStageCreateInfo pipeline_stage_ci = {};
603 pipeline_stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
604 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
605 pipeline_stage_ci.module = shader_module;
606 pipeline_stage_ci.pName = "main";
607
608 VkComputePipelineCreateInfo pipeline_ci = {};
609 pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
610 pipeline_ci.stage = pipeline_stage_ci;
611 pipeline_ci.layout = as_validation_state.pipeline_layout;
612
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600613 result = DispatchCreateComputePipelines(device_gpuav->device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr,
614 &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700615 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700616 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700617 "Failed to create compute pipeline for acceleration structure build validation.");
618 }
619 }
620
621 if (shader_module != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600622 DispatchDestroyShaderModule(device_gpuav->device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700623 }
624
625 if (result == VK_SUCCESS) {
626 as_validation_state.initialized = true;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700627 LogInfo(device_gpuav->device, "UNASSIGNED-GPU-Assisted Validation.",
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600628 "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700629 } else {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600630 device_gpuav->aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700631 }
632}
633
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600634void GpuAssisted::DestroyAccelerationStructureBuildValidationState() {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600635 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700636 if (as_validation_state.pipeline != VK_NULL_HANDLE) {
637 DispatchDestroyPipeline(device, as_validation_state.pipeline, nullptr);
638 }
639 if (as_validation_state.pipeline_layout != VK_NULL_HANDLE) {
640 DispatchDestroyPipelineLayout(device, as_validation_state.pipeline_layout, nullptr);
641 }
642 if (as_validation_state.replacement_as != VK_NULL_HANDLE) {
643 DispatchDestroyAccelerationStructureNV(device, as_validation_state.replacement_as, nullptr);
644 }
645 if (as_validation_state.replacement_as_allocation != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600646 vmaFreeMemory(vmaAllocator, as_validation_state.replacement_as_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700647 }
648}
649
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600650struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700651 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
652 VkPipeline pipeline = VK_NULL_HANDLE;
653 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
654 std::vector<VkDescriptorSet> descriptor_sets;
655 std::vector<std::vector<uint32_t>> dynamic_offsets;
656 uint32_t push_descriptor_set_index = 0;
657 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
658 std::vector<uint8_t> push_constants_data;
659 PushConstantRangesId push_constants_ranges;
660
661 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
662 pipeline_bind_point = bind_point;
663
664 LAST_BOUND_STATE &last_bound = cb_state->lastBound[bind_point];
665 if (last_bound.pipeline_state) {
666 pipeline = last_bound.pipeline_state->pipeline;
667 pipeline_layout = last_bound.pipeline_layout;
668 descriptor_sets.reserve(last_bound.per_set.size());
669 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
670 const auto *bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
671
672 descriptor_sets.push_back(bound_descriptor_set->GetSet());
673 if (bound_descriptor_set->IsPushDescriptor()) {
674 push_descriptor_set_index = static_cast<uint32_t>(i);
675 }
676 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
677 }
678
679 if (last_bound.push_descriptor_set) {
680 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
681 }
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500682 if (last_bound.pipeline_state->pipeline_layout->push_constant_ranges == cb_state->push_constant_data_ranges) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700683 push_constants_data = cb_state->push_constant_data;
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500684 push_constants_ranges = last_bound.pipeline_state->pipeline_layout->push_constant_ranges;
Jason Macnak83cfd582019-07-31 10:14:24 -0700685 }
686 }
687 }
688
689 void Restore(VkCommandBuffer command_buffer) const {
690 if (pipeline != VK_NULL_HANDLE) {
691 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
692 if (!descriptor_sets.empty()) {
693 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
694 VkDescriptorSet descriptor_set = descriptor_sets[i];
695 if (descriptor_set != VK_NULL_HANDLE) {
696 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
697 static_cast<uint32_t>(i), 1, &descriptor_set,
698 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
699 }
700 }
701 }
702 if (!push_descriptor_set_writes.empty()) {
703 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
704 static_cast<uint32_t>(push_descriptor_set_writes.size()),
705 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
706 }
707 for (const auto &push_constant_range : *push_constants_ranges) {
708 if (push_constant_range.size == 0) continue;
709 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
710 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
711 }
712 }
713 }
714};
715
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600716void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
717 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
718 VkDeviceSize instanceOffset, VkBool32 update,
719 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
720 VkBuffer scratch, VkDeviceSize scratchOffset) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700721 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
722 return;
723 }
724
Tony-LunarG99b880b2019-09-26 11:19:52 -0600725 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700726 if (!as_validation_state.initialized) {
727 return;
728 }
729
730 // Empty acceleration structure is valid according to the spec.
731 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
732 return;
733 }
734
735 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
736 assert(cb_state != nullptr);
737
738 std::vector<uint64_t> current_valid_handles;
739 for (const auto &as_state_kv : accelerationStructureMap) {
740 const ACCELERATION_STRUCTURE_STATE &as_state = *as_state_kv.second;
Jeff Bolz95176d02020-04-01 00:36:16 -0500741 if (as_state.built && as_state.create_infoNV.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700742 current_valid_handles.push_back(as_state.opaque_handle);
743 }
744 }
745
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600746 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700747 as_validation_buffer_info.acceleration_structure = dst;
748
749 const VkDeviceSize validation_buffer_size =
750 // One uint for number of instances to validate
751 4 +
752 // Two uint for the replacement acceleration structure handle
753 8 +
754 // One uint for number of invalid handles found
755 4 +
756 // Two uint for the first invalid handle found
757 8 +
758 // One uint for the number of current valid handles
759 4 +
760 // Two uint for each current valid handle
761 (8 * current_valid_handles.size());
762
763 VkBufferCreateInfo validation_buffer_create_info = {};
764 validation_buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
765 validation_buffer_create_info.size = validation_buffer_size;
766 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
767
768 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
769 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
770
Tony-LunarG99b880b2019-09-26 11:19:52 -0600771 VkResult result = vmaCreateBuffer(vmaAllocator, &validation_buffer_create_info, &validation_buffer_alloc_info,
772 &as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -0700773 &as_validation_buffer_info.validation_buffer_allocation, nullptr);
774 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700775 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600776 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700777 return;
778 }
779
780 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600781 result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700782 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700783 ReportSetupProblem(device, "Unable to allocate device memory for acceleration structure build val buffer.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600784 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700785 return;
786 }
787
788 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
789 mapped_validation_buffer->replacement_handle_bits_0 =
790 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
791 mapped_validation_buffer->replacement_handle_bits_1 =
792 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
793 mapped_validation_buffer->invalid_handle_found = 0;
794 mapped_validation_buffer->invalid_handle_bits_0 = 0;
795 mapped_validation_buffer->invalid_handle_bits_1 = 0;
796 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
797
798 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
799 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
800 const uint64_t current_valid_handle = current_valid_handles[i];
801
802 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
803 ++mapped_valid_handles;
804 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
805 ++mapped_valid_handles;
806 }
807
Tony-LunarG99b880b2019-09-26 11:19:52 -0600808 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700809
810 static constexpr const VkDeviceSize kInstanceSize = 64;
811 const VkDeviceSize instance_buffer_size = kInstanceSize * pInfo->instanceCount;
812
Tony-LunarG1dce2392019-10-23 16:49:29 -0600813 result = desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool, debug_desc_layout,
814 &as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700815 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700816 ReportSetupProblem(device, "Unable to get descriptor set for acceleration structure build.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600817 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700818 return;
819 }
820
821 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
822 descriptor_buffer_infos[0].buffer = instanceData;
823 descriptor_buffer_infos[0].offset = instanceOffset;
824 descriptor_buffer_infos[0].range = instance_buffer_size;
825 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.validation_buffer;
826 descriptor_buffer_infos[1].offset = 0;
827 descriptor_buffer_infos[1].range = validation_buffer_size;
828
829 VkWriteDescriptorSet descriptor_set_writes[2] = {};
830 descriptor_set_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
831 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
832 descriptor_set_writes[0].dstBinding = 0;
833 descriptor_set_writes[0].descriptorCount = 1;
834 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
835 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
836 descriptor_set_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
837 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
838 descriptor_set_writes[1].dstBinding = 1;
839 descriptor_set_writes[1].descriptorCount = 1;
840 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
841 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
842
843 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
844
845 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
846 VkMemoryBarrier memory_barrier = {};
847 memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
848 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
849 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
850 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
851 &memory_barrier, 0, nullptr, 0, nullptr);
852
853 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600854 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700855 restorable_state.Create(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
856
857 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
858 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
859 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
860 &as_validation_buffer_info.descriptor_set, 0, nullptr);
861 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
862
863 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
864 // have been replaced by the validation compute shader before any builds take place.
865 VkBufferMemoryBarrier instance_buffer_barrier = {};
866 instance_buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
867 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
868 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
869 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
870 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
871 instance_buffer_barrier.buffer = instanceData;
872 instance_buffer_barrier.offset = instanceOffset;
873 instance_buffer_barrier.size = instance_buffer_size;
874 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
875 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
876 nullptr);
877
878 // Restore the previous compute pipeline state.
879 restorable_state.Restore(commandBuffer);
880
881 as_validation_state.validation_buffers[commandBuffer].push_back(std::move(as_validation_buffer_info));
882}
883
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600884void GpuAssisted::ProcessAccelerationStructureBuildValidationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700885 if (cb_node == nullptr || !cb_node->hasBuildAccelerationStructureCmd) {
886 return;
887 }
888
Tony-LunarG99b880b2019-09-26 11:19:52 -0600889 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700890 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[cb_node->commandBuffer];
891 for (const auto &as_validation_buffer_info : as_validation_buffer_infos) {
892 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
893
Tony-LunarG99b880b2019-09-26 11:19:52 -0600894 VkResult result =
895 vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700896 if (result == VK_SUCCESS) {
897 if (mapped_validation_buffer->invalid_handle_found > 0) {
898 uint64_t invalid_handle = 0;
899 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
900 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
901
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700902 LogError(as_validation_buffer_info.acceleration_structure, "UNASSIGNED-AccelerationStructure",
903 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
904 "handle (%" PRIu64 ")",
905 invalid_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700906 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600907 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700908 }
909 }
910}
911
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600912void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
913 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
914 VkResult result) {
915 if (VK_SUCCESS != result) return;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600916 ValidationStateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600917 for (uint32_t i = 0; i < bindInfoCount; i++) {
918 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
919 ACCELERATION_STRUCTURE_STATE *as_state = GetAccelerationStructureState(info.accelerationStructure);
920 if (as_state) {
921 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
922 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600923 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600924}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700925
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600926// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
927void GpuAssisted::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
928 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
929 void *cpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600930 if (aborted) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600931 return;
932 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600933
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600934 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
935
Tony-LunarG99b880b2019-09-26 11:19:52 -0600936 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600937 std::ostringstream strm;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600938 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Karl Schultz7b024b42018-08-30 16:18:18 -0600939 << "Application has too many descriptor sets in the pipeline layout to continue with gpu validation. "
940 << "Validation is not modifying the pipeline layout. "
941 << "Instrumented shaders are replaced with non-instrumented shaders.";
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700942 ReportSetupProblem(device, strm.str().c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -0600943 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700944 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Karl Schultz7b024b42018-08-30 16:18:18 -0600945 }
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700946}
947
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600948void GpuAssisted::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
949 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
950 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600951 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
952
Karl Schultz7b024b42018-08-30 16:18:18 -0600953 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700954 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600955 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600956 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600957}
958
Karl Schultz7b024b42018-08-30 16:18:18 -0600959// Free the device memory and descriptor set associated with a command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600960void GpuAssisted::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600961 if (aborted) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600962 return;
963 }
Tony-LunarG1dce2392019-10-23 16:49:29 -0600964 auto gpuav_buffer_list = GetBufferInfo(commandBuffer);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600965 for (auto buffer_info : gpuav_buffer_list) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600966 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600967 if (buffer_info.di_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600968 vmaDestroyBuffer(vmaAllocator, buffer_info.di_input_mem_block.buffer, buffer_info.di_input_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600969 }
970 if (buffer_info.bda_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600971 vmaDestroyBuffer(vmaAllocator, buffer_info.bda_input_mem_block.buffer, buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -0600972 }
Tony-LunarGdcbc2c32019-05-06 10:17:44 -0600973 if (buffer_info.desc_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600974 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Tony-LunarGdcbc2c32019-05-06 10:17:44 -0600975 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600976 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600977 command_buffer_map.erase(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700978
Tony-LunarG99b880b2019-09-26 11:19:52 -0600979 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700980 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[commandBuffer];
981 for (auto &as_validation_buffer_info : as_validation_buffer_infos) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600982 vmaDestroyBuffer(vmaAllocator, as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -0700983 as_validation_buffer_info.validation_buffer_allocation);
984
985 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600986 desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool,
987 as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700988 }
989 }
990 as_validation_info.validation_buffers.erase(commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -0600991}
Karl Schultz7b024b42018-08-30 16:18:18 -0600992// Just gives a warning about a possible deadlock.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600993bool GpuAssisted::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
994 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
995 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
996 uint32_t bufferMemoryBarrierCount,
997 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
Jeff Bolz5c801d12019-10-09 10:38:45 -0500998 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600999 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001000 ReportSetupProblem(commandBuffer,
Karl Schultz7b024b42018-08-30 16:18:18 -06001001 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1002 "GPU_Assisted validation waits on queue completion. "
1003 "This wait could block the host's signaling of this event, resulting in deadlock.");
1004 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001005 return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001006}
1007
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001008void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1009 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
1010 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
1011 if (enabled.gpu_validation_reserve_binding_slot && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
1012 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
1013 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
1014 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001015 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1016 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001017 }
1018 }
1019}
1020
1021void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1022 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
1023 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
1024 if (enabled.gpu_validation_reserve_binding_slot && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
1025 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
1026 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
1027 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001028 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1029 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001030 }
1031 }
1032}
1033
1034void GpuAssisted::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1035 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1036 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1037 void *cgpl_state_data) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001038 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001039 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001040 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
1041 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001042 cgpl_state->gpu_create_infos = new_pipeline_create_infos;
1043 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001044}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001045
1046void GpuAssisted::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1047 const VkComputePipelineCreateInfo *pCreateInfos,
1048 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1049 void *ccpl_state_data) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001050 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001051 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001052 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
1053 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001054 ccpl_state->gpu_create_infos = new_pipeline_create_infos;
1055 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
Jason Macnak67407e72019-07-11 11:05:09 -07001056}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001057
1058void GpuAssisted::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1059 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1060 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1061 void *crtpl_state_data) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001062 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001063 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001064 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1065 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001066 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1067 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001068}
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001069
1070void GpuAssisted::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1071 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1072 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1073 void *crtpl_state_data) {
1074 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
1075 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001076 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1077 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001078 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1079 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->gpu_create_infos.data());
1080}
Karl Schultz7b024b42018-08-30 16:18:18 -06001081
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001082void GpuAssisted::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1083 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1084 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1085 VkResult result, void *cgpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001086 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
1087 pPipelines, result, cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001088 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001089}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001090
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001091void GpuAssisted::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1092 const VkComputePipelineCreateInfo *pCreateInfos,
1093 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1094 VkResult result, void *ccpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001095 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1096 result, ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001097 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001098}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001099
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001100void GpuAssisted::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1101 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1102 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1103 VkResult result, void *crtpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001104 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
1105 pPipelines, result, crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001106 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Jason Macnak67407e72019-07-11 11:05:09 -07001107}
1108
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001109void GpuAssisted::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1110 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1111 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1112 VkResult result, void *crtpl_state_data) {
1113 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesKHR(device, pipelineCache, count, pCreateInfos, pAllocator,
1114 pPipelines, result, crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001115 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Karl Schultz7b024b42018-08-30 16:18:18 -06001116}
1117
1118// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001119void GpuAssisted::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001120 for (auto it = shader_map.begin(); it != shader_map.end();) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001121 if (it->second.pipeline == pipeline) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001122 it = shader_map.erase(it);
Karl Schultz7b024b42018-08-30 16:18:18 -06001123 } else {
1124 ++it;
1125 }
1126 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001127 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001128}
1129
1130// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001131bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
1132 uint32_t *unique_shader_id) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001133 if (aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001134 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
1135
1136 // Load original shader SPIR-V
1137 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
1138 new_pgm.clear();
1139 new_pgm.reserve(num_words);
1140 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
1141
1142 // Call the optimizer to instrument the shader.
1143 // 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 -07001144 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Tony-LunarG2ec96bb2019-11-26 13:43:02 -07001145 const bool descriptor_indexing = IsExtEnabled(device_extensions.vk_ext_descriptor_indexing);
Karl Schultz7b024b42018-08-30 16:18:18 -06001146 using namespace spvtools;
1147 spv_target_env target_env = SPV_ENV_VULKAN_1_1;
1148 Optimizer optimizer(target_env);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001149 optimizer.RegisterPass(
Tony-LunarGab47cac2019-12-20 15:28:01 -07001150 CreateInstBindlessCheckPass(desc_set_bind_index, unique_shader_module_id, descriptor_indexing, descriptor_indexing));
Karl Schultz7b024b42018-08-30 16:18:18 -06001151 optimizer.RegisterPass(CreateAggressiveDCEPass());
Tony-LunarG7e0842f2019-12-10 09:26:34 -07001152 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) && shaderInt64)
Tony-LunarG99b880b2019-09-26 11:19:52 -06001153 optimizer.RegisterPass(CreateInstBuffAddrCheckPass(desc_set_bind_index, unique_shader_module_id));
Karl Schultz7b024b42018-08-30 16:18:18 -06001154 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm);
1155 if (!pass) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001156 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Karl Schultz7b024b42018-08-30 16:18:18 -06001157 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001158 *unique_shader_id = unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -06001159 return pass;
1160}
Mark Lobodzinski01734072019-02-13 17:39:15 -07001161// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001162void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
1163 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
1164 void *csm_state_data) {
1165 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
1166 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -06001167 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001168 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
1169 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
Karl Schultz7b024b42018-08-30 16:18:18 -06001170 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001171}
1172
Karl Schultz7b024b42018-08-30 16:18:18 -06001173// Generate the part of the message describing the violation.
1174static void GenerateValidationMessage(const uint32_t *debug_record, std::string &msg, std::string &vuid_msg) {
1175 using namespace spvtools;
1176 std::ostringstream strm;
Tony-LunarGab47cac2019-12-20 15:28:01 -07001177 switch (debug_record[kInstValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001178 case kInstErrorBindlessBounds: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001179 strm << "Index of " << debug_record[kInstBindlessBoundsOutDescIndex] << " used to index descriptor array of length "
1180 << debug_record[kInstBindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001181 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -06001182 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001183 case kInstErrorBindlessUninit: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001184 strm << "Descriptor index " << debug_record[kInstBindlessUninitOutDescIndex] << " is uninitialized. ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001185 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -06001186 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001187 case kInstErrorBuffAddrUnallocRef: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001188 uint64_t *ptr = (uint64_t *)&debug_record[kInstBuffAddrUnallocOutDescPtrLo];
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001189 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
1190 vuid_msg = "UNASSIGNED-Device address out of bounds";
1191 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001192 default: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001193 strm << "Internal Error (unexpected error type = " << debug_record[kInstValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001194 vuid_msg = "UNASSIGNED-Internal Error";
1195 assert(false);
1196 } break;
1197 }
1198 msg = strm.str();
1199}
1200
Karl Schultz7b024b42018-08-30 16:18:18 -06001201// Pull together all the information from the debug record to build the error message strings,
1202// and then assemble them into a single message string.
1203// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
1204// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
1205// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
1206// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
1207//
Tony-LunarG1dce2392019-10-23 16:49:29 -06001208void GpuAssisted::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, VkPipelineBindPoint pipeline_bind_point,
1209 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001210 using namespace spvtools;
1211 const uint32_t total_words = debug_output_buffer[0];
1212 // A zero here means that the shader instrumentation didn't write anything.
1213 // If you have nothing to say, don't say it here.
1214 if (0 == total_words) {
1215 return;
1216 }
1217 // The first word in the debug output buffer is the number of words that would have
1218 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
1219 // The number of words actually written by the shaders is determined by the size of the buffer
1220 // we provide via the descriptor. So, we process only the number of words that can fit in the
1221 // buffer.
1222 // Each "report" written by the shader instrumentation is considered a "record". This function
1223 // is hard-coded to process only one record because it expects the buffer to be large enough to
1224 // hold only one record. If there is a desire to process more than one record, this function needs
1225 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06001226 std::string validation_message;
1227 std::string stage_message;
1228 std::string common_message;
1229 std::string filename_message;
1230 std::string source_message;
1231 std::string vuid_msg;
1232 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
1233 VkPipeline pipeline_handle = VK_NULL_HANDLE;
1234 std::vector<unsigned int> pgm;
1235 // The first record starts at this offset after the total_words.
1236 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
1237 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
1238 // by the instrumented shader.
Tony-LunarG99b880b2019-09-26 11:19:52 -06001239 auto it = shader_map.find(debug_record[kInstCommonOutShaderId]);
1240 if (it != shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001241 shader_module_handle = it->second.shader_module;
1242 pipeline_handle = it->second.pipeline;
1243 pgm = it->second.pgm;
1244 }
1245 GenerateValidationMessage(debug_record, validation_message, vuid_msg);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001246 UtilGenerateStageMessage(debug_record, stage_message);
1247 UtilGenerateCommonMessage(report_data, command_buffer, debug_record, shader_module_handle, pipeline_handle, pipeline_bind_point,
1248 operation_index, common_message);
1249 UtilGenerateSourceMessages(pgm, debug_record, false, filename_message, source_message);
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001250 LogError(queue, vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
1251 filename_message.c_str(), source_message.c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -06001252 // The debug record at word kInstCommonOutSize is the number of words in the record
1253 // written by the shader. Clear the entire record plus the total_words word at the start.
Tony-LunarGab47cac2019-12-20 15:28:01 -07001254 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], (uint32_t)kInstMaxOutCnt);
Karl Schultz7b024b42018-08-30 16:18:18 -06001255 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
1256}
1257
Tony-LunarG81efe392019-03-07 15:43:27 -07001258// 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 -06001259void GpuAssisted::UpdateInstrumentationBuffer(CMD_BUFFER_STATE *cb_node) {
Tony-LunarG1dce2392019-10-23 16:49:29 -06001260 auto gpu_buffer_list = GetBufferInfo(cb_node->commandBuffer);
Tony-LunarG81efe392019-03-07 15:43:27 -07001261 uint32_t *pData;
1262 for (auto &buffer_info : gpu_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001263 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001264 VkResult result = vmaMapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation, (void **)&pData);
Tony-LunarG81efe392019-03-07 15:43:27 -07001265 if (result == VK_SUCCESS) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001266 for (auto update : buffer_info.di_input_mem_block.update_at_submit) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001267 if (update.second->updated) pData[update.first] = 1;
1268 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001269 vmaUnmapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07001270 }
1271 }
1272 }
1273}
1274
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001275void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001276 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1277 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1278 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001279 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07001280 UpdateInstrumentationBuffer(cb_node);
1281 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
1282 UpdateInstrumentationBuffer(secondaryCmdBuffer);
1283 }
1284 }
1285 }
1286}
1287
Karl Schultz58674242019-01-22 15:35:02 -07001288// Issue a memory barrier to make GPU-written data available to host.
1289// Wait for the queue to complete execution.
1290// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001291void GpuAssisted::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
1292 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001293 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001294
Mark Lobodzinski09379db2020-05-07 08:22:01 -06001295 if (aborted || (result != VK_SUCCESS)) return;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001296 bool buffers_present = false;
1297 // Don't QueueWaitIdle if there's nothing to process
1298 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1299 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1300 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
1301 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG1dce2392019-10-23 16:49:29 -06001302 if (GetBufferInfo(cb_node->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd) buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001303 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarG1dce2392019-10-23 16:49:29 -06001304 if (GetBufferInfo(secondaryCmdBuffer->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd)
Jason Macnak83cfd582019-07-31 10:14:24 -07001305 buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001306 }
1307 }
1308 }
1309 if (!buffers_present) return;
Karl Schultz58674242019-01-22 15:35:02 -07001310
Tony-LunarGb5fae462020-03-05 12:43:25 -07001311 UtilSubmitBarrier(queue, this);
Karl Schultz58674242019-01-22 15:35:02 -07001312
Tony-LunarG152a88b2019-03-20 15:42:24 -06001313 DispatchQueueWaitIdle(queue);
Karl Schultz58674242019-01-22 15:35:02 -07001314
Karl Schultz7b024b42018-08-30 16:18:18 -06001315 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1316 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1317 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001318 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001319 UtilProcessInstrumentationBuffer(queue, cb_node, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001320 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06001321 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarGb5fae462020-03-05 12:43:25 -07001322 UtilProcessInstrumentationBuffer(queue, secondaryCmdBuffer, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001323 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06001324 }
1325 }
1326 }
1327}
Tony-LunarGb2501d22019-01-28 09:59:13 -07001328
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001329void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
1330 uint32_t firstVertex, uint32_t firstInstance) {
1331 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1332}
1333
1334void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
1335 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
1336 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1337}
1338
1339void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
1340 uint32_t stride) {
1341 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1342}
1343
1344void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1345 uint32_t count, uint32_t stride) {
1346 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1347}
1348
1349void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
1350 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1351}
1352
1353void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
1354 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1355}
1356
1357void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1358 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1359 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1360 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1361 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1362 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1363 uint32_t width, uint32_t height, uint32_t depth) {
1364 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
1365}
1366
1367void GpuAssisted::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1368 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1369 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1370 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1371 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1372 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1373 uint32_t width, uint32_t height, uint32_t depth) {
1374 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1375 cb_state->hasTraceRaysCmd = true;
1376}
1377
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001378void GpuAssisted::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
1379 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1380 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1381 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1382 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, uint32_t width,
1383 uint32_t height, uint32_t depth) {
1384 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
1385}
1386
1387void GpuAssisted::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
1388 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1389 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1390 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1391 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, uint32_t width,
1392 uint32_t height, uint32_t depth) {
1393 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1394 cb_state->hasTraceRaysCmd = true;
1395}
1396
1397void GpuAssisted::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
1398 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1399 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1400 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1401 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, VkBuffer buffer,
1402 VkDeviceSize offset) {
1403 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
1404}
1405
1406void GpuAssisted::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
1407 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1408 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1409 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1410 const VkStridedBufferRegionKHR *pCallableShaderBindingTable,
1411 VkBuffer buffer, VkDeviceSize offset) {
1412 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1413 cb_state->hasTraceRaysCmd = true;
1414}
1415
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001416void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Jason Macnak67407e72019-07-11 11:05:09 -07001417 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1418 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
andreygca287f22019-04-10 00:15:33 +03001419 return;
1420 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001421 VkResult result;
1422
Tony-LunarG99b880b2019-09-26 11:19:52 -06001423 if (aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001424
1425 std::vector<VkDescriptorSet> desc_sets;
1426 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -06001427 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001428 assert(result == VK_SUCCESS);
1429 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001430 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001431 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001432 return;
1433 }
1434
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001435 VkDescriptorBufferInfo output_desc_buffer_info = {};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001436 output_desc_buffer_info.range = output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001437
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001438 auto cb_node = GetCBState(cmd_buffer);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001439 if (!cb_node) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001440 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001441 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001442 return;
1443 }
1444
Tony-LunarG81efe392019-03-07 15:43:27 -07001445 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001446 GpuAssistedDeviceMemoryBlock output_block = {};
Tony-LunarG0e564722019-03-19 16:09:14 -06001447 VkBufferCreateInfo bufferInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001448 bufferInfo.size = output_buffer_size;
Tony-LunarG0e564722019-03-19 16:09:14 -06001449 bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1450 VmaAllocationCreateInfo allocInfo = {};
1451 allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001452 result = vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001453 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001454 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001455 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001456 return;
1457 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001458
Tony-LunarG81efe392019-03-07 15:43:27 -07001459 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGa77cade2019-03-06 10:49:22 -07001460 uint32_t *pData;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001461 result = vmaMapMemory(vmaAllocator, output_block.allocation, (void **)&pData);
Tony-LunarG0e564722019-03-19 16:09:14 -06001462 if (result == VK_SUCCESS) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001463 memset(pData, 0, output_buffer_size);
1464 vmaUnmapMemory(vmaAllocator, output_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001465 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001466
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001467 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001468 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
1469 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
1470 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001471 uint32_t desc_count = 1;
1472 auto const &state = cb_node->lastBound[bind_point];
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001473 uint32_t number_of_sets = (uint32_t)state.per_set.size();
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001474
Tony-LunarG81efe392019-03-07 15:43:27 -07001475 // Figure out how much memory we need for the input block based on how many sets and bindings there are
1476 // and how big each of the bindings is
Mark Lobodzinskif45e45f2019-04-19 14:15:39 -06001477 if (number_of_sets > 0 && device_extensions.vk_ext_descriptor_indexing) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001478 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
1479 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001480 for (auto s : state.per_set) {
1481 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06001482 if (desc && (desc->GetBindingCount() > 0)) {
1483 auto bindings = desc->GetLayout()->GetSortedBindingSet();
Tony-LunarGa77cade2019-03-06 10:49:22 -07001484 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
1485 for (auto binding : bindings) {
Tony-LunarG7564b382019-08-21 10:11:35 -06001486 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1487 // blocks
1488 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1489 descriptor_count++;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001490 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
1491 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
1492 "validation");
Tony-LunarG7564b382019-08-21 10:11:35 -06001493 } else if (binding == desc->GetLayout()->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001494 descriptor_count += desc->GetVariableDescriptorCount();
1495 } else {
1496 descriptor_count += desc->GetDescriptorCountFromBinding(binding);
1497 }
1498 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001499 }
1500 }
1501
Tony-LunarGa77cade2019-03-06 10:49:22 -07001502 // Note that the size of the input buffer is dependent on the maximum binding number, which
1503 // can be very large. This is because for (set = s, binding = b, index = i), the validation
1504 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
1505 // see if descriptors have been written. In gpu_validation.md, we note this and advise
1506 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
1507 uint32_t words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001508 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
1509 bufferInfo.size = words_needed * 4;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001510 result =
1511 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &di_input_block.buffer, &di_input_block.allocation, nullptr);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001512 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001513 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001514 aborted = true;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001515 return;
1516 }
1517
Tony-LunarGa77cade2019-03-06 10:49:22 -07001518 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
1519 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
1520 // outline of the input buffer format
Tony-LunarG99b880b2019-09-26 11:19:52 -06001521 result = vmaMapMemory(vmaAllocator, di_input_block.allocation, (void **)&pData);
Tony-LunarG76cdcac2019-05-22 16:13:12 -06001522 memset(pData, 0, static_cast<size_t>(bufferInfo.size));
Tony-LunarGa77cade2019-03-06 10:49:22 -07001523 // Pointer to a sets array that points into the sizes array
1524 uint32_t *sets_to_sizes = pData + 1;
1525 // Pointer to the sizes array that contains the array size of the descriptor at each binding
1526 uint32_t *sizes = sets_to_sizes + number_of_sets;
1527 // Pointer to another sets array that points into the bindings array that points into the written array
1528 uint32_t *sets_to_bindings = sizes + binding_count;
1529 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
1530 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
1531 // Index of the next entry in the written array to be updated
1532 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001533 uint32_t bindCounter = number_of_sets + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07001534 // Index of the start of the sets_to_bindings array
1535 pData[0] = number_of_sets + binding_count + 1;
1536
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001537 for (auto s : state.per_set) {
1538 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06001539 if (desc && (desc->GetBindingCount() > 0)) {
1540 auto layout = desc->GetLayout();
1541 auto bindings = layout->GetSortedBindingSet();
Tony-LunarG81efe392019-03-07 15:43:27 -07001542 // For each set, fill in index of its bindings sizes in the sizes array
Tony-LunarGa77cade2019-03-06 10:49:22 -07001543 *sets_to_sizes++ = bindCounter;
Tony-LunarG81efe392019-03-07 15:43:27 -07001544 // For each set, fill in the index of its bindings in the bindings_to_written array
Tony-LunarGa77cade2019-03-06 10:49:22 -07001545 *sets_to_bindings++ = bindCounter + number_of_sets + binding_count;
Tony-LunarG81efe392019-03-07 15:43:27 -07001546 for (auto binding : bindings) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001547 // For each binding, fill in its size in the sizes array
Tony-LunarG7564b382019-08-21 10:11:35 -06001548 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1549 // blocks
1550 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1551 sizes[binding] = 1;
1552 } else if (binding == layout->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001553 sizes[binding] = desc->GetVariableDescriptorCount();
1554 } else {
1555 sizes[binding] = desc->GetDescriptorCountFromBinding(binding);
1556 }
1557 // Fill in the starting index for this binding in the written array in the bindings_to_written array
1558 bindings_to_written[binding] = written_index;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001559
Tony-LunarG7564b382019-08-21 10:11:35 -06001560 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1561 // blocks
1562 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1563 pData[written_index++] = 1;
1564 continue;
1565 }
1566
Tony-LunarGa77cade2019-03-06 10:49:22 -07001567 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
1568 // For each array element in the binding, update the written array with whether it has been written
1569 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
1570 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
Tony-LunarG81efe392019-03-07 15:43:27 -07001571 if (descriptor->updated) {
1572 pData[written_index] = 1;
1573 } else if (desc->IsUpdateAfterBind(binding)) {
1574 // 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 -06001575 di_input_block.update_at_submit[written_index] = descriptor;
Tony-LunarG81efe392019-03-07 15:43:27 -07001576 }
Tony-LunarGa77cade2019-03-06 10:49:22 -07001577 written_index++;
1578 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001579 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001580 auto last = desc->GetLayout()->GetMaxBinding();
1581 bindings_to_written += last + 1;
1582 bindCounter += last + 1;
1583 sizes += last + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07001584 } else {
1585 *sets_to_sizes++ = 0;
1586 *sets_to_bindings++ = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001587 }
1588 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001589 vmaUnmapMemory(vmaAllocator, di_input_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001590
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001591 di_input_desc_buffer_info.range = (words_needed * 4);
1592 di_input_desc_buffer_info.buffer = di_input_block.buffer;
1593 di_input_desc_buffer_info.offset = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001594
1595 desc_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1596 desc_writes[1].dstBinding = 1;
1597 desc_writes[1].descriptorCount = 1;
1598 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001599 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001600 desc_writes[1].dstSet = desc_sets[0];
1601
1602 desc_count = 2;
Tony-LunarG0e564722019-03-19 16:09:14 -06001603 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001604
Tony-LunarG7e0842f2019-12-10 09:26:34 -07001605 if (number_of_sets > 0 && (device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) &&
1606 buffer_map.size() && shaderInt64) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001607 // Example BDA input buffer assuming 2 buffers using BDA:
1608 // Word 0 | Index of start of buffer sizes (in this case 5)
1609 // Word 1 | 0x0000000000000000
1610 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
1611 // Word 3 | Device Address of second buffer
1612 // Word 4 | 0xffffffffffffffff
1613 // Word 5 | 0 (size of pretend buffer at word 1)
1614 // Word 6 | Size in bytes of first buffer
1615 // Word 7 | Size in bytes of second buffer
1616 // Word 8 | 0 (size of pretend buffer in word 4)
1617
Tony-LunarG99b880b2019-09-26 11:19:52 -06001618 uint32_t num_buffers = static_cast<uint32_t>(buffer_map.size());
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001619 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
1620 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
1621 bufferInfo.size = words_needed * 8; // 64 bit words
Tony-LunarG99b880b2019-09-26 11:19:52 -06001622 result =
1623 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &bda_input_block.buffer, &bda_input_block.allocation, nullptr);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001624 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001625 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001626 aborted = true;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001627 return;
1628 }
1629 uint64_t *bda_data;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001630 result = vmaMapMemory(vmaAllocator, bda_input_block.allocation, (void **)&bda_data);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001631 uint32_t address_index = 1;
1632 uint32_t size_index = 3 + num_buffers;
1633 memset(bda_data, 0, static_cast<size_t>(bufferInfo.size));
1634 bda_data[0] = size_index; // Start of buffer sizes
1635 bda_data[address_index++] = 0; // NULL address
1636 bda_data[size_index++] = 0;
1637
Tony-LunarG99b880b2019-09-26 11:19:52 -06001638 for (auto const &value : buffer_map) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001639 bda_data[address_index++] = value.first;
1640 bda_data[size_index++] = value.second;
1641 }
1642 bda_data[address_index] = UINTPTR_MAX;
1643 bda_data[size_index] = 0;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001644 vmaUnmapMemory(vmaAllocator, bda_input_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001645
1646 bda_input_desc_buffer_info.range = (words_needed * 8);
1647 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
1648 bda_input_desc_buffer_info.offset = 0;
1649
1650 desc_writes[desc_count].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1651 desc_writes[desc_count].dstBinding = 2;
1652 desc_writes[desc_count].descriptorCount = 1;
1653 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1654 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
1655 desc_writes[desc_count].dstSet = desc_sets[0];
1656 desc_count++;
1657 }
1658
Tony-LunarGb2501d22019-01-28 09:59:13 -07001659 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001660 output_desc_buffer_info.buffer = output_block.buffer;
1661 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001662
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001663 desc_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1664 desc_writes[0].descriptorCount = 1;
1665 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1666 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
1667 desc_writes[0].dstSet = desc_sets[0];
1668 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001669
andreyg25ce2622019-04-05 23:07:59 +03001670 auto iter = cb_node->lastBound.find(bind_point); // find() allows read-only access to cb_state
Tony-LunarGb2501d22019-01-28 09:59:13 -07001671 if (iter != cb_node->lastBound.end()) {
1672 auto pipeline_state = iter->second.pipeline_state;
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001673 if (pipeline_state && (pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index)) {
1674 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout, desc_set_bind_index, 1,
Tony-LunarG99b880b2019-09-26 11:19:52 -06001675 desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001676 }
Tony-LunarG0e564722019-03-19 16:09:14 -06001677 // Record buffer and memory info in CB state tracking
Tony-LunarG1dce2392019-10-23 16:49:29 -06001678 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 -07001679 } else {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001680 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001681 vmaDestroyBuffer(vmaAllocator, di_input_block.buffer, di_input_block.allocation);
1682 vmaDestroyBuffer(vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
1683 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
1684 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001685 return;
1686 }
1687}