blob: e7878c75f419b2babff32799b1df767fa683be3c [file] [log] [blame]
Tony-LunarG7de10e82020-11-24 11:31:55 -07001/* Copyright (c) 2018-2021 The Khronos Group Inc.
2 * Copyright (c) 2018-2021 Valve Corporation
3 * Copyright (c) 2018-2021 LunarG, Inc.
Karl Schultz7b024b42018-08-30 16:18:18 -06004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060017 * Author: Karl Schultz <karl@lunarg.com>
18 * Author: Tony Barbour <tony@lunarg.com>
Karl Schultz7b024b42018-08-30 16:18:18 -060019 */
20
Tony-LunarGc28e28a2020-08-14 10:37:48 -060021#include <climits>
Tony-LunarGa3ec16c2021-04-06 12:19:57 -060022#include <cmath>
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -070023#include "gpu_validation.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060024#include "spirv-tools/optimizer.hpp"
25#include "spirv-tools/instrument.hpp"
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060026#include "layer_chassis_dispatch.h"
Tony-LunarG7de10e82020-11-24 11:31:55 -070027#include "gpu_vuids.h"
Tony-LunarG20678ff2021-05-07 14:56:26 -060028#include "gpu_pre_draw_constants.h"
Jeremy Gebbena3705f42021-01-19 16:47:43 -070029#include "sync_utils.h"
Jeremy Gebben159b3cc2021-06-03 09:09:03 -060030#include "buffer_state.h"
31#include "cmd_buffer_state.h"
32#include "render_pass_state.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060033
Jason Macnak67407e72019-07-11 11:05:09 -070034static const VkShaderStageFlags kShaderStageAllRayTracing =
35 VK_SHADER_STAGE_ANY_HIT_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV | VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV |
36 VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV | VK_SHADER_STAGE_RAYGEN_BIT_NV;
37
Jason Macnak83cfd582019-07-31 10:14:24 -070038// Keep in sync with the GLSL shader below.
39struct GpuAccelerationStructureBuildValidationBuffer {
40 uint32_t instances_to_validate;
41 uint32_t replacement_handle_bits_0;
42 uint32_t replacement_handle_bits_1;
43 uint32_t invalid_handle_found;
44 uint32_t invalid_handle_bits_0;
45 uint32_t invalid_handle_bits_1;
46 uint32_t valid_handles_count;
47};
48
49// This is the GLSL source for the compute shader that is used during ray tracing acceleration structure
50// building validation which inspects instance buffers for top level acceleration structure builds and
51// reports and replaces invalid bottom level acceleration structure handles with good bottom level
52// acceleration structure handle so that applications can continue without undefined behavior long enough
53// to report errors.
54//
55// #version 450
56// layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
57// struct VkGeometryInstanceNV {
58// uint unused[14];
59// uint handle_bits_0;
60// uint handle_bits_1;
61// };
62// layout(set=0, binding=0, std430) buffer InstanceBuffer {
63// VkGeometryInstanceNV instances[];
64// };
65// layout(set=0, binding=1, std430) buffer ValidationBuffer {
66// uint instances_to_validate;
67// uint replacement_handle_bits_0;
68// uint replacement_handle_bits_1;
69// uint invalid_handle_found;
70// uint invalid_handle_bits_0;
71// uint invalid_handle_bits_1;
72// uint valid_handles_count;
73// uint valid_handles[];
74// };
75// void main() {
76// for (uint instance_index = 0; instance_index < instances_to_validate; instance_index++) {
77// uint instance_handle_bits_0 = instances[instance_index].handle_bits_0;
78// uint instance_handle_bits_1 = instances[instance_index].handle_bits_1;
79// bool valid = false;
80// for (uint valid_handle_index = 0; valid_handle_index < valid_handles_count; valid_handle_index++) {
81// if (instance_handle_bits_0 == valid_handles[2*valid_handle_index+0] &&
82// instance_handle_bits_1 == valid_handles[2*valid_handle_index+1]) {
83// valid = true;
84// break;
85// }
86// }
87// if (!valid) {
88// invalid_handle_found += 1;
89// invalid_handle_bits_0 = instance_handle_bits_0;
90// invalid_handle_bits_1 = instance_handle_bits_1;
91// instances[instance_index].handle_bits_0 = replacement_handle_bits_0;
92// instances[instance_index].handle_bits_1 = replacement_handle_bits_1;
93// }
94// }
95// }
96//
97// To regenerate the spirv below:
98// 1. Save the above GLSL source to a file called validation_shader.comp.
99// 2. Run in terminal
100//
101// glslangValidator.exe -x -V validation_shader.comp -o validation_shader.comp.spv
102//
103// 4. Copy-paste the contents of validation_shader.comp.spv here (clang-format will fix up the alignment).
104static const uint32_t kComputeShaderSpirv[] = {
105 0x07230203, 0x00010000, 0x00080007, 0x0000006d, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, 0x00000001, 0x4c534c47,
106 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0005000f, 0x00000005, 0x00000004, 0x6e69616d,
107 0x00000000, 0x00060010, 0x00000004, 0x00000011, 0x00000001, 0x00000001, 0x00000001, 0x00030003, 0x00000002, 0x000001c2,
108 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00060005, 0x00000008, 0x74736e69, 0x65636e61, 0x646e695f, 0x00007865,
109 0x00070005, 0x00000011, 0x696c6156, 0x69746164, 0x75426e6f, 0x72656666, 0x00000000, 0x00090006, 0x00000011, 0x00000000,
110 0x74736e69, 0x65636e61, 0x6f745f73, 0x6c61765f, 0x74616469, 0x00000065, 0x000a0006, 0x00000011, 0x00000001, 0x6c706572,
111 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x000a0006, 0x00000011, 0x00000002, 0x6c706572,
112 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00090006, 0x00000011, 0x00000003, 0x61766e69,
113 0x5f64696c, 0x646e6168, 0x665f656c, 0x646e756f, 0x00000000, 0x00090006, 0x00000011, 0x00000004, 0x61766e69, 0x5f64696c,
114 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00090006, 0x00000011, 0x00000005, 0x61766e69, 0x5f64696c, 0x646e6168,
115 0x625f656c, 0x5f737469, 0x00000031, 0x00080006, 0x00000011, 0x00000006, 0x696c6176, 0x61685f64, 0x656c646e, 0x6f635f73,
116 0x00746e75, 0x00070006, 0x00000011, 0x00000007, 0x696c6176, 0x61685f64, 0x656c646e, 0x00000073, 0x00030005, 0x00000013,
117 0x00000000, 0x00080005, 0x0000001b, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000305f, 0x00080005,
118 0x0000001e, 0x65476b56, 0x74656d6f, 0x6e497972, 0x6e617473, 0x564e6563, 0x00000000, 0x00050006, 0x0000001e, 0x00000000,
119 0x73756e75, 0x00006465, 0x00070006, 0x0000001e, 0x00000001, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00070006,
120 0x0000001e, 0x00000002, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00060005, 0x00000020, 0x74736e49, 0x65636e61,
121 0x66667542, 0x00007265, 0x00060006, 0x00000020, 0x00000000, 0x74736e69, 0x65636e61, 0x00000073, 0x00030005, 0x00000022,
122 0x00000000, 0x00080005, 0x00000027, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000315f, 0x00040005,
123 0x0000002d, 0x696c6176, 0x00000064, 0x00070005, 0x0000002f, 0x696c6176, 0x61685f64, 0x656c646e, 0x646e695f, 0x00007865,
124 0x00040047, 0x00000010, 0x00000006, 0x00000004, 0x00050048, 0x00000011, 0x00000000, 0x00000023, 0x00000000, 0x00050048,
125 0x00000011, 0x00000001, 0x00000023, 0x00000004, 0x00050048, 0x00000011, 0x00000002, 0x00000023, 0x00000008, 0x00050048,
126 0x00000011, 0x00000003, 0x00000023, 0x0000000c, 0x00050048, 0x00000011, 0x00000004, 0x00000023, 0x00000010, 0x00050048,
127 0x00000011, 0x00000005, 0x00000023, 0x00000014, 0x00050048, 0x00000011, 0x00000006, 0x00000023, 0x00000018, 0x00050048,
128 0x00000011, 0x00000007, 0x00000023, 0x0000001c, 0x00030047, 0x00000011, 0x00000003, 0x00040047, 0x00000013, 0x00000022,
129 0x00000000, 0x00040047, 0x00000013, 0x00000021, 0x00000001, 0x00040047, 0x0000001d, 0x00000006, 0x00000004, 0x00050048,
130 0x0000001e, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x0000001e, 0x00000001, 0x00000023, 0x00000038, 0x00050048,
131 0x0000001e, 0x00000002, 0x00000023, 0x0000003c, 0x00040047, 0x0000001f, 0x00000006, 0x00000040, 0x00050048, 0x00000020,
132 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x00000020, 0x00000003, 0x00040047, 0x00000022, 0x00000022, 0x00000000,
133 0x00040047, 0x00000022, 0x00000021, 0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00040015,
134 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, 0x00000006, 0x0004002b, 0x00000006, 0x00000009,
135 0x00000000, 0x0003001d, 0x00000010, 0x00000006, 0x000a001e, 0x00000011, 0x00000006, 0x00000006, 0x00000006, 0x00000006,
136 0x00000006, 0x00000006, 0x00000006, 0x00000010, 0x00040020, 0x00000012, 0x00000002, 0x00000011, 0x0004003b, 0x00000012,
137 0x00000013, 0x00000002, 0x00040015, 0x00000014, 0x00000020, 0x00000001, 0x0004002b, 0x00000014, 0x00000015, 0x00000000,
138 0x00040020, 0x00000016, 0x00000002, 0x00000006, 0x00020014, 0x00000019, 0x0004002b, 0x00000006, 0x0000001c, 0x0000000e,
139 0x0004001c, 0x0000001d, 0x00000006, 0x0000001c, 0x0005001e, 0x0000001e, 0x0000001d, 0x00000006, 0x00000006, 0x0003001d,
140 0x0000001f, 0x0000001e, 0x0003001e, 0x00000020, 0x0000001f, 0x00040020, 0x00000021, 0x00000002, 0x00000020, 0x0004003b,
141 0x00000021, 0x00000022, 0x00000002, 0x0004002b, 0x00000014, 0x00000024, 0x00000001, 0x0004002b, 0x00000014, 0x00000029,
142 0x00000002, 0x00040020, 0x0000002c, 0x00000007, 0x00000019, 0x0003002a, 0x00000019, 0x0000002e, 0x0004002b, 0x00000014,
143 0x00000036, 0x00000006, 0x0004002b, 0x00000014, 0x0000003b, 0x00000007, 0x0004002b, 0x00000006, 0x0000003c, 0x00000002,
144 0x0004002b, 0x00000006, 0x00000048, 0x00000001, 0x00030029, 0x00000019, 0x00000050, 0x0004002b, 0x00000014, 0x00000058,
145 0x00000003, 0x0004002b, 0x00000014, 0x0000005d, 0x00000004, 0x0004002b, 0x00000014, 0x00000060, 0x00000005, 0x00050036,
146 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007,
147 0x0004003b, 0x00000007, 0x0000001b, 0x00000007, 0x0004003b, 0x00000007, 0x00000027, 0x00000007, 0x0004003b, 0x0000002c,
148 0x0000002d, 0x00000007, 0x0004003b, 0x00000007, 0x0000002f, 0x00000007, 0x0003003e, 0x00000008, 0x00000009, 0x000200f9,
149 0x0000000a, 0x000200f8, 0x0000000a, 0x000400f6, 0x0000000c, 0x0000000d, 0x00000000, 0x000200f9, 0x0000000e, 0x000200f8,
150 0x0000000e, 0x0004003d, 0x00000006, 0x0000000f, 0x00000008, 0x00050041, 0x00000016, 0x00000017, 0x00000013, 0x00000015,
151 0x0004003d, 0x00000006, 0x00000018, 0x00000017, 0x000500b0, 0x00000019, 0x0000001a, 0x0000000f, 0x00000018, 0x000400fa,
152 0x0000001a, 0x0000000b, 0x0000000c, 0x000200f8, 0x0000000b, 0x0004003d, 0x00000006, 0x00000023, 0x00000008, 0x00070041,
153 0x00000016, 0x00000025, 0x00000022, 0x00000015, 0x00000023, 0x00000024, 0x0004003d, 0x00000006, 0x00000026, 0x00000025,
154 0x0003003e, 0x0000001b, 0x00000026, 0x0004003d, 0x00000006, 0x00000028, 0x00000008, 0x00070041, 0x00000016, 0x0000002a,
155 0x00000022, 0x00000015, 0x00000028, 0x00000029, 0x0004003d, 0x00000006, 0x0000002b, 0x0000002a, 0x0003003e, 0x00000027,
156 0x0000002b, 0x0003003e, 0x0000002d, 0x0000002e, 0x0003003e, 0x0000002f, 0x00000009, 0x000200f9, 0x00000030, 0x000200f8,
157 0x00000030, 0x000400f6, 0x00000032, 0x00000033, 0x00000000, 0x000200f9, 0x00000034, 0x000200f8, 0x00000034, 0x0004003d,
158 0x00000006, 0x00000035, 0x0000002f, 0x00050041, 0x00000016, 0x00000037, 0x00000013, 0x00000036, 0x0004003d, 0x00000006,
159 0x00000038, 0x00000037, 0x000500b0, 0x00000019, 0x00000039, 0x00000035, 0x00000038, 0x000400fa, 0x00000039, 0x00000031,
160 0x00000032, 0x000200f8, 0x00000031, 0x0004003d, 0x00000006, 0x0000003a, 0x0000001b, 0x0004003d, 0x00000006, 0x0000003d,
161 0x0000002f, 0x00050084, 0x00000006, 0x0000003e, 0x0000003c, 0x0000003d, 0x00050080, 0x00000006, 0x0000003f, 0x0000003e,
162 0x00000009, 0x00060041, 0x00000016, 0x00000040, 0x00000013, 0x0000003b, 0x0000003f, 0x0004003d, 0x00000006, 0x00000041,
163 0x00000040, 0x000500aa, 0x00000019, 0x00000042, 0x0000003a, 0x00000041, 0x000300f7, 0x00000044, 0x00000000, 0x000400fa,
164 0x00000042, 0x00000043, 0x00000044, 0x000200f8, 0x00000043, 0x0004003d, 0x00000006, 0x00000045, 0x00000027, 0x0004003d,
165 0x00000006, 0x00000046, 0x0000002f, 0x00050084, 0x00000006, 0x00000047, 0x0000003c, 0x00000046, 0x00050080, 0x00000006,
166 0x00000049, 0x00000047, 0x00000048, 0x00060041, 0x00000016, 0x0000004a, 0x00000013, 0x0000003b, 0x00000049, 0x0004003d,
167 0x00000006, 0x0000004b, 0x0000004a, 0x000500aa, 0x00000019, 0x0000004c, 0x00000045, 0x0000004b, 0x000200f9, 0x00000044,
168 0x000200f8, 0x00000044, 0x000700f5, 0x00000019, 0x0000004d, 0x00000042, 0x00000031, 0x0000004c, 0x00000043, 0x000300f7,
169 0x0000004f, 0x00000000, 0x000400fa, 0x0000004d, 0x0000004e, 0x0000004f, 0x000200f8, 0x0000004e, 0x0003003e, 0x0000002d,
170 0x00000050, 0x000200f9, 0x00000032, 0x000200f8, 0x0000004f, 0x000200f9, 0x00000033, 0x000200f8, 0x00000033, 0x0004003d,
171 0x00000006, 0x00000052, 0x0000002f, 0x00050080, 0x00000006, 0x00000053, 0x00000052, 0x00000024, 0x0003003e, 0x0000002f,
172 0x00000053, 0x000200f9, 0x00000030, 0x000200f8, 0x00000032, 0x0004003d, 0x00000019, 0x00000054, 0x0000002d, 0x000400a8,
173 0x00000019, 0x00000055, 0x00000054, 0x000300f7, 0x00000057, 0x00000000, 0x000400fa, 0x00000055, 0x00000056, 0x00000057,
174 0x000200f8, 0x00000056, 0x00050041, 0x00000016, 0x00000059, 0x00000013, 0x00000058, 0x0004003d, 0x00000006, 0x0000005a,
175 0x00000059, 0x00050080, 0x00000006, 0x0000005b, 0x0000005a, 0x00000048, 0x00050041, 0x00000016, 0x0000005c, 0x00000013,
176 0x00000058, 0x0003003e, 0x0000005c, 0x0000005b, 0x0004003d, 0x00000006, 0x0000005e, 0x0000001b, 0x00050041, 0x00000016,
177 0x0000005f, 0x00000013, 0x0000005d, 0x0003003e, 0x0000005f, 0x0000005e, 0x0004003d, 0x00000006, 0x00000061, 0x00000027,
178 0x00050041, 0x00000016, 0x00000062, 0x00000013, 0x00000060, 0x0003003e, 0x00000062, 0x00000061, 0x0004003d, 0x00000006,
179 0x00000063, 0x00000008, 0x00050041, 0x00000016, 0x00000064, 0x00000013, 0x00000024, 0x0004003d, 0x00000006, 0x00000065,
180 0x00000064, 0x00070041, 0x00000016, 0x00000066, 0x00000022, 0x00000015, 0x00000063, 0x00000024, 0x0003003e, 0x00000066,
181 0x00000065, 0x0004003d, 0x00000006, 0x00000067, 0x00000008, 0x00050041, 0x00000016, 0x00000068, 0x00000013, 0x00000029,
182 0x0004003d, 0x00000006, 0x00000069, 0x00000068, 0x00070041, 0x00000016, 0x0000006a, 0x00000022, 0x00000015, 0x00000067,
183 0x00000029, 0x0003003e, 0x0000006a, 0x00000069, 0x000200f9, 0x00000057, 0x000200f8, 0x00000057, 0x000200f9, 0x0000000d,
184 0x000200f8, 0x0000000d, 0x0004003d, 0x00000006, 0x0000006b, 0x00000008, 0x00050080, 0x00000006, 0x0000006c, 0x0000006b,
185 0x00000024, 0x0003003e, 0x00000008, 0x0000006c, 0x000200f9, 0x0000000a, 0x000200f8, 0x0000000c, 0x000100fd, 0x00010038};
186
Karl Schultz7b024b42018-08-30 16:18:18 -0600187// Convenience function for reporting problems with setting up GPU Validation.
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700188template <typename T>
189void GpuAssisted::ReportSetupProblem(T object, const char *const specific_message) const {
190 LogError(object, "UNASSIGNED-GPU-Assisted Validation Error. ", "Detail: (%s)", specific_message);
Karl Schultz7b024b42018-08-30 16:18:18 -0600191}
192
Tony-LunarG5c38b182020-06-10 16:15:32 -0600193bool GpuAssisted::CheckForDescriptorIndexing(DeviceFeatures enabled_features) const {
194 bool result =
195 (IsExtEnabled(device_extensions.vk_ext_descriptor_indexing) &&
196 (enabled_features.core12.descriptorIndexing || enabled_features.core12.shaderInputAttachmentArrayDynamicIndexing ||
197 enabled_features.core12.shaderUniformTexelBufferArrayDynamicIndexing ||
198 enabled_features.core12.shaderStorageTexelBufferArrayDynamicIndexing ||
199 enabled_features.core12.shaderUniformBufferArrayNonUniformIndexing ||
200 enabled_features.core12.shaderSampledImageArrayNonUniformIndexing ||
201 enabled_features.core12.shaderStorageBufferArrayNonUniformIndexing ||
202 enabled_features.core12.shaderStorageImageArrayNonUniformIndexing ||
203 enabled_features.core12.shaderInputAttachmentArrayNonUniformIndexing ||
204 enabled_features.core12.shaderUniformTexelBufferArrayNonUniformIndexing ||
205 enabled_features.core12.shaderStorageTexelBufferArrayNonUniformIndexing ||
206 enabled_features.core12.descriptorBindingUniformBufferUpdateAfterBind ||
207 enabled_features.core12.descriptorBindingSampledImageUpdateAfterBind ||
208 enabled_features.core12.descriptorBindingStorageImageUpdateAfterBind ||
209 enabled_features.core12.descriptorBindingStorageBufferUpdateAfterBind ||
210 enabled_features.core12.descriptorBindingUniformTexelBufferUpdateAfterBind ||
211 enabled_features.core12.descriptorBindingStorageTexelBufferUpdateAfterBind ||
212 enabled_features.core12.descriptorBindingUpdateUnusedWhilePending ||
213 enabled_features.core12.descriptorBindingPartiallyBound ||
214 enabled_features.core12.descriptorBindingVariableDescriptorCount || enabled_features.core12.runtimeDescriptorArray));
215 return result;
216}
217
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600218void GpuAssisted::PreCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
219 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer, void *cb_state_data) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700220 // Ray tracing acceleration structure instance buffers also need the storage buffer usage as
221 // acceleration structure build validation will find and replace invalid acceleration structure
222 // handles inside of a compute shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600223 create_buffer_api_state *cb_state = reinterpret_cast<create_buffer_api_state *>(cb_state_data);
224 if (cb_state && cb_state->modified_create_info.usage & VK_BUFFER_USAGE_RAY_TRACING_BIT_NV) {
225 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
Jason Macnak83cfd582019-07-31 10:14:24 -0700226 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600227
228 // Validating DrawIndirectCount countBuffer will require validation shader to bind the count buffer as a storage buffer
Tony-LunarG3723a3a2021-05-04 14:52:39 -0600229 if (validate_draw_indirect && cb_state && cb_state->modified_create_info.usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) {
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600230 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
231 }
Jason Macnak83cfd582019-07-31 10:14:24 -0700232}
233
Karl Schultz7b024b42018-08-30 16:18:18 -0600234// Turn on necessary device features.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600235void GpuAssisted::PreCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info,
236 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
Mark Lobodzinskib588cd42020-09-30 11:03:34 -0600237 void *modified_create_info) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600238 DispatchGetPhysicalDeviceFeatures(gpu, &supported_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600239 VkPhysicalDeviceFeatures features = {};
240 features.vertexPipelineStoresAndAtomics = true;
241 features.fragmentStoresAndAtomics = true;
242 features.shaderInt64 = true;
Mark Lobodzinskib588cd42020-09-30 11:03:34 -0600243 UtilPreCallRecordCreateDevice(gpu, reinterpret_cast<safe_VkDeviceCreateInfo *>(modified_create_info), supported_features,
244 features);
Karl Schultz7b024b42018-08-30 16:18:18 -0600245}
Karl Schultz7b024b42018-08-30 16:18:18 -0600246// Perform initializations that can be done at Create Device time.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600247void GpuAssisted::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
248 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result) {
249 // The state tracker sets up the device state
Tony-LunarG99b880b2019-09-26 11:19:52 -0600250 ValidationStateTracker::PostCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski5dc3dcd2019-04-23 14:26:28 -0600251
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600252 ValidationObject *device_object = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
253 ValidationObject *validation_data = GetValidationObject(device_object->object_dispatch, this->container_type);
254 GpuAssisted *device_gpu_assisted = static_cast<GpuAssisted *>(validation_data);
Tony-LunarG65f9c492019-01-17 14:24:42 -0700255
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600256 if (device_gpu_assisted->enabled_features.core.robustBufferAccess ||
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700257 device_gpu_assisted->enabled_features.robustness2_features.robustBufferAccess2) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600258 device_gpu_assisted->buffer_oob_enabled = false;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700259 } else {
Tony-LunarGc99dbef2021-06-14 15:11:50 -0600260 std::string bufferoob_string = getLayerOption("khronos_validation.gpuav_buffer_oob");
261 transform(bufferoob_string.begin(), bufferoob_string.end(), bufferoob_string.begin(), ::tolower);
262 device_gpu_assisted->buffer_oob_enabled = bufferoob_string.length() ? !bufferoob_string.compare("true") : true;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700263 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600264
Tony-LunarGc99dbef2021-06-14 15:11:50 -0600265 std::string draw_indirect_string = getLayerOption("khronos_validation.validate_draw_indirect");
266 transform(draw_indirect_string.begin(), draw_indirect_string.end(), draw_indirect_string.begin(), ::tolower);
267 device_gpu_assisted->validate_draw_indirect = draw_indirect_string.length() ? !draw_indirect_string.compare("true") : true;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600268
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600269 if (device_gpu_assisted->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700270 ReportSetupProblem(device, "GPU-Assisted validation requires Vulkan 1.1 or later. GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600271 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600272 return;
273 }
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600274
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600275 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700276 ReportSetupProblem(device,
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600277 "GPU-Assisted validation requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
278 "GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600279 device_gpu_assisted->aborted = true;
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600280 return;
281 }
282
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700283 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) &&
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600284 !supported_features.shaderInt64) {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700285 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
286 "shaderInt64 feature is not available. No buffer device address checking will be attempted");
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600287 }
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600288 device_gpu_assisted->shaderInt64 = supported_features.shaderInt64;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600289 device_gpu_assisted->physicalDevice = physicalDevice;
290 device_gpu_assisted->device = *pDevice;
Tony-LunarGbb145f32020-04-27 13:41:29 -0600291 device_gpu_assisted->output_buffer_size = sizeof(uint32_t) * (spvtools::kInstMaxOutCnt + 1);
Tony-LunarG5c38b182020-06-10 16:15:32 -0600292 device_gpu_assisted->descriptor_indexing = CheckForDescriptorIndexing(device_gpu_assisted->enabled_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600293 std::vector<VkDescriptorSetLayoutBinding> bindings;
294 VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
Tony-LunarGc7ed2082020-06-11 14:00:04 -0600295 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT |
296 VK_SHADER_STAGE_MESH_BIT_NV | VK_SHADER_STAGE_TASK_BIT_NV |
297 kShaderStageAllRayTracing,
Tony-LunarG1dce2392019-10-23 16:49:29 -0600298 NULL};
299 bindings.push_back(binding);
300 for (auto i = 1; i < 3; i++) {
301 binding.binding = i;
302 bindings.push_back(binding);
Karl Schultz7b024b42018-08-30 16:18:18 -0600303 }
Tony-LunarGb5fae462020-03-05 12:43:25 -0700304 UtilPostCallRecordCreateDevice(pCreateInfo, bindings, device_gpu_assisted, device_gpu_assisted->phys_dev_props);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600305 CreateAccelerationStructureBuildValidationState(device_gpu_assisted);
Karl Schultz7b024b42018-08-30 16:18:18 -0600306}
307
Mike Schuchardt2df08912020-12-15 16:28:09 -0800308void GpuAssisted::PostCallRecordGetBufferDeviceAddress(VkDevice device, const VkBufferDeviceAddressInfo *pInfo,
Tony-LunarG588c7052020-04-23 10:47:21 -0600309 VkDeviceAddress address) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600310 BUFFER_STATE *buffer_state = GetBufferState(pInfo->buffer);
311 // Validate against the size requested when the buffer was created
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600312 if (buffer_state) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600313 buffer_map[address] = buffer_state->createInfo.size;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600314 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600315}
316
Mike Schuchardt2df08912020-12-15 16:28:09 -0800317void GpuAssisted::PostCallRecordGetBufferDeviceAddressEXT(VkDevice device, const VkBufferDeviceAddressInfo *pInfo,
Tony-LunarG588c7052020-04-23 10:47:21 -0600318 VkDeviceAddress address) {
319 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
320}
321
Mike Schuchardt2df08912020-12-15 16:28:09 -0800322void GpuAssisted::PostCallRecordGetBufferDeviceAddressKHR(VkDevice device, const VkBufferDeviceAddressInfo *pInfo,
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700323 VkDeviceAddress address) {
Tony-LunarG588c7052020-04-23 10:47:21 -0600324 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700325}
326
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600327void GpuAssisted::PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600328 BUFFER_STATE *buffer_state = GetBufferState(buffer);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600329 if (buffer_state) buffer_map.erase(buffer_state->deviceAddress);
Tony-LunarG2966c732020-05-21 10:33:53 -0600330 ValidationStateTracker::PreCallRecordDestroyBuffer(device, buffer, pAllocator);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600331}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600332
Karl Schultz7b024b42018-08-30 16:18:18 -0600333// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600334void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600335 DestroyAccelerationStructureBuildValidationState();
Tony-LunarGb5fae462020-03-05 12:43:25 -0700336 UtilPreCallRecordDestroyDevice(this);
Tony-LunarG2966c732020-05-21 10:33:53 -0600337 ValidationStateTracker::PreCallRecordDestroyDevice(device, pAllocator);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600338 if (pre_draw_validation_state.globals_created) {
339 DispatchDestroyShaderModule(device, pre_draw_validation_state.validation_shader_module, nullptr);
340 DispatchDestroyDescriptorSetLayout(device, pre_draw_validation_state.validation_ds_layout, nullptr);
341 DispatchDestroyPipelineLayout(device, pre_draw_validation_state.validation_pipeline_layout, nullptr);
342 for (auto it = pre_draw_validation_state.renderpass_to_pipeline.begin();
343 it != pre_draw_validation_state.renderpass_to_pipeline.end(); ++it) {
344 DispatchDestroyPipeline(device, it->second, nullptr);
345 }
346 pre_draw_validation_state.renderpass_to_pipeline.clear();
347 pre_draw_validation_state.globals_created = false;
348 }
Tony-LunarG0a863bc2020-09-16 09:50:04 -0600349 // State Tracker can end up making vma calls through callbacks - don't destroy allocator until ST is done
350 if (vmaAllocator) {
351 vmaDestroyAllocator(vmaAllocator);
352 }
353 desc_set_manager.reset();
Karl Schultz7b024b42018-08-30 16:18:18 -0600354}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600355
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600356void GpuAssisted::CreateAccelerationStructureBuildValidationState(GpuAssisted *device_gpuav) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600357 if (device_gpuav->aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700358 return;
359 }
360
Tony-LunarG99b880b2019-09-26 11:19:52 -0600361 auto &as_validation_state = device_gpuav->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700362 if (as_validation_state.initialized) {
363 return;
364 }
365
366 if (!device_extensions.vk_nv_ray_tracing) {
367 return;
368 }
369
370 // Outline:
371 // - Create valid bottom level acceleration structure which acts as replacement
372 // - Create and load vertex buffer
373 // - Create and load index buffer
374 // - Create, allocate memory for, and bind memory for acceleration structure
375 // - Query acceleration structure handle
376 // - Create command pool and command buffer
377 // - Record build acceleration structure command
378 // - Submit command buffer and wait for completion
379 // - Cleanup
380 // - Create compute pipeline for validating instance buffers
381 // - Create descriptor set layout
382 // - Create pipeline layout
383 // - Create pipeline
384 // - Cleanup
385
386 VkResult result = VK_SUCCESS;
387
388 VkBuffer vbo = VK_NULL_HANDLE;
389 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
390 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600391 auto vbo_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700392 vbo_ci.size = sizeof(float) * 9;
393 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
394
395 VmaAllocationCreateInfo vbo_ai = {};
396 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
397 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
398
Tony-LunarG99b880b2019-09-26 11:19:52 -0600399 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700400 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700401 ReportSetupProblem(device, "Failed to create vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700402 }
403 }
404
405 if (result == VK_SUCCESS) {
406 uint8_t *mapped_vbo_buffer = nullptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700407 result = vmaMapMemory(device_gpuav->vmaAllocator, vbo_allocation, reinterpret_cast<void **>(&mapped_vbo_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700408 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700409 ReportSetupProblem(device, "Failed to map vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700410 } else {
411 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
412 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600413 vmaUnmapMemory(device_gpuav->vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700414 }
415 }
416
417 VkBuffer ibo = VK_NULL_HANDLE;
418 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
419 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600420 auto ibo_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700421 ibo_ci.size = sizeof(uint32_t) * 3;
422 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
423
424 VmaAllocationCreateInfo ibo_ai = {};
425 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
426 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
427
Tony-LunarG99b880b2019-09-26 11:19:52 -0600428 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700429 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700430 ReportSetupProblem(device, "Failed to create index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700431 }
432 }
433
434 if (result == VK_SUCCESS) {
435 uint8_t *mapped_ibo_buffer = nullptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700436 result = vmaMapMemory(device_gpuav->vmaAllocator, ibo_allocation, reinterpret_cast<void **>(&mapped_ibo_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700437 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700438 ReportSetupProblem(device, "Failed to map index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700439 } else {
440 const std::vector<uint32_t> indicies = {0, 1, 2};
441 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600442 vmaUnmapMemory(device_gpuav->vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700443 }
444 }
445
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600446 auto geometry = LvlInitStruct<VkGeometryNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700447 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600448 geometry.geometry.triangles = LvlInitStruct<VkGeometryTrianglesNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700449 geometry.geometry.triangles.vertexData = vbo;
450 geometry.geometry.triangles.vertexOffset = 0;
451 geometry.geometry.triangles.vertexCount = 3;
452 geometry.geometry.triangles.vertexStride = 12;
453 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
454 geometry.geometry.triangles.indexData = ibo;
455 geometry.geometry.triangles.indexOffset = 0;
456 geometry.geometry.triangles.indexCount = 3;
457 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
458 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
459 geometry.geometry.triangles.transformOffset = 0;
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600460 geometry.geometry.aabbs = LvlInitStruct<VkGeometryAABBNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700461
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600462 auto as_ci = LvlInitStruct<VkAccelerationStructureCreateInfoNV>();
463 as_ci.info = LvlInitStruct<VkAccelerationStructureInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700464 as_ci.info.instanceCount = 0;
465 as_ci.info.geometryCount = 1;
466 as_ci.info.pGeometries = &geometry;
467 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600468 result = DispatchCreateAccelerationStructureNV(device_gpuav->device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700469 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700470 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700471 "Failed to create acceleration structure for acceleration structure build validation.");
472 }
473 }
474
475 VkMemoryRequirements2 as_mem_requirements = {};
476 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600477 auto as_mem_requirements_info = LvlInitStruct<VkAccelerationStructureMemoryRequirementsInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700478 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
479 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
480
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600481 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700482 }
483
484 VmaAllocationInfo as_memory_ai = {};
485 if (result == VK_SUCCESS) {
486 VmaAllocationCreateInfo as_memory_aci = {};
487 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
488
Tony-LunarG99b880b2019-09-26 11:19:52 -0600489 result = vmaAllocateMemory(device_gpuav->vmaAllocator, &as_mem_requirements.memoryRequirements, &as_memory_aci,
490 &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700491 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700492 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700493 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
494 }
495 }
496
497 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600498 auto as_bind_info = LvlInitStruct<VkBindAccelerationStructureMemoryInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700499 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
500 as_bind_info.memory = as_memory_ai.deviceMemory;
501 as_bind_info.memoryOffset = as_memory_ai.offset;
502
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600503 result = DispatchBindAccelerationStructureMemoryNV(device_gpuav->device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700504 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700505 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700506 "Failed to bind acceleration structure memory for acceleration structure build validation.");
507 }
508 }
509
510 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600511 result = DispatchGetAccelerationStructureHandleNV(device_gpuav->device, as_validation_state.replacement_as,
512 sizeof(uint64_t), &as_validation_state.replacement_as_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700513 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700514 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700515 "Failed to get acceleration structure handle for acceleration structure build validation.");
516 }
517 }
518
519 VkMemoryRequirements2 scratch_mem_requirements = {};
520 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600521 auto scratch_mem_requirements_info = LvlInitStruct<VkAccelerationStructureMemoryRequirementsInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700522 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
523 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
524
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600525 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &scratch_mem_requirements_info,
526 &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700527 }
528
529 VkBuffer scratch = VK_NULL_HANDLE;
Tony-LunarG18900282020-05-20 12:34:33 -0600530 VmaAllocation scratch_allocation = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700531 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600532 auto scratch_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700533 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
534 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
Jason Macnak83cfd582019-07-31 10:14:24 -0700535 VmaAllocationCreateInfo scratch_aci = {};
536 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
537
Tony-LunarG18900282020-05-20 12:34:33 -0600538 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &scratch_ci, &scratch_aci, &scratch, &scratch_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700539 if (result != VK_SUCCESS) {
Tony-LunarG18900282020-05-20 12:34:33 -0600540 ReportSetupProblem(device_gpuav->device,
541 "Failed to create scratch buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700542 }
543 }
544
545 VkCommandPool command_pool = VK_NULL_HANDLE;
546 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600547 auto command_pool_ci = LvlInitStruct<VkCommandPoolCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700548 command_pool_ci.queueFamilyIndex = 0;
549
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600550 result = DispatchCreateCommandPool(device_gpuav->device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700551 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700552 ReportSetupProblem(device_gpuav->device, "Failed to create command pool for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700553 }
554 }
555
556 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
557
558 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600559 auto command_buffer_ai = LvlInitStruct<VkCommandBufferAllocateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700560 command_buffer_ai.commandPool = command_pool;
561 command_buffer_ai.commandBufferCount = 1;
562 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
563
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600564 result = DispatchAllocateCommandBuffers(device_gpuav->device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700565 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700566 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700567 "Failed to create command buffer for acceleration structure build validation.");
568 }
569
570 // Hook up command buffer dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600571 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700572 }
573
574 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600575 auto command_buffer_bi = LvlInitStruct<VkCommandBufferBeginInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700576
577 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
578 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700579 ReportSetupProblem(device_gpuav->device, "Failed to begin command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700580 }
581 }
582
583 if (result == VK_SUCCESS) {
584 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
585 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
586 DispatchEndCommandBuffer(command_buffer);
587 }
588
589 VkQueue queue = VK_NULL_HANDLE;
590 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600591 DispatchGetDeviceQueue(device_gpuav->device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700592
593 // Hook up queue dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600594 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700595
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600596 auto submit_info = LvlInitStruct<VkSubmitInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700597 submit_info.commandBufferCount = 1;
598 submit_info.pCommandBuffers = &command_buffer;
599 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
600 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700601 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700602 "Failed to submit command buffer for acceleration structure build validation.");
603 }
604 }
605
606 if (result == VK_SUCCESS) {
607 result = DispatchQueueWaitIdle(queue);
608 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700609 ReportSetupProblem(device_gpuav->device, "Failed to wait for queue idle for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700610 }
611 }
612
613 if (vbo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600614 vmaDestroyBuffer(device_gpuav->vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700615 }
616 if (ibo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600617 vmaDestroyBuffer(device_gpuav->vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700618 }
619 if (scratch != VK_NULL_HANDLE) {
Tony-LunarG18900282020-05-20 12:34:33 -0600620 vmaDestroyBuffer(device_gpuav->vmaAllocator, scratch, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700621 }
622 if (command_pool != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600623 DispatchDestroyCommandPool(device_gpuav->device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700624 }
625
Tony-LunarG99b880b2019-09-26 11:19:52 -0600626 if (device_gpuav->debug_desc_layout == VK_NULL_HANDLE) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700627 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700628 "Failed to find descriptor set layout for acceleration structure build validation.");
629 result = VK_INCOMPLETE;
630 }
631
632 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600633 auto pipeline_layout_ci = LvlInitStruct<VkPipelineLayoutCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700634 pipeline_layout_ci.setLayoutCount = 1;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600635 pipeline_layout_ci.pSetLayouts = &device_gpuav->debug_desc_layout;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600636 result = DispatchCreatePipelineLayout(device_gpuav->device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700637 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700638 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700639 "Failed to create pipeline layout for acceleration structure build validation.");
640 }
641 }
642
643 VkShaderModule shader_module = VK_NULL_HANDLE;
644 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600645 auto shader_module_ci = LvlInitStruct<VkShaderModuleCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700646 shader_module_ci.codeSize = sizeof(kComputeShaderSpirv);
647 shader_module_ci.pCode = (uint32_t *)kComputeShaderSpirv;
648
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600649 result = DispatchCreateShaderModule(device_gpuav->device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700650 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700651 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700652 "Failed to create compute shader module for acceleration structure build validation.");
653 }
654 }
655
656 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600657 auto pipeline_stage_ci = LvlInitStruct<VkPipelineShaderStageCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700658 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
659 pipeline_stage_ci.module = shader_module;
660 pipeline_stage_ci.pName = "main";
661
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600662 auto pipeline_ci = LvlInitStruct<VkComputePipelineCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700663 pipeline_ci.stage = pipeline_stage_ci;
664 pipeline_ci.layout = as_validation_state.pipeline_layout;
665
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600666 result = DispatchCreateComputePipelines(device_gpuav->device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr,
667 &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700668 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700669 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700670 "Failed to create compute pipeline for acceleration structure build validation.");
671 }
672 }
673
674 if (shader_module != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600675 DispatchDestroyShaderModule(device_gpuav->device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700676 }
677
678 if (result == VK_SUCCESS) {
679 as_validation_state.initialized = true;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700680 LogInfo(device_gpuav->device, "UNASSIGNED-GPU-Assisted Validation.",
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600681 "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700682 } else {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600683 device_gpuav->aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700684 }
685}
686
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600687void GpuAssisted::DestroyAccelerationStructureBuildValidationState() {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600688 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700689 if (as_validation_state.pipeline != VK_NULL_HANDLE) {
690 DispatchDestroyPipeline(device, as_validation_state.pipeline, nullptr);
691 }
692 if (as_validation_state.pipeline_layout != VK_NULL_HANDLE) {
693 DispatchDestroyPipelineLayout(device, as_validation_state.pipeline_layout, nullptr);
694 }
695 if (as_validation_state.replacement_as != VK_NULL_HANDLE) {
696 DispatchDestroyAccelerationStructureNV(device, as_validation_state.replacement_as, nullptr);
697 }
698 if (as_validation_state.replacement_as_allocation != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600699 vmaFreeMemory(vmaAllocator, as_validation_state.replacement_as_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700700 }
701}
702
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600703struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700704 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
705 VkPipeline pipeline = VK_NULL_HANDLE;
706 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
707 std::vector<VkDescriptorSet> descriptor_sets;
708 std::vector<std::vector<uint32_t>> dynamic_offsets;
709 uint32_t push_descriptor_set_index = 0;
710 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
711 std::vector<uint8_t> push_constants_data;
712 PushConstantRangesId push_constants_ranges;
713
714 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
715 pipeline_bind_point = bind_point;
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600716 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
Jason Macnak83cfd582019-07-31 10:14:24 -0700717
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600718 LAST_BOUND_STATE &last_bound = cb_state->lastBound[lv_bind_point];
Jason Macnak83cfd582019-07-31 10:14:24 -0700719 if (last_bound.pipeline_state) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600720 pipeline = last_bound.pipeline_state->pipeline();
Jason Macnak83cfd582019-07-31 10:14:24 -0700721 pipeline_layout = last_bound.pipeline_layout;
722 descriptor_sets.reserve(last_bound.per_set.size());
723 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
724 const auto *bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
725
726 descriptor_sets.push_back(bound_descriptor_set->GetSet());
727 if (bound_descriptor_set->IsPushDescriptor()) {
728 push_descriptor_set_index = static_cast<uint32_t>(i);
729 }
730 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
731 }
732
733 if (last_bound.push_descriptor_set) {
734 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
735 }
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500736 if (last_bound.pipeline_state->pipeline_layout->push_constant_ranges == cb_state->push_constant_data_ranges) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700737 push_constants_data = cb_state->push_constant_data;
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500738 push_constants_ranges = last_bound.pipeline_state->pipeline_layout->push_constant_ranges;
Jason Macnak83cfd582019-07-31 10:14:24 -0700739 }
740 }
741 }
742
743 void Restore(VkCommandBuffer command_buffer) const {
744 if (pipeline != VK_NULL_HANDLE) {
745 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
746 if (!descriptor_sets.empty()) {
747 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
748 VkDescriptorSet descriptor_set = descriptor_sets[i];
749 if (descriptor_set != VK_NULL_HANDLE) {
750 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
751 static_cast<uint32_t>(i), 1, &descriptor_set,
752 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
753 }
754 }
755 }
756 if (!push_descriptor_set_writes.empty()) {
757 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
758 static_cast<uint32_t>(push_descriptor_set_writes.size()),
759 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
760 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600761 if (!push_constants_data.empty()) {
762 for (const auto &push_constant_range : *push_constants_ranges) {
763 if (push_constant_range.size == 0) continue;
764 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
765 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
766 }
Jason Macnak83cfd582019-07-31 10:14:24 -0700767 }
768 }
769 }
770};
771
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600772void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
773 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
774 VkDeviceSize instanceOffset, VkBool32 update,
775 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
776 VkBuffer scratch, VkDeviceSize scratchOffset) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700777 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
778 return;
779 }
780
Tony-LunarG99b880b2019-09-26 11:19:52 -0600781 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700782 if (!as_validation_state.initialized) {
783 return;
784 }
785
786 // Empty acceleration structure is valid according to the spec.
787 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
788 return;
789 }
790
791 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
792 assert(cb_state != nullptr);
793
794 std::vector<uint64_t> current_valid_handles;
795 for (const auto &as_state_kv : accelerationStructureMap) {
796 const ACCELERATION_STRUCTURE_STATE &as_state = *as_state_kv.second;
Jeff Bolz95176d02020-04-01 00:36:16 -0500797 if (as_state.built && as_state.create_infoNV.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700798 current_valid_handles.push_back(as_state.opaque_handle);
799 }
800 }
801
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600802 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700803 as_validation_buffer_info.acceleration_structure = dst;
804
805 const VkDeviceSize validation_buffer_size =
806 // One uint for number of instances to validate
807 4 +
808 // Two uint for the replacement acceleration structure handle
809 8 +
810 // One uint for number of invalid handles found
811 4 +
812 // Two uint for the first invalid handle found
813 8 +
814 // One uint for the number of current valid handles
815 4 +
816 // Two uint for each current valid handle
817 (8 * current_valid_handles.size());
818
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600819 auto validation_buffer_create_info = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700820 validation_buffer_create_info.size = validation_buffer_size;
821 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
822
823 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
824 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
825
Tony-LunarG99b880b2019-09-26 11:19:52 -0600826 VkResult result = vmaCreateBuffer(vmaAllocator, &validation_buffer_create_info, &validation_buffer_alloc_info,
827 &as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -0700828 &as_validation_buffer_info.validation_buffer_allocation, nullptr);
829 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700830 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600831 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700832 return;
833 }
834
835 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700836 result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation,
837 reinterpret_cast<void **>(&mapped_validation_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700838 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700839 ReportSetupProblem(device, "Unable to allocate device memory for acceleration structure build val buffer.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600840 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700841 return;
842 }
843
844 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
845 mapped_validation_buffer->replacement_handle_bits_0 =
846 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
847 mapped_validation_buffer->replacement_handle_bits_1 =
848 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
849 mapped_validation_buffer->invalid_handle_found = 0;
850 mapped_validation_buffer->invalid_handle_bits_0 = 0;
851 mapped_validation_buffer->invalid_handle_bits_1 = 0;
852 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
853
854 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
855 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
856 const uint64_t current_valid_handle = current_valid_handles[i];
857
858 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
859 ++mapped_valid_handles;
860 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
861 ++mapped_valid_handles;
862 }
863
Tony-LunarG99b880b2019-09-26 11:19:52 -0600864 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700865
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700866 static constexpr const VkDeviceSize k_instance_size = 64;
867 const VkDeviceSize instance_buffer_size = k_instance_size * pInfo->instanceCount;
Jason Macnak83cfd582019-07-31 10:14:24 -0700868
Tony-LunarG1dce2392019-10-23 16:49:29 -0600869 result = desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool, debug_desc_layout,
870 &as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700871 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700872 ReportSetupProblem(device, "Unable to get descriptor set for acceleration structure build.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600873 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700874 return;
875 }
876
877 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
878 descriptor_buffer_infos[0].buffer = instanceData;
879 descriptor_buffer_infos[0].offset = instanceOffset;
880 descriptor_buffer_infos[0].range = instance_buffer_size;
881 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.validation_buffer;
882 descriptor_buffer_infos[1].offset = 0;
883 descriptor_buffer_infos[1].range = validation_buffer_size;
884
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600885 VkWriteDescriptorSet descriptor_set_writes[2] = {
886 LvlInitStruct<VkWriteDescriptorSet>(),
887 LvlInitStruct<VkWriteDescriptorSet>(),
888 };
Jason Macnak83cfd582019-07-31 10:14:24 -0700889 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
890 descriptor_set_writes[0].dstBinding = 0;
891 descriptor_set_writes[0].descriptorCount = 1;
892 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
893 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
Jason Macnak83cfd582019-07-31 10:14:24 -0700894 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
895 descriptor_set_writes[1].dstBinding = 1;
896 descriptor_set_writes[1].descriptorCount = 1;
897 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
898 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
899
900 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
901
902 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600903 auto memory_barrier = LvlInitStruct<VkMemoryBarrier>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700904 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
905 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
906 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
907 &memory_barrier, 0, nullptr, 0, nullptr);
908
909 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600910 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700911 restorable_state.Create(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
912
913 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
914 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
915 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
916 &as_validation_buffer_info.descriptor_set, 0, nullptr);
917 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
918
919 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
920 // have been replaced by the validation compute shader before any builds take place.
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600921 auto instance_buffer_barrier = LvlInitStruct<VkBufferMemoryBarrier>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700922 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
923 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
924 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
925 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
926 instance_buffer_barrier.buffer = instanceData;
927 instance_buffer_barrier.offset = instanceOffset;
928 instance_buffer_barrier.size = instance_buffer_size;
929 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
930 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
931 nullptr);
932
933 // Restore the previous compute pipeline state.
934 restorable_state.Restore(commandBuffer);
935
936 as_validation_state.validation_buffers[commandBuffer].push_back(std::move(as_validation_buffer_info));
937}
938
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600939void GpuAssisted::ProcessAccelerationStructureBuildValidationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700940 if (cb_node == nullptr || !cb_node->hasBuildAccelerationStructureCmd) {
941 return;
942 }
943
Tony-LunarG99b880b2019-09-26 11:19:52 -0600944 auto &as_validation_info = acceleration_structure_validation_state;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600945 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[cb_node->commandBuffer()];
Jason Macnak83cfd582019-07-31 10:14:24 -0700946 for (const auto &as_validation_buffer_info : as_validation_buffer_infos) {
947 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
948
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700949 VkResult result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation,
950 reinterpret_cast<void **>(&mapped_validation_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700951 if (result == VK_SUCCESS) {
952 if (mapped_validation_buffer->invalid_handle_found > 0) {
953 uint64_t invalid_handle = 0;
954 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
955 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
956
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700957 LogError(as_validation_buffer_info.acceleration_structure, "UNASSIGNED-AccelerationStructure",
958 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
959 "handle (%" PRIu64 ")",
960 invalid_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700961 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600962 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700963 }
964 }
965}
966
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600967void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
968 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
969 VkResult result) {
970 if (VK_SUCCESS != result) return;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600971 ValidationStateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600972 for (uint32_t i = 0; i < bindInfoCount; i++) {
973 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
sourav parmarcd5fb182020-07-17 12:58:44 -0700974 ACCELERATION_STRUCTURE_STATE *as_state = GetAccelerationStructureStateNV(info.accelerationStructure);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600975 if (as_state) {
976 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
977 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600978 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600979}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700980
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600981// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
982void GpuAssisted::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
983 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
984 void *cpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600985 if (aborted) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600986 return;
987 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600988
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600989 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
990
Tony-LunarG99b880b2019-09-26 11:19:52 -0600991 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600992 std::ostringstream strm;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600993 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Karl Schultz7b024b42018-08-30 16:18:18 -0600994 << "Application has too many descriptor sets in the pipeline layout to continue with gpu validation. "
995 << "Validation is not modifying the pipeline layout. "
996 << "Instrumented shaders are replaced with non-instrumented shaders.";
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700997 ReportSetupProblem(device, strm.str().c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -0600998 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700999 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Karl Schultz7b024b42018-08-30 16:18:18 -06001000 }
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -07001001}
1002
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001003void GpuAssisted::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
1004 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
1005 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001006 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1007
Karl Schultz7b024b42018-08-30 16:18:18 -06001008 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001009 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001010 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -06001011 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001012}
1013
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001014// Free the device memory and descriptor set(s) associated with a command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001015void GpuAssisted::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001016 if (aborted) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001017 return;
1018 }
Tony-LunarG1dce2392019-10-23 16:49:29 -06001019 auto gpuav_buffer_list = GetBufferInfo(commandBuffer);
John Zulauf79f06582021-02-27 18:38:39 -07001020 for (const auto &buffer_info : gpuav_buffer_list) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001021 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001022 if (buffer_info.di_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001023 vmaDestroyBuffer(vmaAllocator, buffer_info.di_input_mem_block.buffer, buffer_info.di_input_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001024 }
1025 if (buffer_info.bda_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001026 vmaDestroyBuffer(vmaAllocator, buffer_info.bda_input_mem_block.buffer, buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -06001027 }
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001028 if (buffer_info.desc_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001029 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001030 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001031 if (buffer_info.pre_draw_resources.desc_set != VK_NULL_HANDLE) {
1032 desc_set_manager->PutBackDescriptorSet(buffer_info.pre_draw_resources.desc_pool,
1033 buffer_info.pre_draw_resources.desc_set);
1034 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001035 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001036 command_buffer_map.erase(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001037
Tony-LunarG99b880b2019-09-26 11:19:52 -06001038 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001039 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[commandBuffer];
1040 for (auto &as_validation_buffer_info : as_validation_buffer_infos) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001041 vmaDestroyBuffer(vmaAllocator, as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -07001042 as_validation_buffer_info.validation_buffer_allocation);
1043
1044 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001045 desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool,
1046 as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -07001047 }
1048 }
1049 as_validation_info.validation_buffers.erase(commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -06001050}
Karl Schultz7b024b42018-08-30 16:18:18 -06001051// Just gives a warning about a possible deadlock.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001052bool GpuAssisted::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
1053 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
1054 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1055 uint32_t bufferMemoryBarrierCount,
1056 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
Jeff Bolz5c801d12019-10-09 10:38:45 -05001057 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001058 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001059 ReportSetupProblem(commandBuffer,
Karl Schultz7b024b42018-08-30 16:18:18 -06001060 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1061 "GPU_Assisted validation waits on queue completion. "
1062 "This wait could block the host's signaling of this event, resulting in deadlock.");
1063 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001064 return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001065}
1066
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001067bool GpuAssisted::PreCallValidateCmdWaitEvents2KHR(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
1068 const VkDependencyInfoKHR *pDependencyInfos) const {
1069 VkPipelineStageFlags2KHR srcStageMask = 0;
1070
1071 for (uint32_t i = 0; i < eventCount; i++) {
1072 auto stage_masks = sync_utils::GetGlobalStageMasks(pDependencyInfos[i]);
1073 srcStageMask = stage_masks.src;
1074 }
1075
1076 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
1077 ReportSetupProblem(commandBuffer,
1078 "CmdWaitEvents2KHR recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1079 "GPU_Assisted validation waits on queue completion. "
1080 "This wait could block the host's signaling of this event, resulting in deadlock.");
1081 }
1082 return false;
1083}
1084
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001085void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1086 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
1087 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -06001088 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001089 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
1090 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
1091 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001092 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1093 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001094 }
1095 }
1096}
1097
1098void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1099 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
1100 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -06001101 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001102 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
1103 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
1104 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001105 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1106 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001107 }
1108 }
1109}
1110
1111void GpuAssisted::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1112 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1113 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1114 void *cgpl_state_data) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001115 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001116 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001117 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
1118 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001119 cgpl_state->gpu_create_infos = new_pipeline_create_infos;
1120 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001121}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001122
1123void GpuAssisted::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1124 const VkComputePipelineCreateInfo *pCreateInfos,
1125 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1126 void *ccpl_state_data) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001127 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001128 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001129 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
1130 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001131 ccpl_state->gpu_create_infos = new_pipeline_create_infos;
1132 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
Jason Macnak67407e72019-07-11 11:05:09 -07001133}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001134
1135void GpuAssisted::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1136 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1137 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1138 void *crtpl_state_data) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001139 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001140 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001141 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1142 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001143 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1144 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001145}
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001146
sourav parmarcd5fb182020-07-17 12:58:44 -07001147void GpuAssisted::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
1148 VkPipelineCache pipelineCache, uint32_t count,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001149 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1150 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1151 void *crtpl_state_data) {
1152 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
1153 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001154 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1155 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001156 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1157 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->gpu_create_infos.data());
1158}
Karl Schultz7b024b42018-08-30 16:18:18 -06001159
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001160void GpuAssisted::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1161 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1162 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1163 VkResult result, void *cgpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001164 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
1165 pPipelines, result, cgpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001166 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
1167 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, cgpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001168 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001169}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001170
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001171void GpuAssisted::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1172 const VkComputePipelineCreateInfo *pCreateInfos,
1173 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1174 VkResult result, void *ccpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001175 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1176 result, ccpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001177 create_compute_pipeline_api_state *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
1178 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, ccpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001179 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001180}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001181
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001182void GpuAssisted::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1183 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1184 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1185 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001186 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001187 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
1188 pPipelines, result, crtpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001189 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001190 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Jason Macnak67407e72019-07-11 11:05:09 -07001191}
1192
sourav parmarcd5fb182020-07-17 12:58:44 -07001193void GpuAssisted::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
1194 VkPipelineCache pipelineCache, uint32_t count,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001195 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1196 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1197 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001198 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
sourav parmarcd5fb182020-07-17 12:58:44 -07001199 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesKHR(
1200 device, deferredOperation, pipelineCache, count, pCreateInfos, pAllocator, pPipelines, result, crtpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001201 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001202 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Karl Schultz7b024b42018-08-30 16:18:18 -06001203}
1204
1205// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001206void GpuAssisted::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001207 for (auto it = shader_map.begin(); it != shader_map.end();) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001208 if (it->second.pipeline == pipeline) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001209 it = shader_map.erase(it);
Karl Schultz7b024b42018-08-30 16:18:18 -06001210 } else {
1211 ++it;
1212 }
1213 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001214 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001215}
1216
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001217void GpuAssisted::PreCallRecordDestroyRenderPass(VkDevice device, VkRenderPass renderPass,
1218 const VkAllocationCallbacks *pAllocator) {
1219 auto pipeline = pre_draw_validation_state.renderpass_to_pipeline.find(renderPass);
1220 if (pipeline != pre_draw_validation_state.renderpass_to_pipeline.end()) {
1221 DispatchDestroyPipeline(device, pipeline->second, nullptr);
1222 pre_draw_validation_state.renderpass_to_pipeline.erase(pipeline);
1223 }
1224}
1225
Karl Schultz7b024b42018-08-30 16:18:18 -06001226// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001227bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
1228 uint32_t *unique_shader_id) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001229 if (aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001230 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
1231
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001232 const spvtools::MessageConsumer gpu_console_message_consumer =
Tony-LunarG79641702020-07-13 15:43:05 -06001233 [this](spv_message_level_t level, const char *, const spv_position_t &position, const char *message) -> void {
1234 switch (level) {
1235 case SPV_MSG_FATAL:
1236 case SPV_MSG_INTERNAL_ERROR:
1237 case SPV_MSG_ERROR:
1238 this->LogError(this->device, "UNASSIGNED-GPU-Assisted", "Error during shader instrumentation: line %zu: %s",
1239 position.index, message);
1240 break;
1241 default:
1242 break;
1243 }
1244 };
1245
Karl Schultz7b024b42018-08-30 16:18:18 -06001246 // Load original shader SPIR-V
1247 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
1248 new_pgm.clear();
1249 new_pgm.reserve(num_words);
1250 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
1251
1252 // Call the optimizer to instrument the shader.
1253 // 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 -07001254 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Karl Schultz7b024b42018-08-30 16:18:18 -06001255 using namespace spvtools;
Tony-LunarG8a51b7d2020-07-01 15:57:23 -06001256 spv_target_env target_env = PickSpirvEnv(api_version, (device_extensions.vk_khr_spirv_1_4 != kNotEnabled));
Tony-LunarGf29f77f2020-08-26 15:48:00 -06001257 spvtools::ValidatorOptions val_options;
1258 AdjustValidatorOptions(device_extensions, enabled_features, val_options);
1259 spvtools::OptimizerOptions opt_options;
1260 opt_options.set_run_validator(true);
1261 opt_options.set_validator_options(val_options);
Karl Schultz7b024b42018-08-30 16:18:18 -06001262 Optimizer optimizer(target_env);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001263 optimizer.SetMessageConsumer(gpu_console_message_consumer);
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001264 optimizer.RegisterPass(CreateInstBindlessCheckPass(desc_set_bind_index, unique_shader_module_id, descriptor_indexing,
Tony-LunarGe8632e42020-11-18 17:03:12 -07001265 descriptor_indexing, buffer_oob_enabled, buffer_oob_enabled));
Karl Schultz7b024b42018-08-30 16:18:18 -06001266 optimizer.RegisterPass(CreateAggressiveDCEPass());
Tony-LunarG5c38b182020-06-10 16:15:32 -06001267 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) && shaderInt64 &&
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001268 enabled_features.core12.bufferDeviceAddress) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001269 optimizer.RegisterPass(CreateInstBuffAddrCheckPass(desc_set_bind_index, unique_shader_module_id));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001270 }
Tony-LunarGf29f77f2020-08-26 15:48:00 -06001271 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm, opt_options);
Karl Schultz7b024b42018-08-30 16:18:18 -06001272 if (!pass) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001273 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Karl Schultz7b024b42018-08-30 16:18:18 -06001274 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001275 *unique_shader_id = unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -06001276 return pass;
1277}
Mark Lobodzinski01734072019-02-13 17:39:15 -07001278// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001279void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
1280 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
1281 void *csm_state_data) {
1282 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
1283 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -06001284 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001285 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
1286 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
Karl Schultz7b024b42018-08-30 16:18:18 -06001287 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001288}
Tony-LunarG20678ff2021-05-07 14:56:26 -06001289
Tony-LunarG7345a062021-06-24 13:16:38 -06001290static const int kInstErrorPreDrawValidate = spvtools::kInstErrorMax + 1;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001291static const int kPreDrawValidateSubError = spvtools::kInstValidationOutError + 1;
Karl Schultz7b024b42018-08-30 16:18:18 -06001292// Generate the part of the message describing the violation.
Tony-LunarG1a7c9f92021-04-29 16:04:42 -06001293bool GenerateValidationMessage(const uint32_t *debug_record, std::string &msg, std::string &vuid_msg, GpuAssistedBufferInfo buf_info, GpuAssisted *gpu_assisted) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001294 using namespace spvtools;
1295 std::ostringstream strm;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001296 bool return_code = true;
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001297 assert(kInstErrorPreDrawValidate == _kInstErrorPreDrawValidate);
1298 assert(kInstValidationOutError == _kInstValidationOutError);
Tony-LunarGab47cac2019-12-20 15:28:01 -07001299 switch (debug_record[kInstValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001300 case kInstErrorBindlessBounds: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001301 strm << "Index of " << debug_record[kInstBindlessBoundsOutDescIndex] << " used to index descriptor array of length "
1302 << debug_record[kInstBindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001303 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -06001304 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001305 case kInstErrorBindlessUninit: {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001306 strm << "Descriptor index " << debug_record[kInstBindlessUninitOutDescIndex] << " is uninitialized.";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001307 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -06001308 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001309 case kInstErrorBuffAddrUnallocRef: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001310 uint64_t *ptr = (uint64_t *)&debug_record[kInstBuffAddrUnallocOutDescPtrLo];
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001311 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
1312 vuid_msg = "UNASSIGNED-Device address out of bounds";
1313 } break;
Tony-LunarG7de10e82020-11-24 11:31:55 -07001314 case kInstErrorBuffOOBUniform:
1315 case kInstErrorBuffOOBStorage: {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001316 auto size = debug_record[kInstBindlessBuffOOBOutBuffSize];
1317 if (size == 0) {
1318 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex] << " is uninitialized.";
1319 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
1320 } else {
1321 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex]
1322 << " access out of bounds. Descriptor size is " << debug_record[kInstBindlessBuffOOBOutBuffSize]
Tony-LunarG7de10e82020-11-24 11:31:55 -07001323 << " and highest byte accessed was " << debug_record[kInstBindlessBuffOOBOutBuffOff];
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001324 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001325 if (debug_record[kInstValidationOutError] == kInstErrorBuffOOBUniform)
1326 vuid_msg = vuid.uniform_access_oob;
1327 else
1328 vuid_msg = vuid.storage_access_oob;
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001329 }
1330 } break;
Tony-LunarG7de10e82020-11-24 11:31:55 -07001331 case kInstErrorBuffOOBUniformTexel:
1332 case kInstErrorBuffOOBStorageTexel: {
1333 auto size = debug_record[kInstBindlessBuffOOBOutBuffSize];
1334 if (size == 0) {
1335 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex] << " is uninitialized.";
1336 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001337 } else {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001338 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex]
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001339 << " access out of bounds. Descriptor size is " << debug_record[kInstBindlessBuffOOBOutBuffSize]
1340 << " texels and highest texel accessed was " << debug_record[kInstBindlessBuffOOBOutBuffOff];
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001341 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001342 if (debug_record[kInstValidationOutError] == kInstErrorBuffOOBUniformTexel)
1343 vuid_msg = vuid.uniform_access_oob;
1344 else
1345 vuid_msg = vuid.storage_access_oob;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001346 }
Tony-LunarG63f82e02021-04-12 16:13:48 -06001347 } break;
1348 case kInstErrorPreDrawValidate: {
Tim Van Patten38bdcdd2021-05-14 16:41:00 -06001349 // Buffer size must be >= (stride * (drawCount - 1) + offset + sizeof(VkDrawIndexedIndirectCommand))
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001350 if (debug_record[kPreDrawValidateSubError] == pre_draw_count_exceeds_bufsize_error) {
Tony-LunarG63f82e02021-04-12 16:13:48 -06001351 uint32_t count = debug_record[kPreDrawValidateSubError + 1];
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001352 uint32_t stride = buf_info.pre_draw_resources.stride;
1353 uint32_t offset = static_cast<uint32_t>(buf_info.pre_draw_resources.offset);
1354 uint32_t draw_size = (stride * (count - 1) + offset + sizeof(VkDrawIndexedIndirectCommand));
1355 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
1356 strm << "Indirect draw count of " << count << " would exceed buffer size " << buf_info.pre_draw_resources.buf_size
1357 << " of buffer " << buf_info.pre_draw_resources.buffer << " stride = " << stride << " offset = " << offset
1358 << " (stride * (drawCount - 1) + offset + sizeof(VkDrawIndexedIndirectCommand)) = " << draw_size;
Tony-LunarG64aeaf72021-04-14 11:13:35 -06001359 if (count == 1) {
1360 vuid_msg = vuid.count_exceeds_bufsize_1;
1361 } else {
1362 vuid_msg = vuid.count_exceeds_bufsize;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001363 }
Tony-LunarG1a7c9f92021-04-29 16:04:42 -06001364 } else if (debug_record[kPreDrawValidateSubError] == pre_draw_count_exceeds_limit_error) {
1365 uint32_t count = debug_record[kPreDrawValidateSubError + 1];
1366 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
1367 strm << "Indirect draw count of " << count << " would exceed maxDrawIndirectCount limit of "
1368 << gpu_assisted->phys_dev_props.limits.maxDrawIndirectCount;
1369 vuid_msg = vuid.count_exceeds_device_limit;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001370 } else if (debug_record[kPreDrawValidateSubError] == pre_draw_first_instance_error) {
1371 uint32_t index = debug_record[kPreDrawValidateSubError + 1];
1372 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
1373 strm << "The drawIndirectFirstInstance feature is not enabled, but the firstInstance member of the "
1374 "VkDrawIndirectCommand structure at index "
1375 << index << " is not zero";
1376 vuid_msg = vuid.first_instance_not_zero;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001377 }
1378 return_code = false;
1379 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001380 default: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001381 strm << "Internal Error (unexpected error type = " << debug_record[kInstValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001382 vuid_msg = "UNASSIGNED-Internal Error";
1383 assert(false);
1384 } break;
1385 }
1386 msg = strm.str();
Tony-LunarG63f82e02021-04-12 16:13:48 -06001387 return return_code;
Karl Schultz7b024b42018-08-30 16:18:18 -06001388}
1389
Karl Schultz7b024b42018-08-30 16:18:18 -06001390// Pull together all the information from the debug record to build the error message strings,
1391// and then assemble them into a single message string.
1392// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
1393// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
1394// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
1395// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
1396//
Tony-LunarG7de10e82020-11-24 11:31:55 -07001397void GpuAssisted::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, GpuAssistedBufferInfo &buffer_info,
Tony-LunarG1dce2392019-10-23 16:49:29 -06001398 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001399 using namespace spvtools;
1400 const uint32_t total_words = debug_output_buffer[0];
1401 // A zero here means that the shader instrumentation didn't write anything.
1402 // If you have nothing to say, don't say it here.
1403 if (0 == total_words) {
1404 return;
1405 }
1406 // The first word in the debug output buffer is the number of words that would have
1407 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
1408 // The number of words actually written by the shaders is determined by the size of the buffer
1409 // we provide via the descriptor. So, we process only the number of words that can fit in the
1410 // buffer.
1411 // Each "report" written by the shader instrumentation is considered a "record". This function
1412 // is hard-coded to process only one record because it expects the buffer to be large enough to
1413 // hold only one record. If there is a desire to process more than one record, this function needs
1414 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06001415 std::string validation_message;
1416 std::string stage_message;
1417 std::string common_message;
1418 std::string filename_message;
1419 std::string source_message;
1420 std::string vuid_msg;
1421 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
1422 VkPipeline pipeline_handle = VK_NULL_HANDLE;
1423 std::vector<unsigned int> pgm;
1424 // The first record starts at this offset after the total_words.
1425 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
1426 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
1427 // by the instrumented shader.
Tony-LunarG99b880b2019-09-26 11:19:52 -06001428 auto it = shader_map.find(debug_record[kInstCommonOutShaderId]);
1429 if (it != shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001430 shader_module_handle = it->second.shader_module;
1431 pipeline_handle = it->second.pipeline;
1432 pgm = it->second.pgm;
1433 }
Tony-LunarG1a7c9f92021-04-29 16:04:42 -06001434 bool gen_full_message = GenerateValidationMessage(debug_record, validation_message, vuid_msg, buffer_info, this);
Tony-LunarG63f82e02021-04-12 16:13:48 -06001435 if (gen_full_message) {
1436 UtilGenerateStageMessage(debug_record, stage_message);
1437 UtilGenerateCommonMessage(report_data, command_buffer, debug_record, shader_module_handle, pipeline_handle,
1438 buffer_info.pipeline_bind_point, operation_index, common_message);
1439 UtilGenerateSourceMessages(pgm, debug_record, false, filename_message, source_message);
1440 LogError(queue, vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
1441 filename_message.c_str(), source_message.c_str());
1442 }
1443 else {
1444 LogError(queue, vuid_msg.c_str(), "%s", validation_message.c_str());
1445 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001446 // The debug record at word kInstCommonOutSize is the number of words in the record
1447 // written by the shader. Clear the entire record plus the total_words word at the start.
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001448 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], static_cast<uint32_t>(kInstMaxOutCnt));
Karl Schultz7b024b42018-08-30 16:18:18 -06001449 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
1450}
1451
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001452void GpuAssisted::SetDescriptorInitialized(uint32_t *pData, uint32_t index, const cvdescriptorset::Descriptor *descriptor) {
1453 if (descriptor->GetClass() == cvdescriptorset::DescriptorClass::GeneralBuffer) {
1454 auto buffer = static_cast<const cvdescriptorset::BufferDescriptor *>(descriptor)->GetBuffer();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001455 if (buffer == VK_NULL_HANDLE) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001456 pData[index] = UINT_MAX;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001457 } else {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001458 auto buffer_state = static_cast<const cvdescriptorset::BufferDescriptor *>(descriptor)->GetBufferState();
1459 pData[index] = static_cast<uint32_t>(buffer_state->createInfo.size);
1460 }
1461 } else if (descriptor->GetClass() == cvdescriptorset::DescriptorClass::TexelBuffer) {
1462 auto buffer_view = static_cast<const cvdescriptorset::TexelDescriptor *>(descriptor)->GetBufferView();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001463 if (buffer_view == VK_NULL_HANDLE) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001464 pData[index] = UINT_MAX;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001465 } else {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001466 auto buffer_view_state = static_cast<const cvdescriptorset::TexelDescriptor *>(descriptor)->GetBufferViewState();
1467 pData[index] = static_cast<uint32_t>(buffer_view_state->buffer_state->createInfo.size);
1468 }
1469 } else {
1470 pData[index] = 1;
1471 }
1472}
1473
Tony-LunarG81efe392019-03-07 15:43:27 -07001474// 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 -06001475void GpuAssisted::UpdateInstrumentationBuffer(CMD_BUFFER_STATE *cb_node) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001476 auto gpu_buffer_list = GetBufferInfo(cb_node->commandBuffer());
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001477 uint32_t *data;
Tony-LunarG81efe392019-03-07 15:43:27 -07001478 for (auto &buffer_info : gpu_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001479 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001480 VkResult result =
1481 vmaMapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation, reinterpret_cast<void **>(&data));
Tony-LunarG81efe392019-03-07 15:43:27 -07001482 if (result == VK_SUCCESS) {
John Zulauf79f06582021-02-27 18:38:39 -07001483 for (const auto &update : buffer_info.di_input_mem_block.update_at_submit) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001484 if (update.second->updated) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001485 SetDescriptorInitialized(data, update.first, update.second);
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001486 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001487 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001488 vmaUnmapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07001489 }
1490 }
1491 }
1492}
1493
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001494void GpuAssisted::PreRecordCommandBuffer(VkCommandBuffer command_buffer) {
1495 auto cb_node = GetCBState(command_buffer);
1496 UpdateInstrumentationBuffer(cb_node);
John Zulauf79f06582021-02-27 18:38:39 -07001497 for (auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001498 UpdateInstrumentationBuffer(secondary_cmd_buffer);
1499 }
1500}
1501
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001502void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001503 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1504 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1505 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001506 PreRecordCommandBuffer(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07001507 }
1508 }
1509}
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001510void GpuAssisted::PreCallRecordQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR *pSubmits,
1511 VkFence fence) {
1512 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1513 const VkSubmitInfo2KHR *submit = &pSubmits[submit_idx];
1514 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
1515 PreRecordCommandBuffer(submit->pCommandBufferInfos[i].commandBuffer);
1516 }
1517 }
1518}
1519
1520bool GpuAssisted::CommandBufferNeedsProcessing(VkCommandBuffer command_buffer) {
1521 bool buffers_present = false;
1522 auto cb_node = GetCBState(command_buffer);
1523
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001524 if (GetBufferInfo(cb_node->commandBuffer()).size() || cb_node->hasBuildAccelerationStructureCmd) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001525 buffers_present = true;
1526 }
John Zulauf79f06582021-02-27 18:38:39 -07001527 for (const auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001528 if (GetBufferInfo(secondary_cmd_buffer->commandBuffer()).size() || cb_node->hasBuildAccelerationStructureCmd) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001529 buffers_present = true;
1530 }
1531 }
1532 return buffers_present;
1533}
1534
1535void GpuAssisted::ProcessCommandBuffer(VkQueue queue, VkCommandBuffer command_buffer) {
1536 auto cb_node = GetCBState(command_buffer);
1537
1538 UtilProcessInstrumentationBuffer(queue, cb_node, this);
1539 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
John Zulauf79f06582021-02-27 18:38:39 -07001540 for (auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001541 UtilProcessInstrumentationBuffer(queue, secondary_cmd_buffer, this);
1542 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
1543 }
1544}
Tony-LunarG81efe392019-03-07 15:43:27 -07001545
Karl Schultz58674242019-01-22 15:35:02 -07001546// Issue a memory barrier to make GPU-written data available to host.
1547// Wait for the queue to complete execution.
1548// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001549void GpuAssisted::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
1550 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001551 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001552
Mark Lobodzinski09379db2020-05-07 08:22:01 -06001553 if (aborted || (result != VK_SUCCESS)) return;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001554 bool buffers_present = false;
1555 // Don't QueueWaitIdle if there's nothing to process
1556 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1557 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1558 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001559 buffers_present |= CommandBufferNeedsProcessing(submit->pCommandBuffers[i]);
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001560 }
1561 }
1562 if (!buffers_present) return;
Karl Schultz58674242019-01-22 15:35:02 -07001563
Tony-LunarGb5fae462020-03-05 12:43:25 -07001564 UtilSubmitBarrier(queue, this);
Karl Schultz58674242019-01-22 15:35:02 -07001565
Tony-LunarG152a88b2019-03-20 15:42:24 -06001566 DispatchQueueWaitIdle(queue);
Karl Schultz58674242019-01-22 15:35:02 -07001567
Karl Schultz7b024b42018-08-30 16:18:18 -06001568 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1569 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1570 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001571 ProcessCommandBuffer(queue, submit->pCommandBuffers[i]);
1572 }
1573 }
1574}
1575
1576void GpuAssisted::PostCallRecordQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR *pSubmits,
1577 VkFence fence, VkResult result) {
1578 ValidationStateTracker::PostCallRecordQueueSubmit2KHR(queue, submitCount, pSubmits, fence, result);
1579
1580 if (aborted || (result != VK_SUCCESS)) return;
1581 bool buffers_present = false;
1582 // Don't QueueWaitIdle if there's nothing to process
1583 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1584 const VkSubmitInfo2KHR *submit = &pSubmits[submit_idx];
1585 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
1586 buffers_present |= CommandBufferNeedsProcessing(submit->pCommandBufferInfos[i].commandBuffer);
1587 }
1588 }
1589 if (!buffers_present) return;
1590
1591 UtilSubmitBarrier(queue, this);
1592
1593 DispatchQueueWaitIdle(queue);
1594
1595 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1596 const VkSubmitInfo2KHR *submit = &pSubmits[submit_idx];
1597 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
1598 ProcessCommandBuffer(queue, submit->pCommandBufferInfos[i].commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -06001599 }
1600 }
1601}
Tony-LunarGb2501d22019-01-28 09:59:13 -07001602
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001603void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
1604 uint32_t firstVertex, uint32_t firstInstance) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001605 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAW);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001606}
1607
1608void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
1609 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001610 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXED);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001611}
1612
1613void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
1614 uint32_t stride) {
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001615 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, count, stride, 0, 0};
1616 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECT, &cdi_state);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001617}
1618
1619void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1620 uint32_t count, uint32_t stride) {
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001621 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, count, stride, 0, 0};
1622 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECT, &cdi_state);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001623}
1624
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001625void GpuAssisted::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1626 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1627 uint32_t stride) {
1628 ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1629 maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001630 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1631 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTCOUNT, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001632}
1633
1634void GpuAssisted::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1635 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001636
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001637 uint32_t stride) {
1638 ValidationStateTracker::PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1639 maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001640 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1641 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTCOUNT, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001642}
1643
Tony-LunarG54176fb2020-12-02 10:47:22 -07001644void GpuAssisted::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
1645 uint32_t firstInstance, VkBuffer counterBuffer,
1646 VkDeviceSize counterBufferOffset, uint32_t counterOffset,
1647 uint32_t vertexStride) {
1648 ValidationStateTracker::PreCallRecordCmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer,
1649 counterBufferOffset, counterOffset, vertexStride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001650 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTBYTECOUNTEXT);
Tony-LunarG54176fb2020-12-02 10:47:22 -07001651}
1652
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001653void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1654 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1655 uint32_t maxDrawCount, uint32_t stride) {
1656 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer,
1657 countBufferOffset, maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001658 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1659 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECTCOUNT, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001660}
1661
1662void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1663 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1664 uint32_t maxDrawCount, uint32_t stride) {
1665 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1666 maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001667 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1668 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECTCOUNT, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001669}
1670
1671void GpuAssisted::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
1672 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001673 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001674}
1675
1676void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1677 uint32_t drawCount, uint32_t stride) {
1678 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001679 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSINDIRECTNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001680}
1681
1682void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1683 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1684 uint32_t maxDrawCount, uint32_t stride) {
1685 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer,
1686 countBufferOffset, maxDrawCount, stride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001687 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSINDIRECTCOUNTNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001688}
1689
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001690void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001691 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCH);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001692}
1693
1694void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001695 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHINDIRECT);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001696}
1697
Tony-LunarGd13f9b52020-09-08 15:45:45 -06001698void GpuAssisted::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1699 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1700 uint32_t groupCountZ) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001701 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHBASE);
Tony-LunarGd13f9b52020-09-08 15:45:45 -06001702}
1703
Tony-LunarG52c8c602020-09-10 16:29:56 -06001704void GpuAssisted::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1705 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1706 uint32_t groupCountZ) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001707 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHBASE);
Tony-LunarG52c8c602020-09-10 16:29:56 -06001708}
1709
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001710void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1711 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1712 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1713 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1714 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1715 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1716 uint32_t width, uint32_t height, uint32_t depth) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001717 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, CMD_TRACERAYSNV);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001718}
1719
1720void GpuAssisted::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1721 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1722 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1723 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1724 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1725 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1726 uint32_t width, uint32_t height, uint32_t depth) {
1727 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1728 cb_state->hasTraceRaysCmd = true;
1729}
1730
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001731void GpuAssisted::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001732 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1733 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1734 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1735 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001736 uint32_t height, uint32_t depth) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001737 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, CMD_TRACERAYSKHR);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001738}
1739
1740void GpuAssisted::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001741 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1742 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1743 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1744 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001745 uint32_t height, uint32_t depth) {
1746 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1747 cb_state->hasTraceRaysCmd = true;
1748}
1749
1750void GpuAssisted::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001751 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1752 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1753 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1754 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -07001755 VkDeviceAddress indirectDeviceAddress) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001756 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, CMD_TRACERAYSINDIRECTKHR);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001757}
1758
1759void GpuAssisted::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001760 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1761 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1762 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1763 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -07001764 VkDeviceAddress indirectDeviceAddress) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001765 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1766 cb_state->hasTraceRaysCmd = true;
1767}
1768
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001769// To generate the pre draw validation shader, run the following from the repository base level
Tony-LunarG20678ff2021-05-07 14:56:26 -06001770// python ./scripts/generate_spirv.py --outfilename ./layers/generated/gpu_pre_draw_shader.h ./layers/gpu_pre_draw_shader.vert
1771// ./External/glslang/build/install/bin/glslangValidator.exe
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001772#include "gpu_pre_draw_shader.h"
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001773void GpuAssisted::AllocatePreDrawValidationResources(GpuAssistedDeviceMemoryBlock output_block,
1774 GpuAssistedPreDrawResources &resources, const LAST_BOUND_STATE &state,
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001775 VkPipeline *pPipeline, const GpuAssistedCmdDrawIndirectState *cdi_state) {
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001776 VkResult result;
1777 if (!pre_draw_validation_state.globals_created) {
1778 auto shader_module_ci = LvlInitStruct<VkShaderModuleCreateInfo>();
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001779 shader_module_ci.codeSize = sizeof(gpu_pre_draw_shader_vert);
1780 shader_module_ci.pCode = gpu_pre_draw_shader_vert;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001781 result =
1782 DispatchCreateShaderModule(device, &shader_module_ci, nullptr, &pre_draw_validation_state.validation_shader_module);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001783 if (result != VK_SUCCESS) {
1784 ReportSetupProblem(device, "Unable to create shader module. Aborting GPU-AV");
1785 aborted = true;
1786 return;
1787 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001788
1789 std::vector<VkDescriptorSetLayoutBinding> bindings;
1790 VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, NULL};
1791 // 0 - output buffer, 1 - count buffer
1792 bindings.push_back(binding);
1793 binding.binding = 1;
1794 bindings.push_back(binding);
1795
1796 VkDescriptorSetLayoutCreateInfo ds_layout_ci = {};
1797 ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
1798 ds_layout_ci.bindingCount = static_cast<uint32_t>(bindings.size());
1799 ds_layout_ci.pBindings = bindings.data();
1800 result = DispatchCreateDescriptorSetLayout(device, &ds_layout_ci, nullptr, &pre_draw_validation_state.validation_ds_layout);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001801 if (result != VK_SUCCESS) {
1802 ReportSetupProblem(device, "Unable to create descriptor set layout. Aborting GPU-AV");
1803 aborted = true;
1804 return;
1805 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001806
1807 const uint32_t push_constant_range_count = 1;
1808 VkPushConstantRange push_constant_ranges[push_constant_range_count] = {};
1809 push_constant_ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
1810 push_constant_ranges[0].offset = 0;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001811 push_constant_ranges[0].size = 4 * sizeof(uint32_t);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001812 VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo[1] = {};
1813 pipelineLayoutCreateInfo[0].sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
1814 pipelineLayoutCreateInfo[0].pNext = NULL;
1815 pipelineLayoutCreateInfo[0].pushConstantRangeCount = push_constant_range_count;
1816 pipelineLayoutCreateInfo[0].pPushConstantRanges = push_constant_ranges;
1817 pipelineLayoutCreateInfo[0].setLayoutCount = 1;
1818 pipelineLayoutCreateInfo[0].pSetLayouts = &pre_draw_validation_state.validation_ds_layout;
1819 result = DispatchCreatePipelineLayout(device, pipelineLayoutCreateInfo, NULL,
1820 &pre_draw_validation_state.validation_pipeline_layout);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001821 if (result != VK_SUCCESS) {
1822 ReportSetupProblem(device, "Unable to create pipeline layout. Aborting GPU-AV");
1823 aborted = true;
1824 return;
1825 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001826
1827 pre_draw_validation_state.globals_created = true;
1828 }
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001829 VkRenderPass render_pass = state.pipeline_state->rp_state->renderPass();
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001830 assert(render_pass != VK_NULL_HANDLE);
1831 auto pipeline = pre_draw_validation_state.renderpass_to_pipeline.find(render_pass);
1832 if (pipeline == pre_draw_validation_state.renderpass_to_pipeline.end()) {
1833 auto pipeline_stage_ci = LvlInitStruct<VkPipelineShaderStageCreateInfo>();
1834 pipeline_stage_ci.stage = VK_SHADER_STAGE_VERTEX_BIT;
1835 pipeline_stage_ci.module = pre_draw_validation_state.validation_shader_module;
1836 pipeline_stage_ci.pName = "main";
1837
1838 auto graphicsPipelineCreateInfo = LvlInitStruct<VkGraphicsPipelineCreateInfo>();
1839 auto vertexInputState = LvlInitStruct<VkPipelineVertexInputStateCreateInfo>();
1840 auto inputAssemblyState = LvlInitStruct<VkPipelineInputAssemblyStateCreateInfo>();
1841 inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1842 auto rasterizationState = LvlInitStruct<VkPipelineRasterizationStateCreateInfo>();
1843 rasterizationState.rasterizerDiscardEnable = VK_TRUE;
1844 auto colorBlendState = LvlInitStruct<VkPipelineColorBlendStateCreateInfo>();
1845
1846 graphicsPipelineCreateInfo.pVertexInputState = &vertexInputState;
1847 graphicsPipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
1848 graphicsPipelineCreateInfo.pRasterizationState = &rasterizationState;
1849 graphicsPipelineCreateInfo.pColorBlendState = &colorBlendState;
1850 graphicsPipelineCreateInfo.renderPass = render_pass;
1851 graphicsPipelineCreateInfo.layout = pre_draw_validation_state.validation_pipeline_layout;
1852 graphicsPipelineCreateInfo.stageCount = 1;
1853 graphicsPipelineCreateInfo.pStages = &pipeline_stage_ci;
1854
1855 VkPipeline new_pipeline = VK_NULL_HANDLE;
1856 result = DispatchCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, nullptr, &new_pipeline);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001857 if (result != VK_SUCCESS) {
1858 ReportSetupProblem(device, "Unable to create graphics pipeline. Aborting GPU-AV");
1859 aborted = true;
1860 return;
1861 }
1862
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001863 *pPipeline = new_pipeline;
1864 pre_draw_validation_state.renderpass_to_pipeline[render_pass] = new_pipeline;
1865 } else {
1866 *pPipeline = pipeline->second;
1867 }
1868
1869 result = desc_set_manager->GetDescriptorSet(&resources.desc_pool, pre_draw_validation_state.validation_ds_layout,
1870 &resources.desc_set);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001871 if (result != VK_SUCCESS) {
1872 ReportSetupProblem(device, "Unable to allocate descriptor set. Aborting GPU-AV");
1873 aborted = true;
1874 return;
1875 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001876
1877 VkDescriptorBufferInfo buffer_infos[3] = {};
1878 // Error output buffer
1879 buffer_infos[0].buffer = output_block.buffer;
1880 buffer_infos[0].offset = 0;
1881 buffer_infos[0].range = VK_WHOLE_SIZE;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001882 if (cdi_state->count_buffer) {
1883 // Count buffer
1884 buffer_infos[1].buffer = cdi_state->count_buffer;
1885 } else {
1886 // Draw Buffer
1887 buffer_infos[1].buffer = cdi_state->buffer;
1888 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001889 buffer_infos[1].offset = 0;
1890 buffer_infos[1].range = VK_WHOLE_SIZE;
1891
1892 VkWriteDescriptorSet desc_writes[2] = {};
1893 for (auto i = 0; i < 2; i++) {
1894 desc_writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1895 desc_writes[i].dstBinding = i;
1896 desc_writes[i].descriptorCount = 1;
1897 desc_writes[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1898 desc_writes[i].pBufferInfo = &buffer_infos[i];
1899 desc_writes[i].dstSet = resources.desc_set;
1900 }
1901 DispatchUpdateDescriptorSets(device, 2, desc_writes, 0, NULL);
1902}
1903
Tony-LunarG7de10e82020-11-24 11:31:55 -07001904void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point,
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001905 CMD_TYPE cmd_type, const GpuAssistedCmdDrawIndirectState *cdi_state) {
Jason Macnak67407e72019-07-11 11:05:09 -07001906 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1907 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
andreygca287f22019-04-10 00:15:33 +03001908 return;
1909 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001910 VkResult result;
1911
Tony-LunarG99b880b2019-09-26 11:19:52 -06001912 if (aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001913
1914 std::vector<VkDescriptorSet> desc_sets;
1915 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -06001916 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001917 assert(result == VK_SUCCESS);
1918 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001919 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001920 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001921 return;
1922 }
1923
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001924 VkDescriptorBufferInfo output_desc_buffer_info = {};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001925 output_desc_buffer_info.range = output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001926
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001927 auto cb_node = GetCBState(cmd_buffer);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001928 if (!cb_node) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001929 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001930 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001931 return;
1932 }
1933
Tony-LunarG81efe392019-03-07 15:43:27 -07001934 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001935 GpuAssistedDeviceMemoryBlock output_block = {};
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001936 VkBufferCreateInfo buffer_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
1937 buffer_info.size = output_buffer_size;
1938 buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1939 VmaAllocationCreateInfo alloc_info = {};
1940 alloc_info.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
1941 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001942 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001943 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001944 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001945 return;
1946 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001947
Tony-LunarG81efe392019-03-07 15:43:27 -07001948 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001949 uint32_t *data_ptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001950 result = vmaMapMemory(vmaAllocator, output_block.allocation, reinterpret_cast<void **>(&data_ptr));
Tony-LunarG0e564722019-03-19 16:09:14 -06001951 if (result == VK_SUCCESS) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001952 memset(data_ptr, 0, output_buffer_size);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001953 vmaUnmapMemory(vmaAllocator, output_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001954 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001955
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001956 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001957 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
1958 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
1959 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001960 GpuAssistedPreDrawResources pre_draw_resources = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001961 uint32_t desc_count = 1;
locke-lunargb8d7a7a2020-10-25 16:01:52 -06001962 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
1963 auto const &state = cb_node->lastBound[lv_bind_point];
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001964 uint32_t number_of_sets = static_cast<uint32_t>(state.per_set.size());
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001965
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001966 if (validate_draw_indirect && ((cmd_type == CMD_DRAWINDIRECTCOUNT || cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT) ||
1967 ((cmd_type == CMD_DRAWINDIRECT || cmd_type == CMD_DRAWINDEXEDINDIRECT) &&
1968 !(enabled_features.core.drawIndirectFirstInstance)))) {
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001969 // Insert a draw that can examine some device memory right before the draw we're validating (Pre Draw Validation)
Tony-LunarG20678ff2021-05-07 14:56:26 -06001970 //
1971 // NOTE that this validation does not attempt to abort invalid api calls as most other validation does. A crash
1972 // or DEVICE_LOST resulting from the invalid call will prevent preceeding validation errors from being reported.
1973
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001974 assert(bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001975 assert(cdi_state != NULL);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001976 VkPipeline validation_pipeline;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001977 AllocatePreDrawValidationResources(output_block, pre_draw_resources, state, &validation_pipeline, cdi_state);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001978 if (aborted) return;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001979
1980 // Save current graphics pipeline state
1981 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
1982 restorable_state.Create(cb_node, VK_PIPELINE_BIND_POINT_GRAPHICS);
1983
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001984 // Save parameters for error message
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001985 pre_draw_resources.buffer = cdi_state->buffer;
1986 pre_draw_resources.offset = cdi_state->offset;
1987 pre_draw_resources.stride = cdi_state->stride;
1988
1989 uint32_t pushConstants[4] = {};
1990 if (cmd_type == CMD_DRAWINDIRECTCOUNT || cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT) {
1991 if (cdi_state->count_buffer_offset > std::numeric_limits<uint32_t>::max()) {
1992 ReportSetupProblem(device,
1993 "Count buffer offset is larger than can be contained in an unsigned int. Aborting GPU-AV");
1994 aborted = true;
1995 return;
1996 }
1997
1998 // Buffer size must be >= (stride * (drawCount - 1) + offset + sizeof(VkDrawIndirectCommand))
1999 uint32_t struct_size;
2000 if (cmd_type == CMD_DRAWINDIRECTCOUNT) {
2001 struct_size = sizeof(VkDrawIndirectCommand);
2002 } else {
2003 assert(cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT);
2004 struct_size = sizeof(VkDrawIndexedIndirectCommand);
2005 }
2006 BUFFER_STATE *buffer_state = GetBufferState(cdi_state->buffer);
2007 uint32_t max_count;
2008 uint64_t bufsize = buffer_state->createInfo.size;
2009 uint64_t first_command_bytes = struct_size + cdi_state->offset;
2010 if (first_command_bytes > bufsize) {
2011 max_count = 0;
2012 } else {
2013 max_count = 1 + static_cast<uint32_t>(std::floor(((bufsize - first_command_bytes) / cdi_state->stride)));
2014 }
2015 pre_draw_resources.buf_size = buffer_state->createInfo.size;
2016
2017 assert(phys_dev_props.limits.maxDrawIndirectCount > 0);
2018 pushConstants[0] = phys_dev_props.limits.maxDrawIndirectCount;
2019 pushConstants[1] = max_count;
2020 pushConstants[2] = static_cast<uint32_t>((cdi_state->count_buffer_offset / sizeof(uint32_t)));
2021 } else {
2022 pushConstants[0] = 0; // firstInstance check instead of count buffer check
2023 pushConstants[1] = cdi_state->drawCount;
2024 if (cmd_type == CMD_DRAWINDIRECT) {
2025 pushConstants[2] = static_cast<uint32_t>(
2026 ((cdi_state->offset + offsetof(struct VkDrawIndirectCommand, firstInstance)) / sizeof(uint32_t)));
2027 } else {
2028 assert(cmd_type == CMD_DRAWINDEXEDINDIRECT);
2029 pushConstants[2] = static_cast<uint32_t>(
2030 ((cdi_state->offset + offsetof(struct VkDrawIndexedIndirectCommand, firstInstance)) / sizeof(uint32_t)));
2031 }
2032 pushConstants[3] = (cdi_state->stride / sizeof(uint32_t));
2033 }
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06002034
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002035 // Insert diagnostic draw
2036 DispatchCmdBindPipeline(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, validation_pipeline);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002037 DispatchCmdPushConstants(cmd_buffer, pre_draw_validation_state.validation_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0,
2038 sizeof(pushConstants), pushConstants);
2039 DispatchCmdBindDescriptorSets(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
2040 pre_draw_validation_state.validation_pipeline_layout, 0, 1, &pre_draw_resources.desc_set, 0,
2041 nullptr);
2042 DispatchCmdDraw(cmd_buffer, 3, 1, 0, 0);
2043
2044 // Restore the previous graphics pipeline state.
2045 restorable_state.Restore(cmd_buffer);
2046 }
2047
Tony-LunarGe29097a2020-12-03 10:59:19 -07002048 bool has_buffers = false;
Tony-LunarG81efe392019-03-07 15:43:27 -07002049 // Figure out how much memory we need for the input block based on how many sets and bindings there are
2050 // and how big each of the bindings is
Tony-LunarGc28e28a2020-08-14 10:37:48 -06002051 if (number_of_sets > 0 && (descriptor_indexing || buffer_oob_enabled)) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002052 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
2053 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
John Zulauf79f06582021-02-27 18:38:39 -07002054 for (const auto &s : state.per_set) {
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002055 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06002056 if (desc && (desc->GetBindingCount() > 0)) {
2057 auto bindings = desc->GetLayout()->GetSortedBindingSet();
Tony-LunarGa77cade2019-03-06 10:49:22 -07002058 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
2059 for (auto binding : bindings) {
Tony-LunarG7564b382019-08-21 10:11:35 -06002060 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2061 // blocks
Tony-LunarGe29097a2020-12-03 10:59:19 -07002062 auto descriptor_type = desc->GetLayout()->GetTypeFromBinding(binding);
2063 if (descriptor_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
Tony-LunarG7564b382019-08-21 10:11:35 -06002064 descriptor_count++;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07002065 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
2066 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
2067 "validation");
Tony-LunarG7564b382019-08-21 10:11:35 -06002068 } else if (binding == desc->GetLayout()->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002069 descriptor_count += desc->GetVariableDescriptorCount();
2070 } else {
2071 descriptor_count += desc->GetDescriptorCountFromBinding(binding);
2072 }
Tony-LunarGe29097a2020-12-03 10:59:19 -07002073 if (!has_buffers && (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
2074 descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC ||
2075 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
Tony-LunarGe8632e42020-11-18 17:03:12 -07002076 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
2077 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
2078 descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002079 has_buffers = true;
Tony-LunarGa77cade2019-03-06 10:49:22 -07002080 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -06002081 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002082 }
2083 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002084
Tony-LunarGe29097a2020-12-03 10:59:19 -07002085 if (descriptor_indexing || has_buffers) {
2086 // Note that the size of the input buffer is dependent on the maximum binding number, which
2087 // can be very large. This is because for (set = s, binding = b, index = i), the validation
2088 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
2089 // see if descriptors have been written. In gpu_validation.md, we note this and advise
2090 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
2091 uint32_t words_needed;
2092 if (descriptor_indexing) {
2093 words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
2094 } else {
2095 words_needed = 1 + number_of_sets + binding_count + descriptor_count;
2096 }
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002097 alloc_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2098 buffer_info.size = words_needed * 4;
2099 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &di_input_block.buffer, &di_input_block.allocation,
2100 nullptr);
Tony-LunarGe29097a2020-12-03 10:59:19 -07002101 if (result != VK_SUCCESS) {
2102 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
2103 aborted = true;
2104 return;
2105 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002106
Tony-LunarGe29097a2020-12-03 10:59:19 -07002107 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
2108 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
2109 // outline of the input buffer format
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002110 result = vmaMapMemory(vmaAllocator, di_input_block.allocation, reinterpret_cast<void **>(&data_ptr));
2111 memset(data_ptr, 0, static_cast<size_t>(buffer_info.size));
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002112
Tony-LunarGe29097a2020-12-03 10:59:19 -07002113 // Descriptor indexing needs the number of descriptors at each binding.
2114 if (descriptor_indexing) {
2115 // Pointer to a sets array that points into the sizes array
2116 uint32_t *sets_to_sizes = data_ptr + 1;
2117 // Pointer to the sizes array that contains the array size of the descriptor at each binding
2118 uint32_t *sizes = sets_to_sizes + number_of_sets;
2119 // Pointer to another sets array that points into the bindings array that points into the written array
2120 uint32_t *sets_to_bindings = sizes + binding_count;
2121 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
2122 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
2123 // Index of the next entry in the written array to be updated
2124 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
2125 uint32_t bind_counter = number_of_sets + 1;
2126 // Index of the start of the sets_to_bindings array
2127 data_ptr[0] = number_of_sets + binding_count + 1;
2128
John Zulauf79f06582021-02-27 18:38:39 -07002129 for (const auto &s : state.per_set) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002130 auto desc = s.bound_descriptor_set;
2131 if (desc && (desc->GetBindingCount() > 0)) {
2132 auto layout = desc->GetLayout();
2133 auto bindings = layout->GetSortedBindingSet();
2134 // For each set, fill in index of its bindings sizes in the sizes array
2135 *sets_to_sizes++ = bind_counter;
2136 // For each set, fill in the index of its bindings in the bindings_to_written array
2137 *sets_to_bindings++ = bind_counter + number_of_sets + binding_count;
2138 for (auto binding : bindings) {
2139 // For each binding, fill in its size in the sizes array
2140 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2141 // uniform blocks
2142 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2143 sizes[binding] = 1;
2144 } else if (binding == layout->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
2145 sizes[binding] = desc->GetVariableDescriptorCount();
2146 } else {
2147 sizes[binding] = desc->GetDescriptorCountFromBinding(binding);
2148 }
2149 // Fill in the starting index for this binding in the written array in the bindings_to_written array
2150 bindings_to_written[binding] = written_index;
2151
2152 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2153 // uniform blocks
2154 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2155 data_ptr[written_index++] = UINT_MAX;
2156 continue;
2157 }
2158
2159 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
2160 // For each array element in the binding, update the written array with whether it has been written
2161 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
2162 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
2163 if (descriptor->updated) {
2164 SetDescriptorInitialized(data_ptr, written_index, descriptor);
2165 } else if (desc->IsUpdateAfterBind(binding)) {
2166 // If it hasn't been written now and it's update after bind, put it in a list to check at
2167 // QueueSubmit
2168 di_input_block.update_at_submit[written_index] = descriptor;
2169 }
2170 written_index++;
2171 }
2172 }
2173 auto last = desc->GetLayout()->GetMaxBinding();
2174 bindings_to_written += last + 1;
2175 bind_counter += last + 1;
2176 sizes += last + 1;
2177 } else {
2178 *sets_to_sizes++ = 0;
2179 *sets_to_bindings++ = 0;
2180 }
2181 }
2182 } else {
2183 // If no descriptor indexing, we don't need number of descriptors at each binding, so
2184 // no sets_to_sizes or sizes arrays, just sets_to_bindings, bindings_to_written and written_index
2185
2186 // Pointer to sets array that points into the bindings array that points into the written array
2187 uint32_t *sets_to_bindings = data_ptr + 1;
2188 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
2189 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
2190 // Index of the next entry in the written array to be updated
2191 uint32_t written_index = 1 + number_of_sets + binding_count;
2192 uint32_t bind_counter = number_of_sets + 1;
2193 data_ptr[0] = 1;
2194
John Zulauf79f06582021-02-27 18:38:39 -07002195 for (const auto &s : state.per_set) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002196 auto desc = s.bound_descriptor_set;
2197 if (desc && (desc->GetBindingCount() > 0)) {
2198 auto layout = desc->GetLayout();
2199 auto bindings = layout->GetSortedBindingSet();
2200 *sets_to_bindings++ = bind_counter;
2201 for (auto binding : bindings) {
2202 // Fill in the starting index for this binding in the written array in the bindings_to_written array
2203 bindings_to_written[binding] = written_index;
2204
2205 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2206 // uniform blocks
2207 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2208 data_ptr[written_index++] = UINT_MAX;
2209 continue;
2210 }
2211
2212 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
2213
2214 // For each array element in the binding, update the written array with whether it has been written
2215 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
2216 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
2217 if (descriptor->updated) {
2218 SetDescriptorInitialized(data_ptr, written_index, descriptor);
2219 } else if (desc->IsUpdateAfterBind(binding)) {
2220 // If it hasn't been written now and it's update after bind, put it in a list to check at
2221 // QueueSubmit
2222 di_input_block.update_at_submit[written_index] = descriptor;
2223 }
2224 written_index++;
2225 }
2226 }
2227 auto last = desc->GetLayout()->GetMaxBinding();
2228 bindings_to_written += last + 1;
2229 bind_counter += last + 1;
2230 } else {
2231 *sets_to_bindings++ = 0;
2232 }
2233 }
2234 }
2235 vmaUnmapMemory(vmaAllocator, di_input_block.allocation);
2236
2237 di_input_desc_buffer_info.range = (words_needed * 4);
2238 di_input_desc_buffer_info.buffer = di_input_block.buffer;
2239 di_input_desc_buffer_info.offset = 0;
2240
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06002241 desc_writes[1] = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarGe29097a2020-12-03 10:59:19 -07002242 desc_writes[1].dstBinding = 1;
2243 desc_writes[1].descriptorCount = 1;
2244 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2245 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
2246 desc_writes[1].dstSet = desc_sets[0];
2247
2248 desc_count = 2;
2249 }
Tony-LunarG0e564722019-03-19 16:09:14 -06002250 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002251
Tony-LunarGc111b242020-06-30 14:43:45 -06002252 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) && buffer_map.size() &&
Tony-LunarG5c38b182020-06-10 16:15:32 -06002253 shaderInt64 && enabled_features.core12.bufferDeviceAddress) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002254 // Example BDA input buffer assuming 2 buffers using BDA:
2255 // Word 0 | Index of start of buffer sizes (in this case 5)
2256 // Word 1 | 0x0000000000000000
2257 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
2258 // Word 3 | Device Address of second buffer
2259 // Word 4 | 0xffffffffffffffff
2260 // Word 5 | 0 (size of pretend buffer at word 1)
2261 // Word 6 | Size in bytes of first buffer
2262 // Word 7 | Size in bytes of second buffer
2263 // Word 8 | 0 (size of pretend buffer in word 4)
2264
Tony-LunarG99b880b2019-09-26 11:19:52 -06002265 uint32_t num_buffers = static_cast<uint32_t>(buffer_map.size());
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002266 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002267 alloc_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2268 buffer_info.size = words_needed * 8; // 64 bit words
Tony-LunarG99b880b2019-09-26 11:19:52 -06002269 result =
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002270 vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &bda_input_block.buffer, &bda_input_block.allocation, nullptr);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002271 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07002272 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002273 aborted = true;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002274 return;
2275 }
2276 uint64_t *bda_data;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002277 result = vmaMapMemory(vmaAllocator, bda_input_block.allocation, reinterpret_cast<void **>(&bda_data));
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002278 uint32_t address_index = 1;
2279 uint32_t size_index = 3 + num_buffers;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002280 memset(bda_data, 0, static_cast<size_t>(buffer_info.size));
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002281 bda_data[0] = size_index; // Start of buffer sizes
2282 bda_data[address_index++] = 0; // NULL address
2283 bda_data[size_index++] = 0;
2284
John Zulauf79f06582021-02-27 18:38:39 -07002285 for (const auto &value : buffer_map) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002286 bda_data[address_index++] = value.first;
2287 bda_data[size_index++] = value.second;
2288 }
2289 bda_data[address_index] = UINTPTR_MAX;
2290 bda_data[size_index] = 0;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002291 vmaUnmapMemory(vmaAllocator, bda_input_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002292
2293 bda_input_desc_buffer_info.range = (words_needed * 8);
2294 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
2295 bda_input_desc_buffer_info.offset = 0;
2296
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06002297 desc_writes[desc_count] = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002298 desc_writes[desc_count].dstBinding = 2;
2299 desc_writes[desc_count].descriptorCount = 1;
2300 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2301 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
2302 desc_writes[desc_count].dstSet = desc_sets[0];
2303 desc_count++;
2304 }
2305
Tony-LunarGb2501d22019-01-28 09:59:13 -07002306 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002307 output_desc_buffer_info.buffer = output_block.buffer;
2308 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002309
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06002310 desc_writes[0] = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002311 desc_writes[0].descriptorCount = 1;
2312 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2313 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
2314 desc_writes[0].dstSet = desc_sets[0];
2315 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002316
locke-lunargb8d7a7a2020-10-25 16:01:52 -06002317 const auto *pipeline_state = state.pipeline_state;
2318 if (pipeline_state) {
2319 if ((pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index) &&
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06002320 !pipeline_state->pipeline_layout->Destroyed()) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002321 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout(), desc_set_bind_index, 1,
Tony-LunarG99b880b2019-09-26 11:19:52 -06002322 desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002323 }
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06002324 if (pipeline_state->pipeline_layout->Destroyed()) {
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002325 ReportSetupProblem(device, "Pipeline layout has been destroyed, aborting GPU-AV");
2326 aborted = true;
2327 } else {
2328 // Record buffer and memory info in CB state tracking
2329 GetBufferInfo(cmd_buffer)
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002330 .emplace_back(output_block, di_input_block, bda_input_block, pre_draw_resources, desc_sets[0], desc_pool,
2331 bind_point, cmd_type);
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002332 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002333 } else {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07002334 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002335 aborted = true;
2336 }
2337 if (aborted) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002338 vmaDestroyBuffer(vmaAllocator, di_input_block.buffer, di_input_block.allocation);
2339 vmaDestroyBuffer(vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
2340 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002341 return;
2342 }
2343}