blob: 8037a766596960451146e7c3643dcfa9261220da [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-LunarGa3ec16c2021-04-06 12:19:57 -0600260 const char *bufferoob_string = getLayerOption("khronos_validation.gpuav_buffer_oob");
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600261 device_gpu_assisted->buffer_oob_enabled = *bufferoob_string ? !strcmp(bufferoob_string, "true") : true;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700262 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600263
Tony-LunarG3723a3a2021-05-04 14:52:39 -0600264 const char *draw_indirect_string = getLayerOption("khronos_validation.validate_draw_indirect");
265 device_gpu_assisted->validate_draw_indirect = *draw_indirect_string ? !strcmp(draw_indirect_string, "true") : true;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600266
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600267 if (device_gpu_assisted->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700268 ReportSetupProblem(device, "GPU-Assisted validation requires Vulkan 1.1 or later. GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600269 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600270 return;
271 }
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600272
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600273 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700274 ReportSetupProblem(device,
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600275 "GPU-Assisted validation requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
276 "GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600277 device_gpu_assisted->aborted = true;
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600278 return;
279 }
280
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700281 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) &&
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600282 !supported_features.shaderInt64) {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700283 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
284 "shaderInt64 feature is not available. No buffer device address checking will be attempted");
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600285 }
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600286 device_gpu_assisted->shaderInt64 = supported_features.shaderInt64;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600287 device_gpu_assisted->physicalDevice = physicalDevice;
288 device_gpu_assisted->device = *pDevice;
Tony-LunarGbb145f32020-04-27 13:41:29 -0600289 device_gpu_assisted->output_buffer_size = sizeof(uint32_t) * (spvtools::kInstMaxOutCnt + 1);
Tony-LunarG5c38b182020-06-10 16:15:32 -0600290 device_gpu_assisted->descriptor_indexing = CheckForDescriptorIndexing(device_gpu_assisted->enabled_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600291 std::vector<VkDescriptorSetLayoutBinding> bindings;
292 VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
Tony-LunarGc7ed2082020-06-11 14:00:04 -0600293 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT |
294 VK_SHADER_STAGE_MESH_BIT_NV | VK_SHADER_STAGE_TASK_BIT_NV |
295 kShaderStageAllRayTracing,
Tony-LunarG1dce2392019-10-23 16:49:29 -0600296 NULL};
297 bindings.push_back(binding);
298 for (auto i = 1; i < 3; i++) {
299 binding.binding = i;
300 bindings.push_back(binding);
Karl Schultz7b024b42018-08-30 16:18:18 -0600301 }
Tony-LunarGb5fae462020-03-05 12:43:25 -0700302 UtilPostCallRecordCreateDevice(pCreateInfo, bindings, device_gpu_assisted, device_gpu_assisted->phys_dev_props);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600303 CreateAccelerationStructureBuildValidationState(device_gpu_assisted);
Karl Schultz7b024b42018-08-30 16:18:18 -0600304}
305
Mike Schuchardt2df08912020-12-15 16:28:09 -0800306void GpuAssisted::PostCallRecordGetBufferDeviceAddress(VkDevice device, const VkBufferDeviceAddressInfo *pInfo,
Tony-LunarG588c7052020-04-23 10:47:21 -0600307 VkDeviceAddress address) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600308 BUFFER_STATE *buffer_state = GetBufferState(pInfo->buffer);
309 // Validate against the size requested when the buffer was created
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600310 if (buffer_state) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600311 buffer_map[address] = buffer_state->createInfo.size;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600312 buffer_state->deviceAddress = address;
313 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600314}
315
Mike Schuchardt2df08912020-12-15 16:28:09 -0800316void GpuAssisted::PostCallRecordGetBufferDeviceAddressEXT(VkDevice device, const VkBufferDeviceAddressInfo *pInfo,
Tony-LunarG588c7052020-04-23 10:47:21 -0600317 VkDeviceAddress address) {
318 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
319}
320
Mike Schuchardt2df08912020-12-15 16:28:09 -0800321void GpuAssisted::PostCallRecordGetBufferDeviceAddressKHR(VkDevice device, const VkBufferDeviceAddressInfo *pInfo,
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700322 VkDeviceAddress address) {
Tony-LunarG588c7052020-04-23 10:47:21 -0600323 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700324}
325
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600326void GpuAssisted::PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600327 BUFFER_STATE *buffer_state = GetBufferState(buffer);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600328 if (buffer_state) buffer_map.erase(buffer_state->deviceAddress);
Tony-LunarG2966c732020-05-21 10:33:53 -0600329 ValidationStateTracker::PreCallRecordDestroyBuffer(device, buffer, pAllocator);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600330}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600331
Karl Schultz7b024b42018-08-30 16:18:18 -0600332// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600333void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600334 DestroyAccelerationStructureBuildValidationState();
Tony-LunarGb5fae462020-03-05 12:43:25 -0700335 UtilPreCallRecordDestroyDevice(this);
Tony-LunarG2966c732020-05-21 10:33:53 -0600336 ValidationStateTracker::PreCallRecordDestroyDevice(device, pAllocator);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600337 if (pre_draw_validation_state.globals_created) {
338 DispatchDestroyShaderModule(device, pre_draw_validation_state.validation_shader_module, nullptr);
339 DispatchDestroyDescriptorSetLayout(device, pre_draw_validation_state.validation_ds_layout, nullptr);
340 DispatchDestroyPipelineLayout(device, pre_draw_validation_state.validation_pipeline_layout, nullptr);
341 for (auto it = pre_draw_validation_state.renderpass_to_pipeline.begin();
342 it != pre_draw_validation_state.renderpass_to_pipeline.end(); ++it) {
343 DispatchDestroyPipeline(device, it->second, nullptr);
344 }
345 pre_draw_validation_state.renderpass_to_pipeline.clear();
346 pre_draw_validation_state.globals_created = false;
347 }
Tony-LunarG0a863bc2020-09-16 09:50:04 -0600348 // State Tracker can end up making vma calls through callbacks - don't destroy allocator until ST is done
349 if (vmaAllocator) {
350 vmaDestroyAllocator(vmaAllocator);
351 }
352 desc_set_manager.reset();
Karl Schultz7b024b42018-08-30 16:18:18 -0600353}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600354
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600355void GpuAssisted::CreateAccelerationStructureBuildValidationState(GpuAssisted *device_gpuav) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600356 if (device_gpuav->aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700357 return;
358 }
359
Tony-LunarG99b880b2019-09-26 11:19:52 -0600360 auto &as_validation_state = device_gpuav->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700361 if (as_validation_state.initialized) {
362 return;
363 }
364
365 if (!device_extensions.vk_nv_ray_tracing) {
366 return;
367 }
368
369 // Outline:
370 // - Create valid bottom level acceleration structure which acts as replacement
371 // - Create and load vertex buffer
372 // - Create and load index buffer
373 // - Create, allocate memory for, and bind memory for acceleration structure
374 // - Query acceleration structure handle
375 // - Create command pool and command buffer
376 // - Record build acceleration structure command
377 // - Submit command buffer and wait for completion
378 // - Cleanup
379 // - Create compute pipeline for validating instance buffers
380 // - Create descriptor set layout
381 // - Create pipeline layout
382 // - Create pipeline
383 // - Cleanup
384
385 VkResult result = VK_SUCCESS;
386
387 VkBuffer vbo = VK_NULL_HANDLE;
388 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
389 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600390 auto vbo_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700391 vbo_ci.size = sizeof(float) * 9;
392 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
393
394 VmaAllocationCreateInfo vbo_ai = {};
395 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
396 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
397
Tony-LunarG99b880b2019-09-26 11:19:52 -0600398 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700399 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700400 ReportSetupProblem(device, "Failed to create vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700401 }
402 }
403
404 if (result == VK_SUCCESS) {
405 uint8_t *mapped_vbo_buffer = nullptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700406 result = vmaMapMemory(device_gpuav->vmaAllocator, vbo_allocation, reinterpret_cast<void **>(&mapped_vbo_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700407 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700408 ReportSetupProblem(device, "Failed to map vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700409 } else {
410 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
411 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600412 vmaUnmapMemory(device_gpuav->vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700413 }
414 }
415
416 VkBuffer ibo = VK_NULL_HANDLE;
417 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
418 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600419 auto ibo_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700420 ibo_ci.size = sizeof(uint32_t) * 3;
421 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
422
423 VmaAllocationCreateInfo ibo_ai = {};
424 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
425 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
426
Tony-LunarG99b880b2019-09-26 11:19:52 -0600427 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700428 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700429 ReportSetupProblem(device, "Failed to create index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700430 }
431 }
432
433 if (result == VK_SUCCESS) {
434 uint8_t *mapped_ibo_buffer = nullptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700435 result = vmaMapMemory(device_gpuav->vmaAllocator, ibo_allocation, reinterpret_cast<void **>(&mapped_ibo_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700436 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700437 ReportSetupProblem(device, "Failed to map index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700438 } else {
439 const std::vector<uint32_t> indicies = {0, 1, 2};
440 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600441 vmaUnmapMemory(device_gpuav->vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700442 }
443 }
444
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600445 auto geometry = LvlInitStruct<VkGeometryNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700446 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600447 geometry.geometry.triangles = LvlInitStruct<VkGeometryTrianglesNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700448 geometry.geometry.triangles.vertexData = vbo;
449 geometry.geometry.triangles.vertexOffset = 0;
450 geometry.geometry.triangles.vertexCount = 3;
451 geometry.geometry.triangles.vertexStride = 12;
452 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
453 geometry.geometry.triangles.indexData = ibo;
454 geometry.geometry.triangles.indexOffset = 0;
455 geometry.geometry.triangles.indexCount = 3;
456 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
457 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
458 geometry.geometry.triangles.transformOffset = 0;
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600459 geometry.geometry.aabbs = LvlInitStruct<VkGeometryAABBNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700460
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600461 auto as_ci = LvlInitStruct<VkAccelerationStructureCreateInfoNV>();
462 as_ci.info = LvlInitStruct<VkAccelerationStructureInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700463 as_ci.info.instanceCount = 0;
464 as_ci.info.geometryCount = 1;
465 as_ci.info.pGeometries = &geometry;
466 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600467 result = DispatchCreateAccelerationStructureNV(device_gpuav->device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700468 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700469 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700470 "Failed to create acceleration structure for acceleration structure build validation.");
471 }
472 }
473
474 VkMemoryRequirements2 as_mem_requirements = {};
475 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600476 auto as_mem_requirements_info = LvlInitStruct<VkAccelerationStructureMemoryRequirementsInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700477 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
478 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
479
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600480 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700481 }
482
483 VmaAllocationInfo as_memory_ai = {};
484 if (result == VK_SUCCESS) {
485 VmaAllocationCreateInfo as_memory_aci = {};
486 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
487
Tony-LunarG99b880b2019-09-26 11:19:52 -0600488 result = vmaAllocateMemory(device_gpuav->vmaAllocator, &as_mem_requirements.memoryRequirements, &as_memory_aci,
489 &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700490 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700491 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700492 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
493 }
494 }
495
496 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600497 auto as_bind_info = LvlInitStruct<VkBindAccelerationStructureMemoryInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700498 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
499 as_bind_info.memory = as_memory_ai.deviceMemory;
500 as_bind_info.memoryOffset = as_memory_ai.offset;
501
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600502 result = DispatchBindAccelerationStructureMemoryNV(device_gpuav->device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700503 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700504 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700505 "Failed to bind acceleration structure memory for acceleration structure build validation.");
506 }
507 }
508
509 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600510 result = DispatchGetAccelerationStructureHandleNV(device_gpuav->device, as_validation_state.replacement_as,
511 sizeof(uint64_t), &as_validation_state.replacement_as_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700512 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700513 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700514 "Failed to get acceleration structure handle for acceleration structure build validation.");
515 }
516 }
517
518 VkMemoryRequirements2 scratch_mem_requirements = {};
519 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600520 auto scratch_mem_requirements_info = LvlInitStruct<VkAccelerationStructureMemoryRequirementsInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700521 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
522 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
523
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600524 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &scratch_mem_requirements_info,
525 &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700526 }
527
528 VkBuffer scratch = VK_NULL_HANDLE;
Tony-LunarG18900282020-05-20 12:34:33 -0600529 VmaAllocation scratch_allocation = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700530 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600531 auto scratch_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700532 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
533 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
Jason Macnak83cfd582019-07-31 10:14:24 -0700534 VmaAllocationCreateInfo scratch_aci = {};
535 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
536
Tony-LunarG18900282020-05-20 12:34:33 -0600537 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &scratch_ci, &scratch_aci, &scratch, &scratch_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700538 if (result != VK_SUCCESS) {
Tony-LunarG18900282020-05-20 12:34:33 -0600539 ReportSetupProblem(device_gpuav->device,
540 "Failed to create scratch buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700541 }
542 }
543
544 VkCommandPool command_pool = VK_NULL_HANDLE;
545 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600546 auto command_pool_ci = LvlInitStruct<VkCommandPoolCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700547 command_pool_ci.queueFamilyIndex = 0;
548
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600549 result = DispatchCreateCommandPool(device_gpuav->device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700550 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700551 ReportSetupProblem(device_gpuav->device, "Failed to create command pool for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700552 }
553 }
554
555 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
556
557 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600558 auto command_buffer_ai = LvlInitStruct<VkCommandBufferAllocateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700559 command_buffer_ai.commandPool = command_pool;
560 command_buffer_ai.commandBufferCount = 1;
561 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
562
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600563 result = DispatchAllocateCommandBuffers(device_gpuav->device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700564 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700565 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700566 "Failed to create command buffer for acceleration structure build validation.");
567 }
568
569 // Hook up command buffer dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600570 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700571 }
572
573 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600574 auto command_buffer_bi = LvlInitStruct<VkCommandBufferBeginInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700575
576 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
577 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700578 ReportSetupProblem(device_gpuav->device, "Failed to begin command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700579 }
580 }
581
582 if (result == VK_SUCCESS) {
583 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
584 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
585 DispatchEndCommandBuffer(command_buffer);
586 }
587
588 VkQueue queue = VK_NULL_HANDLE;
589 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600590 DispatchGetDeviceQueue(device_gpuav->device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700591
592 // Hook up queue dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600593 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700594
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600595 auto submit_info = LvlInitStruct<VkSubmitInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700596 submit_info.commandBufferCount = 1;
597 submit_info.pCommandBuffers = &command_buffer;
598 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
599 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700600 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700601 "Failed to submit command buffer for acceleration structure build validation.");
602 }
603 }
604
605 if (result == VK_SUCCESS) {
606 result = DispatchQueueWaitIdle(queue);
607 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700608 ReportSetupProblem(device_gpuav->device, "Failed to wait for queue idle for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700609 }
610 }
611
612 if (vbo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600613 vmaDestroyBuffer(device_gpuav->vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700614 }
615 if (ibo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600616 vmaDestroyBuffer(device_gpuav->vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700617 }
618 if (scratch != VK_NULL_HANDLE) {
Tony-LunarG18900282020-05-20 12:34:33 -0600619 vmaDestroyBuffer(device_gpuav->vmaAllocator, scratch, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700620 }
621 if (command_pool != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600622 DispatchDestroyCommandPool(device_gpuav->device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700623 }
624
Tony-LunarG99b880b2019-09-26 11:19:52 -0600625 if (device_gpuav->debug_desc_layout == VK_NULL_HANDLE) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700626 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700627 "Failed to find descriptor set layout for acceleration structure build validation.");
628 result = VK_INCOMPLETE;
629 }
630
631 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600632 auto pipeline_layout_ci = LvlInitStruct<VkPipelineLayoutCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700633 pipeline_layout_ci.setLayoutCount = 1;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600634 pipeline_layout_ci.pSetLayouts = &device_gpuav->debug_desc_layout;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600635 result = DispatchCreatePipelineLayout(device_gpuav->device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700636 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700637 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700638 "Failed to create pipeline layout for acceleration structure build validation.");
639 }
640 }
641
642 VkShaderModule shader_module = VK_NULL_HANDLE;
643 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600644 auto shader_module_ci = LvlInitStruct<VkShaderModuleCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700645 shader_module_ci.codeSize = sizeof(kComputeShaderSpirv);
646 shader_module_ci.pCode = (uint32_t *)kComputeShaderSpirv;
647
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600648 result = DispatchCreateShaderModule(device_gpuav->device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700649 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700650 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700651 "Failed to create compute shader module for acceleration structure build validation.");
652 }
653 }
654
655 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600656 auto pipeline_stage_ci = LvlInitStruct<VkPipelineShaderStageCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700657 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
658 pipeline_stage_ci.module = shader_module;
659 pipeline_stage_ci.pName = "main";
660
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600661 auto pipeline_ci = LvlInitStruct<VkComputePipelineCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700662 pipeline_ci.stage = pipeline_stage_ci;
663 pipeline_ci.layout = as_validation_state.pipeline_layout;
664
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600665 result = DispatchCreateComputePipelines(device_gpuav->device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr,
666 &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700667 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700668 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700669 "Failed to create compute pipeline for acceleration structure build validation.");
670 }
671 }
672
673 if (shader_module != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600674 DispatchDestroyShaderModule(device_gpuav->device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700675 }
676
677 if (result == VK_SUCCESS) {
678 as_validation_state.initialized = true;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700679 LogInfo(device_gpuav->device, "UNASSIGNED-GPU-Assisted Validation.",
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600680 "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700681 } else {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600682 device_gpuav->aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700683 }
684}
685
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600686void GpuAssisted::DestroyAccelerationStructureBuildValidationState() {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600687 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700688 if (as_validation_state.pipeline != VK_NULL_HANDLE) {
689 DispatchDestroyPipeline(device, as_validation_state.pipeline, nullptr);
690 }
691 if (as_validation_state.pipeline_layout != VK_NULL_HANDLE) {
692 DispatchDestroyPipelineLayout(device, as_validation_state.pipeline_layout, nullptr);
693 }
694 if (as_validation_state.replacement_as != VK_NULL_HANDLE) {
695 DispatchDestroyAccelerationStructureNV(device, as_validation_state.replacement_as, nullptr);
696 }
697 if (as_validation_state.replacement_as_allocation != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600698 vmaFreeMemory(vmaAllocator, as_validation_state.replacement_as_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700699 }
700}
701
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600702struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700703 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
704 VkPipeline pipeline = VK_NULL_HANDLE;
705 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
706 std::vector<VkDescriptorSet> descriptor_sets;
707 std::vector<std::vector<uint32_t>> dynamic_offsets;
708 uint32_t push_descriptor_set_index = 0;
709 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
710 std::vector<uint8_t> push_constants_data;
711 PushConstantRangesId push_constants_ranges;
712
713 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
714 pipeline_bind_point = bind_point;
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600715 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
Jason Macnak83cfd582019-07-31 10:14:24 -0700716
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600717 LAST_BOUND_STATE &last_bound = cb_state->lastBound[lv_bind_point];
Jason Macnak83cfd582019-07-31 10:14:24 -0700718 if (last_bound.pipeline_state) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600719 pipeline = last_bound.pipeline_state->pipeline();
Jason Macnak83cfd582019-07-31 10:14:24 -0700720 pipeline_layout = last_bound.pipeline_layout;
721 descriptor_sets.reserve(last_bound.per_set.size());
722 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
723 const auto *bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
724
725 descriptor_sets.push_back(bound_descriptor_set->GetSet());
726 if (bound_descriptor_set->IsPushDescriptor()) {
727 push_descriptor_set_index = static_cast<uint32_t>(i);
728 }
729 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
730 }
731
732 if (last_bound.push_descriptor_set) {
733 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
734 }
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500735 if (last_bound.pipeline_state->pipeline_layout->push_constant_ranges == cb_state->push_constant_data_ranges) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700736 push_constants_data = cb_state->push_constant_data;
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500737 push_constants_ranges = last_bound.pipeline_state->pipeline_layout->push_constant_ranges;
Jason Macnak83cfd582019-07-31 10:14:24 -0700738 }
739 }
740 }
741
742 void Restore(VkCommandBuffer command_buffer) const {
743 if (pipeline != VK_NULL_HANDLE) {
744 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
745 if (!descriptor_sets.empty()) {
746 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
747 VkDescriptorSet descriptor_set = descriptor_sets[i];
748 if (descriptor_set != VK_NULL_HANDLE) {
749 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
750 static_cast<uint32_t>(i), 1, &descriptor_set,
751 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
752 }
753 }
754 }
755 if (!push_descriptor_set_writes.empty()) {
756 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
757 static_cast<uint32_t>(push_descriptor_set_writes.size()),
758 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
759 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600760 if (!push_constants_data.empty()) {
761 for (const auto &push_constant_range : *push_constants_ranges) {
762 if (push_constant_range.size == 0) continue;
763 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
764 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
765 }
Jason Macnak83cfd582019-07-31 10:14:24 -0700766 }
767 }
768 }
769};
770
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600771void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
772 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
773 VkDeviceSize instanceOffset, VkBool32 update,
774 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
775 VkBuffer scratch, VkDeviceSize scratchOffset) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700776 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
777 return;
778 }
779
Tony-LunarG99b880b2019-09-26 11:19:52 -0600780 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700781 if (!as_validation_state.initialized) {
782 return;
783 }
784
785 // Empty acceleration structure is valid according to the spec.
786 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
787 return;
788 }
789
790 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
791 assert(cb_state != nullptr);
792
793 std::vector<uint64_t> current_valid_handles;
794 for (const auto &as_state_kv : accelerationStructureMap) {
795 const ACCELERATION_STRUCTURE_STATE &as_state = *as_state_kv.second;
Jeff Bolz95176d02020-04-01 00:36:16 -0500796 if (as_state.built && as_state.create_infoNV.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700797 current_valid_handles.push_back(as_state.opaque_handle);
798 }
799 }
800
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600801 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700802 as_validation_buffer_info.acceleration_structure = dst;
803
804 const VkDeviceSize validation_buffer_size =
805 // One uint for number of instances to validate
806 4 +
807 // Two uint for the replacement acceleration structure handle
808 8 +
809 // One uint for number of invalid handles found
810 4 +
811 // Two uint for the first invalid handle found
812 8 +
813 // One uint for the number of current valid handles
814 4 +
815 // Two uint for each current valid handle
816 (8 * current_valid_handles.size());
817
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600818 auto validation_buffer_create_info = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700819 validation_buffer_create_info.size = validation_buffer_size;
820 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
821
822 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
823 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
824
Tony-LunarG99b880b2019-09-26 11:19:52 -0600825 VkResult result = vmaCreateBuffer(vmaAllocator, &validation_buffer_create_info, &validation_buffer_alloc_info,
826 &as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -0700827 &as_validation_buffer_info.validation_buffer_allocation, nullptr);
828 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700829 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600830 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700831 return;
832 }
833
834 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700835 result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation,
836 reinterpret_cast<void **>(&mapped_validation_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700837 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700838 ReportSetupProblem(device, "Unable to allocate device memory for acceleration structure build val buffer.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600839 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700840 return;
841 }
842
843 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
844 mapped_validation_buffer->replacement_handle_bits_0 =
845 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
846 mapped_validation_buffer->replacement_handle_bits_1 =
847 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
848 mapped_validation_buffer->invalid_handle_found = 0;
849 mapped_validation_buffer->invalid_handle_bits_0 = 0;
850 mapped_validation_buffer->invalid_handle_bits_1 = 0;
851 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
852
853 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
854 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
855 const uint64_t current_valid_handle = current_valid_handles[i];
856
857 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
858 ++mapped_valid_handles;
859 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
860 ++mapped_valid_handles;
861 }
862
Tony-LunarG99b880b2019-09-26 11:19:52 -0600863 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700864
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700865 static constexpr const VkDeviceSize k_instance_size = 64;
866 const VkDeviceSize instance_buffer_size = k_instance_size * pInfo->instanceCount;
Jason Macnak83cfd582019-07-31 10:14:24 -0700867
Tony-LunarG1dce2392019-10-23 16:49:29 -0600868 result = desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool, debug_desc_layout,
869 &as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700870 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700871 ReportSetupProblem(device, "Unable to get descriptor set for acceleration structure build.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600872 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700873 return;
874 }
875
876 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
877 descriptor_buffer_infos[0].buffer = instanceData;
878 descriptor_buffer_infos[0].offset = instanceOffset;
879 descriptor_buffer_infos[0].range = instance_buffer_size;
880 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.validation_buffer;
881 descriptor_buffer_infos[1].offset = 0;
882 descriptor_buffer_infos[1].range = validation_buffer_size;
883
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600884 VkWriteDescriptorSet descriptor_set_writes[2] = {
885 LvlInitStruct<VkWriteDescriptorSet>(),
886 LvlInitStruct<VkWriteDescriptorSet>(),
887 };
Jason Macnak83cfd582019-07-31 10:14:24 -0700888 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
889 descriptor_set_writes[0].dstBinding = 0;
890 descriptor_set_writes[0].descriptorCount = 1;
891 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
892 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
Jason Macnak83cfd582019-07-31 10:14:24 -0700893 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
894 descriptor_set_writes[1].dstBinding = 1;
895 descriptor_set_writes[1].descriptorCount = 1;
896 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
897 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
898
899 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
900
901 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600902 auto memory_barrier = LvlInitStruct<VkMemoryBarrier>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700903 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
904 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
905 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
906 &memory_barrier, 0, nullptr, 0, nullptr);
907
908 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600909 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700910 restorable_state.Create(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
911
912 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
913 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
914 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
915 &as_validation_buffer_info.descriptor_set, 0, nullptr);
916 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
917
918 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
919 // have been replaced by the validation compute shader before any builds take place.
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600920 auto instance_buffer_barrier = LvlInitStruct<VkBufferMemoryBarrier>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700921 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
922 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
923 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
924 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
925 instance_buffer_barrier.buffer = instanceData;
926 instance_buffer_barrier.offset = instanceOffset;
927 instance_buffer_barrier.size = instance_buffer_size;
928 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
929 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
930 nullptr);
931
932 // Restore the previous compute pipeline state.
933 restorable_state.Restore(commandBuffer);
934
935 as_validation_state.validation_buffers[commandBuffer].push_back(std::move(as_validation_buffer_info));
936}
937
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600938void GpuAssisted::ProcessAccelerationStructureBuildValidationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700939 if (cb_node == nullptr || !cb_node->hasBuildAccelerationStructureCmd) {
940 return;
941 }
942
Tony-LunarG99b880b2019-09-26 11:19:52 -0600943 auto &as_validation_info = acceleration_structure_validation_state;
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600944 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[cb_node->commandBuffer()];
Jason Macnak83cfd582019-07-31 10:14:24 -0700945 for (const auto &as_validation_buffer_info : as_validation_buffer_infos) {
946 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
947
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700948 VkResult result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation,
949 reinterpret_cast<void **>(&mapped_validation_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700950 if (result == VK_SUCCESS) {
951 if (mapped_validation_buffer->invalid_handle_found > 0) {
952 uint64_t invalid_handle = 0;
953 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
954 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
955
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700956 LogError(as_validation_buffer_info.acceleration_structure, "UNASSIGNED-AccelerationStructure",
957 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
958 "handle (%" PRIu64 ")",
959 invalid_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700960 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600961 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700962 }
963 }
964}
965
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600966void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
967 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
968 VkResult result) {
969 if (VK_SUCCESS != result) return;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600970 ValidationStateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600971 for (uint32_t i = 0; i < bindInfoCount; i++) {
972 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
sourav parmarcd5fb182020-07-17 12:58:44 -0700973 ACCELERATION_STRUCTURE_STATE *as_state = GetAccelerationStructureStateNV(info.accelerationStructure);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600974 if (as_state) {
975 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
976 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600977 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600978}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700979
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600980// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
981void GpuAssisted::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
982 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
983 void *cpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600984 if (aborted) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600985 return;
986 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600987
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600988 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
989
Tony-LunarG99b880b2019-09-26 11:19:52 -0600990 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600991 std::ostringstream strm;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600992 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Karl Schultz7b024b42018-08-30 16:18:18 -0600993 << "Application has too many descriptor sets in the pipeline layout to continue with gpu validation. "
994 << "Validation is not modifying the pipeline layout. "
995 << "Instrumented shaders are replaced with non-instrumented shaders.";
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700996 ReportSetupProblem(device, strm.str().c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -0600997 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700998 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Karl Schultz7b024b42018-08-30 16:18:18 -0600999 }
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -07001000}
1001
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001002void GpuAssisted::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
1003 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
1004 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001005 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1006
Karl Schultz7b024b42018-08-30 16:18:18 -06001007 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001008 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001009 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -06001010 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001011}
1012
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001013// Free the device memory and descriptor set(s) associated with a command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001014void GpuAssisted::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001015 if (aborted) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001016 return;
1017 }
Tony-LunarG1dce2392019-10-23 16:49:29 -06001018 auto gpuav_buffer_list = GetBufferInfo(commandBuffer);
John Zulauf79f06582021-02-27 18:38:39 -07001019 for (const auto &buffer_info : gpuav_buffer_list) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001020 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001021 if (buffer_info.di_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001022 vmaDestroyBuffer(vmaAllocator, buffer_info.di_input_mem_block.buffer, buffer_info.di_input_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001023 }
1024 if (buffer_info.bda_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001025 vmaDestroyBuffer(vmaAllocator, buffer_info.bda_input_mem_block.buffer, buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -06001026 }
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001027 if (buffer_info.desc_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001028 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001029 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001030 if (buffer_info.pre_draw_resources.desc_set != VK_NULL_HANDLE) {
1031 desc_set_manager->PutBackDescriptorSet(buffer_info.pre_draw_resources.desc_pool,
1032 buffer_info.pre_draw_resources.desc_set);
1033 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001034 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001035 command_buffer_map.erase(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001036
Tony-LunarG99b880b2019-09-26 11:19:52 -06001037 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001038 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[commandBuffer];
1039 for (auto &as_validation_buffer_info : as_validation_buffer_infos) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001040 vmaDestroyBuffer(vmaAllocator, as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -07001041 as_validation_buffer_info.validation_buffer_allocation);
1042
1043 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001044 desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool,
1045 as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -07001046 }
1047 }
1048 as_validation_info.validation_buffers.erase(commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -06001049}
Karl Schultz7b024b42018-08-30 16:18:18 -06001050// Just gives a warning about a possible deadlock.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001051bool GpuAssisted::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
1052 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
1053 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1054 uint32_t bufferMemoryBarrierCount,
1055 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
Jeff Bolz5c801d12019-10-09 10:38:45 -05001056 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001057 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001058 ReportSetupProblem(commandBuffer,
Karl Schultz7b024b42018-08-30 16:18:18 -06001059 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1060 "GPU_Assisted validation waits on queue completion. "
1061 "This wait could block the host's signaling of this event, resulting in deadlock.");
1062 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001063 return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001064}
1065
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001066bool GpuAssisted::PreCallValidateCmdWaitEvents2KHR(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
1067 const VkDependencyInfoKHR *pDependencyInfos) const {
1068 VkPipelineStageFlags2KHR srcStageMask = 0;
1069
1070 for (uint32_t i = 0; i < eventCount; i++) {
1071 auto stage_masks = sync_utils::GetGlobalStageMasks(pDependencyInfos[i]);
1072 srcStageMask = stage_masks.src;
1073 }
1074
1075 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
1076 ReportSetupProblem(commandBuffer,
1077 "CmdWaitEvents2KHR recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1078 "GPU_Assisted validation waits on queue completion. "
1079 "This wait could block the host's signaling of this event, resulting in deadlock.");
1080 }
1081 return false;
1082}
1083
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001084void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1085 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
1086 // 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 -06001087 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001088 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
1089 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
1090 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001091 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1092 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001093 }
1094 }
1095}
1096
1097void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1098 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
1099 // 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 -06001100 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001101 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
1102 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
1103 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001104 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1105 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001106 }
1107 }
1108}
1109
1110void GpuAssisted::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1111 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1112 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1113 void *cgpl_state_data) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001114 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001115 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001116 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
1117 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001118 cgpl_state->gpu_create_infos = new_pipeline_create_infos;
1119 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001120}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001121
1122void GpuAssisted::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1123 const VkComputePipelineCreateInfo *pCreateInfos,
1124 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1125 void *ccpl_state_data) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001126 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001127 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001128 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
1129 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001130 ccpl_state->gpu_create_infos = new_pipeline_create_infos;
1131 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
Jason Macnak67407e72019-07-11 11:05:09 -07001132}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001133
1134void GpuAssisted::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1135 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1136 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1137 void *crtpl_state_data) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001138 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001139 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001140 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1141 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001142 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1143 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001144}
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001145
sourav parmarcd5fb182020-07-17 12:58:44 -07001146void GpuAssisted::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
1147 VkPipelineCache pipelineCache, uint32_t count,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001148 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1149 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1150 void *crtpl_state_data) {
1151 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
1152 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001153 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1154 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001155 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1156 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->gpu_create_infos.data());
1157}
Karl Schultz7b024b42018-08-30 16:18:18 -06001158
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001159void GpuAssisted::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1160 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1161 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1162 VkResult result, void *cgpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001163 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
1164 pPipelines, result, cgpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001165 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
1166 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, cgpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001167 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001168}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001169
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001170void GpuAssisted::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1171 const VkComputePipelineCreateInfo *pCreateInfos,
1172 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1173 VkResult result, void *ccpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001174 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1175 result, ccpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001176 create_compute_pipeline_api_state *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
1177 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, ccpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001178 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001179}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001180
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001181void GpuAssisted::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1182 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1183 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1184 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001185 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001186 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
1187 pPipelines, result, crtpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001188 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001189 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Jason Macnak67407e72019-07-11 11:05:09 -07001190}
1191
sourav parmarcd5fb182020-07-17 12:58:44 -07001192void GpuAssisted::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
1193 VkPipelineCache pipelineCache, uint32_t count,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001194 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1195 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1196 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001197 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
sourav parmarcd5fb182020-07-17 12:58:44 -07001198 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesKHR(
1199 device, deferredOperation, pipelineCache, count, pCreateInfos, pAllocator, pPipelines, result, crtpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001200 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001201 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Karl Schultz7b024b42018-08-30 16:18:18 -06001202}
1203
1204// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001205void GpuAssisted::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001206 for (auto it = shader_map.begin(); it != shader_map.end();) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001207 if (it->second.pipeline == pipeline) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001208 it = shader_map.erase(it);
Karl Schultz7b024b42018-08-30 16:18:18 -06001209 } else {
1210 ++it;
1211 }
1212 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001213 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001214}
1215
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001216void GpuAssisted::PreCallRecordDestroyRenderPass(VkDevice device, VkRenderPass renderPass,
1217 const VkAllocationCallbacks *pAllocator) {
1218 auto pipeline = pre_draw_validation_state.renderpass_to_pipeline.find(renderPass);
1219 if (pipeline != pre_draw_validation_state.renderpass_to_pipeline.end()) {
1220 DispatchDestroyPipeline(device, pipeline->second, nullptr);
1221 pre_draw_validation_state.renderpass_to_pipeline.erase(pipeline);
1222 }
1223}
1224
Karl Schultz7b024b42018-08-30 16:18:18 -06001225// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001226bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
1227 uint32_t *unique_shader_id) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001228 if (aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001229 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
1230
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001231 const spvtools::MessageConsumer gpu_console_message_consumer =
Tony-LunarG79641702020-07-13 15:43:05 -06001232 [this](spv_message_level_t level, const char *, const spv_position_t &position, const char *message) -> void {
1233 switch (level) {
1234 case SPV_MSG_FATAL:
1235 case SPV_MSG_INTERNAL_ERROR:
1236 case SPV_MSG_ERROR:
1237 this->LogError(this->device, "UNASSIGNED-GPU-Assisted", "Error during shader instrumentation: line %zu: %s",
1238 position.index, message);
1239 break;
1240 default:
1241 break;
1242 }
1243 };
1244
Karl Schultz7b024b42018-08-30 16:18:18 -06001245 // Load original shader SPIR-V
1246 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
1247 new_pgm.clear();
1248 new_pgm.reserve(num_words);
1249 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
1250
1251 // Call the optimizer to instrument the shader.
1252 // 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 -07001253 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Karl Schultz7b024b42018-08-30 16:18:18 -06001254 using namespace spvtools;
Tony-LunarG8a51b7d2020-07-01 15:57:23 -06001255 spv_target_env target_env = PickSpirvEnv(api_version, (device_extensions.vk_khr_spirv_1_4 != kNotEnabled));
Tony-LunarGf29f77f2020-08-26 15:48:00 -06001256 spvtools::ValidatorOptions val_options;
1257 AdjustValidatorOptions(device_extensions, enabled_features, val_options);
1258 spvtools::OptimizerOptions opt_options;
1259 opt_options.set_run_validator(true);
1260 opt_options.set_validator_options(val_options);
Karl Schultz7b024b42018-08-30 16:18:18 -06001261 Optimizer optimizer(target_env);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001262 optimizer.SetMessageConsumer(gpu_console_message_consumer);
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001263 optimizer.RegisterPass(CreateInstBindlessCheckPass(desc_set_bind_index, unique_shader_module_id, descriptor_indexing,
Tony-LunarGe8632e42020-11-18 17:03:12 -07001264 descriptor_indexing, buffer_oob_enabled, buffer_oob_enabled));
Karl Schultz7b024b42018-08-30 16:18:18 -06001265 optimizer.RegisterPass(CreateAggressiveDCEPass());
Tony-LunarG5c38b182020-06-10 16:15:32 -06001266 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) && shaderInt64 &&
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001267 enabled_features.core12.bufferDeviceAddress) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001268 optimizer.RegisterPass(CreateInstBuffAddrCheckPass(desc_set_bind_index, unique_shader_module_id));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001269 }
Tony-LunarGf29f77f2020-08-26 15:48:00 -06001270 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm, opt_options);
Karl Schultz7b024b42018-08-30 16:18:18 -06001271 if (!pass) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001272 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Karl Schultz7b024b42018-08-30 16:18:18 -06001273 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001274 *unique_shader_id = unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -06001275 return pass;
1276}
Mark Lobodzinski01734072019-02-13 17:39:15 -07001277// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001278void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
1279 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
1280 void *csm_state_data) {
1281 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
1282 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -06001283 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001284 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
1285 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
Karl Schultz7b024b42018-08-30 16:18:18 -06001286 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001287}
Tony-LunarG20678ff2021-05-07 14:56:26 -06001288
Tony-LunarG63f82e02021-04-12 16:13:48 -06001289static const int kInstErrorPreDrawValidate = spvtools::kInstErrorBuffOOBStorageTexel + 1; // TODO - get this into instrument.hpp
1290static const int kPreDrawValidateSubError = spvtools::kInstValidationOutError + 1;
Karl Schultz7b024b42018-08-30 16:18:18 -06001291// Generate the part of the message describing the violation.
Tony-LunarG1a7c9f92021-04-29 16:04:42 -06001292bool 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 -06001293 using namespace spvtools;
1294 std::ostringstream strm;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001295 bool return_code = true;
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001296 assert(kInstErrorPreDrawValidate == _kInstErrorPreDrawValidate);
1297 assert(kInstValidationOutError == _kInstValidationOutError);
Tony-LunarGab47cac2019-12-20 15:28:01 -07001298 switch (debug_record[kInstValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001299 case kInstErrorBindlessBounds: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001300 strm << "Index of " << debug_record[kInstBindlessBoundsOutDescIndex] << " used to index descriptor array of length "
1301 << debug_record[kInstBindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001302 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -06001303 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001304 case kInstErrorBindlessUninit: {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001305 strm << "Descriptor index " << debug_record[kInstBindlessUninitOutDescIndex] << " is uninitialized.";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001306 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -06001307 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001308 case kInstErrorBuffAddrUnallocRef: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001309 uint64_t *ptr = (uint64_t *)&debug_record[kInstBuffAddrUnallocOutDescPtrLo];
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001310 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
1311 vuid_msg = "UNASSIGNED-Device address out of bounds";
1312 } break;
Tony-LunarG7de10e82020-11-24 11:31:55 -07001313 case kInstErrorBuffOOBUniform:
1314 case kInstErrorBuffOOBStorage: {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001315 auto size = debug_record[kInstBindlessBuffOOBOutBuffSize];
1316 if (size == 0) {
1317 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex] << " is uninitialized.";
1318 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
1319 } else {
1320 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex]
1321 << " access out of bounds. Descriptor size is " << debug_record[kInstBindlessBuffOOBOutBuffSize]
Tony-LunarG7de10e82020-11-24 11:31:55 -07001322 << " and highest byte accessed was " << debug_record[kInstBindlessBuffOOBOutBuffOff];
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001323 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001324 if (debug_record[kInstValidationOutError] == kInstErrorBuffOOBUniform)
1325 vuid_msg = vuid.uniform_access_oob;
1326 else
1327 vuid_msg = vuid.storage_access_oob;
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001328 }
1329 } break;
Tony-LunarG7de10e82020-11-24 11:31:55 -07001330 case kInstErrorBuffOOBUniformTexel:
1331 case kInstErrorBuffOOBStorageTexel: {
1332 auto size = debug_record[kInstBindlessBuffOOBOutBuffSize];
1333 if (size == 0) {
1334 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex] << " is uninitialized.";
1335 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001336 } else {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001337 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex]
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001338 << " access out of bounds. Descriptor size is " << debug_record[kInstBindlessBuffOOBOutBuffSize]
1339 << " texels and highest texel accessed was " << debug_record[kInstBindlessBuffOOBOutBuffOff];
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001340 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001341 if (debug_record[kInstValidationOutError] == kInstErrorBuffOOBUniformTexel)
1342 vuid_msg = vuid.uniform_access_oob;
1343 else
1344 vuid_msg = vuid.storage_access_oob;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001345 }
Tony-LunarG63f82e02021-04-12 16:13:48 -06001346 } break;
1347 case kInstErrorPreDrawValidate: {
Tim Van Patten38bdcdd2021-05-14 16:41:00 -06001348 // Buffer size must be >= (stride * (drawCount - 1) + offset + sizeof(VkDrawIndexedIndirectCommand))
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001349 if (debug_record[kPreDrawValidateSubError] == pre_draw_count_exceeds_bufsize_error) {
Tony-LunarG63f82e02021-04-12 16:13:48 -06001350 uint32_t count = debug_record[kPreDrawValidateSubError + 1];
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001351 uint32_t stride = buf_info.pre_draw_resources.stride;
1352 uint32_t offset = static_cast<uint32_t>(buf_info.pre_draw_resources.offset);
1353 uint32_t draw_size = (stride * (count - 1) + offset + sizeof(VkDrawIndexedIndirectCommand));
1354 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
1355 strm << "Indirect draw count of " << count << " would exceed buffer size " << buf_info.pre_draw_resources.buf_size
1356 << " of buffer " << buf_info.pre_draw_resources.buffer << " stride = " << stride << " offset = " << offset
1357 << " (stride * (drawCount - 1) + offset + sizeof(VkDrawIndexedIndirectCommand)) = " << draw_size;
Tony-LunarG64aeaf72021-04-14 11:13:35 -06001358 if (count == 1) {
1359 vuid_msg = vuid.count_exceeds_bufsize_1;
1360 } else {
1361 vuid_msg = vuid.count_exceeds_bufsize;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001362 }
Tony-LunarG1a7c9f92021-04-29 16:04:42 -06001363 } else if (debug_record[kPreDrawValidateSubError] == pre_draw_count_exceeds_limit_error) {
1364 uint32_t count = debug_record[kPreDrawValidateSubError + 1];
1365 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
1366 strm << "Indirect draw count of " << count << " would exceed maxDrawIndirectCount limit of "
1367 << gpu_assisted->phys_dev_props.limits.maxDrawIndirectCount;
1368 vuid_msg = vuid.count_exceeds_device_limit;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001369 } else if (debug_record[kPreDrawValidateSubError] == pre_draw_first_instance_error) {
1370 uint32_t index = debug_record[kPreDrawValidateSubError + 1];
1371 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
1372 strm << "The drawIndirectFirstInstance feature is not enabled, but the firstInstance member of the "
1373 "VkDrawIndirectCommand structure at index "
1374 << index << " is not zero";
1375 vuid_msg = vuid.first_instance_not_zero;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001376 }
1377 return_code = false;
1378 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001379 default: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001380 strm << "Internal Error (unexpected error type = " << debug_record[kInstValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001381 vuid_msg = "UNASSIGNED-Internal Error";
1382 assert(false);
1383 } break;
1384 }
1385 msg = strm.str();
Tony-LunarG63f82e02021-04-12 16:13:48 -06001386 return return_code;
Karl Schultz7b024b42018-08-30 16:18:18 -06001387}
1388
Karl Schultz7b024b42018-08-30 16:18:18 -06001389// Pull together all the information from the debug record to build the error message strings,
1390// and then assemble them into a single message string.
1391// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
1392// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
1393// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
1394// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
1395//
Tony-LunarG7de10e82020-11-24 11:31:55 -07001396void GpuAssisted::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, GpuAssistedBufferInfo &buffer_info,
Tony-LunarG1dce2392019-10-23 16:49:29 -06001397 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001398 using namespace spvtools;
1399 const uint32_t total_words = debug_output_buffer[0];
1400 // A zero here means that the shader instrumentation didn't write anything.
1401 // If you have nothing to say, don't say it here.
1402 if (0 == total_words) {
1403 return;
1404 }
1405 // The first word in the debug output buffer is the number of words that would have
1406 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
1407 // The number of words actually written by the shaders is determined by the size of the buffer
1408 // we provide via the descriptor. So, we process only the number of words that can fit in the
1409 // buffer.
1410 // Each "report" written by the shader instrumentation is considered a "record". This function
1411 // is hard-coded to process only one record because it expects the buffer to be large enough to
1412 // hold only one record. If there is a desire to process more than one record, this function needs
1413 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06001414 std::string validation_message;
1415 std::string stage_message;
1416 std::string common_message;
1417 std::string filename_message;
1418 std::string source_message;
1419 std::string vuid_msg;
1420 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
1421 VkPipeline pipeline_handle = VK_NULL_HANDLE;
1422 std::vector<unsigned int> pgm;
1423 // The first record starts at this offset after the total_words.
1424 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
1425 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
1426 // by the instrumented shader.
Tony-LunarG99b880b2019-09-26 11:19:52 -06001427 auto it = shader_map.find(debug_record[kInstCommonOutShaderId]);
1428 if (it != shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001429 shader_module_handle = it->second.shader_module;
1430 pipeline_handle = it->second.pipeline;
1431 pgm = it->second.pgm;
1432 }
Tony-LunarG1a7c9f92021-04-29 16:04:42 -06001433 bool gen_full_message = GenerateValidationMessage(debug_record, validation_message, vuid_msg, buffer_info, this);
Tony-LunarG63f82e02021-04-12 16:13:48 -06001434 if (gen_full_message) {
1435 UtilGenerateStageMessage(debug_record, stage_message);
1436 UtilGenerateCommonMessage(report_data, command_buffer, debug_record, shader_module_handle, pipeline_handle,
1437 buffer_info.pipeline_bind_point, operation_index, common_message);
1438 UtilGenerateSourceMessages(pgm, debug_record, false, filename_message, source_message);
1439 LogError(queue, vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
1440 filename_message.c_str(), source_message.c_str());
1441 }
1442 else {
1443 LogError(queue, vuid_msg.c_str(), "%s", validation_message.c_str());
1444 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001445 // The debug record at word kInstCommonOutSize is the number of words in the record
1446 // written by the shader. Clear the entire record plus the total_words word at the start.
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001447 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], static_cast<uint32_t>(kInstMaxOutCnt));
Karl Schultz7b024b42018-08-30 16:18:18 -06001448 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
1449}
1450
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001451void GpuAssisted::SetDescriptorInitialized(uint32_t *pData, uint32_t index, const cvdescriptorset::Descriptor *descriptor) {
1452 if (descriptor->GetClass() == cvdescriptorset::DescriptorClass::GeneralBuffer) {
1453 auto buffer = static_cast<const cvdescriptorset::BufferDescriptor *>(descriptor)->GetBuffer();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001454 if (buffer == VK_NULL_HANDLE) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001455 pData[index] = UINT_MAX;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001456 } else {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001457 auto buffer_state = static_cast<const cvdescriptorset::BufferDescriptor *>(descriptor)->GetBufferState();
1458 pData[index] = static_cast<uint32_t>(buffer_state->createInfo.size);
1459 }
1460 } else if (descriptor->GetClass() == cvdescriptorset::DescriptorClass::TexelBuffer) {
1461 auto buffer_view = static_cast<const cvdescriptorset::TexelDescriptor *>(descriptor)->GetBufferView();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001462 if (buffer_view == VK_NULL_HANDLE) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001463 pData[index] = UINT_MAX;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001464 } else {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001465 auto buffer_view_state = static_cast<const cvdescriptorset::TexelDescriptor *>(descriptor)->GetBufferViewState();
1466 pData[index] = static_cast<uint32_t>(buffer_view_state->buffer_state->createInfo.size);
1467 }
1468 } else {
1469 pData[index] = 1;
1470 }
1471}
1472
Tony-LunarG81efe392019-03-07 15:43:27 -07001473// 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 -06001474void GpuAssisted::UpdateInstrumentationBuffer(CMD_BUFFER_STATE *cb_node) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001475 auto gpu_buffer_list = GetBufferInfo(cb_node->commandBuffer());
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001476 uint32_t *data;
Tony-LunarG81efe392019-03-07 15:43:27 -07001477 for (auto &buffer_info : gpu_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001478 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001479 VkResult result =
1480 vmaMapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation, reinterpret_cast<void **>(&data));
Tony-LunarG81efe392019-03-07 15:43:27 -07001481 if (result == VK_SUCCESS) {
John Zulauf79f06582021-02-27 18:38:39 -07001482 for (const auto &update : buffer_info.di_input_mem_block.update_at_submit) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001483 if (update.second->updated) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001484 SetDescriptorInitialized(data, update.first, update.second);
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001485 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001486 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001487 vmaUnmapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07001488 }
1489 }
1490 }
1491}
1492
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001493void GpuAssisted::PreRecordCommandBuffer(VkCommandBuffer command_buffer) {
1494 auto cb_node = GetCBState(command_buffer);
1495 UpdateInstrumentationBuffer(cb_node);
John Zulauf79f06582021-02-27 18:38:39 -07001496 for (auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001497 UpdateInstrumentationBuffer(secondary_cmd_buffer);
1498 }
1499}
1500
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001501void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001502 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1503 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1504 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001505 PreRecordCommandBuffer(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07001506 }
1507 }
1508}
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001509void GpuAssisted::PreCallRecordQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR *pSubmits,
1510 VkFence fence) {
1511 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1512 const VkSubmitInfo2KHR *submit = &pSubmits[submit_idx];
1513 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
1514 PreRecordCommandBuffer(submit->pCommandBufferInfos[i].commandBuffer);
1515 }
1516 }
1517}
1518
1519bool GpuAssisted::CommandBufferNeedsProcessing(VkCommandBuffer command_buffer) {
1520 bool buffers_present = false;
1521 auto cb_node = GetCBState(command_buffer);
1522
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001523 if (GetBufferInfo(cb_node->commandBuffer()).size() || cb_node->hasBuildAccelerationStructureCmd) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001524 buffers_present = true;
1525 }
John Zulauf79f06582021-02-27 18:38:39 -07001526 for (const auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001527 if (GetBufferInfo(secondary_cmd_buffer->commandBuffer()).size() || cb_node->hasBuildAccelerationStructureCmd) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001528 buffers_present = true;
1529 }
1530 }
1531 return buffers_present;
1532}
1533
1534void GpuAssisted::ProcessCommandBuffer(VkQueue queue, VkCommandBuffer command_buffer) {
1535 auto cb_node = GetCBState(command_buffer);
1536
1537 UtilProcessInstrumentationBuffer(queue, cb_node, this);
1538 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
John Zulauf79f06582021-02-27 18:38:39 -07001539 for (auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001540 UtilProcessInstrumentationBuffer(queue, secondary_cmd_buffer, this);
1541 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
1542 }
1543}
Tony-LunarG81efe392019-03-07 15:43:27 -07001544
Karl Schultz58674242019-01-22 15:35:02 -07001545// Issue a memory barrier to make GPU-written data available to host.
1546// Wait for the queue to complete execution.
1547// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001548void GpuAssisted::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
1549 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001550 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001551
Mark Lobodzinski09379db2020-05-07 08:22:01 -06001552 if (aborted || (result != VK_SUCCESS)) return;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001553 bool buffers_present = false;
1554 // Don't QueueWaitIdle if there's nothing to process
1555 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1556 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1557 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001558 buffers_present |= CommandBufferNeedsProcessing(submit->pCommandBuffers[i]);
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001559 }
1560 }
1561 if (!buffers_present) return;
Karl Schultz58674242019-01-22 15:35:02 -07001562
Tony-LunarGb5fae462020-03-05 12:43:25 -07001563 UtilSubmitBarrier(queue, this);
Karl Schultz58674242019-01-22 15:35:02 -07001564
Tony-LunarG152a88b2019-03-20 15:42:24 -06001565 DispatchQueueWaitIdle(queue);
Karl Schultz58674242019-01-22 15:35:02 -07001566
Karl Schultz7b024b42018-08-30 16:18:18 -06001567 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1568 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1569 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001570 ProcessCommandBuffer(queue, submit->pCommandBuffers[i]);
1571 }
1572 }
1573}
1574
1575void GpuAssisted::PostCallRecordQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR *pSubmits,
1576 VkFence fence, VkResult result) {
1577 ValidationStateTracker::PostCallRecordQueueSubmit2KHR(queue, submitCount, pSubmits, fence, result);
1578
1579 if (aborted || (result != VK_SUCCESS)) return;
1580 bool buffers_present = false;
1581 // Don't QueueWaitIdle if there's nothing to process
1582 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1583 const VkSubmitInfo2KHR *submit = &pSubmits[submit_idx];
1584 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
1585 buffers_present |= CommandBufferNeedsProcessing(submit->pCommandBufferInfos[i].commandBuffer);
1586 }
1587 }
1588 if (!buffers_present) return;
1589
1590 UtilSubmitBarrier(queue, this);
1591
1592 DispatchQueueWaitIdle(queue);
1593
1594 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1595 const VkSubmitInfo2KHR *submit = &pSubmits[submit_idx];
1596 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
1597 ProcessCommandBuffer(queue, submit->pCommandBufferInfos[i].commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -06001598 }
1599 }
1600}
Tony-LunarGb2501d22019-01-28 09:59:13 -07001601
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001602void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
1603 uint32_t firstVertex, uint32_t firstInstance) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001604 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAW);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001605}
1606
1607void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
1608 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001609 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXED);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001610}
1611
1612void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
1613 uint32_t stride) {
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001614 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, count, stride, 0, 0};
1615 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECT, &cdi_state);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001616}
1617
1618void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1619 uint32_t count, uint32_t stride) {
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001620 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, count, stride, 0, 0};
1621 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECT, &cdi_state);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001622}
1623
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001624void GpuAssisted::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1625 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1626 uint32_t stride) {
1627 ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1628 maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001629 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1630 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTCOUNT, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001631}
1632
1633void GpuAssisted::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1634 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001635
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001636 uint32_t stride) {
1637 ValidationStateTracker::PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1638 maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001639 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1640 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTCOUNT, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001641}
1642
Tony-LunarG54176fb2020-12-02 10:47:22 -07001643void GpuAssisted::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
1644 uint32_t firstInstance, VkBuffer counterBuffer,
1645 VkDeviceSize counterBufferOffset, uint32_t counterOffset,
1646 uint32_t vertexStride) {
1647 ValidationStateTracker::PreCallRecordCmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer,
1648 counterBufferOffset, counterOffset, vertexStride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001649 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTBYTECOUNTEXT);
Tony-LunarG54176fb2020-12-02 10:47:22 -07001650}
1651
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001652void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1653 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1654 uint32_t maxDrawCount, uint32_t stride) {
1655 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer,
1656 countBufferOffset, maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001657 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1658 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECTCOUNT, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001659}
1660
1661void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1662 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1663 uint32_t maxDrawCount, uint32_t stride) {
1664 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1665 maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001666 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1667 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECTCOUNT, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001668}
1669
1670void GpuAssisted::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
1671 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001672 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001673}
1674
1675void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1676 uint32_t drawCount, uint32_t stride) {
1677 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001678 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSINDIRECTNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001679}
1680
1681void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1682 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1683 uint32_t maxDrawCount, uint32_t stride) {
1684 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer,
1685 countBufferOffset, maxDrawCount, stride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001686 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSINDIRECTCOUNTNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001687}
1688
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001689void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001690 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCH);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001691}
1692
1693void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001694 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHINDIRECT);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001695}
1696
Tony-LunarGd13f9b52020-09-08 15:45:45 -06001697void GpuAssisted::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1698 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1699 uint32_t groupCountZ) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001700 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHBASE);
Tony-LunarGd13f9b52020-09-08 15:45:45 -06001701}
1702
Tony-LunarG52c8c602020-09-10 16:29:56 -06001703void GpuAssisted::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1704 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1705 uint32_t groupCountZ) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001706 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHBASE);
Tony-LunarG52c8c602020-09-10 16:29:56 -06001707}
1708
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001709void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1710 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1711 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1712 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1713 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1714 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1715 uint32_t width, uint32_t height, uint32_t depth) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001716 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, CMD_TRACERAYSNV);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001717}
1718
1719void GpuAssisted::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1720 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1721 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1722 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1723 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1724 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1725 uint32_t width, uint32_t height, uint32_t depth) {
1726 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1727 cb_state->hasTraceRaysCmd = true;
1728}
1729
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001730void GpuAssisted::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001731 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1732 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1733 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1734 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001735 uint32_t height, uint32_t depth) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001736 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, CMD_TRACERAYSKHR);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001737}
1738
1739void GpuAssisted::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001740 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1741 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1742 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1743 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001744 uint32_t height, uint32_t depth) {
1745 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1746 cb_state->hasTraceRaysCmd = true;
1747}
1748
1749void GpuAssisted::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001750 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1751 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1752 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1753 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -07001754 VkDeviceAddress indirectDeviceAddress) {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001755 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, CMD_TRACERAYSINDIRECTKHR);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001756}
1757
1758void GpuAssisted::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001759 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1760 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1761 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1762 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -07001763 VkDeviceAddress indirectDeviceAddress) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001764 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1765 cb_state->hasTraceRaysCmd = true;
1766}
1767
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001768// To generate the pre draw validation shader, run the following from the repository base level
Tony-LunarG20678ff2021-05-07 14:56:26 -06001769// python ./scripts/generate_spirv.py --outfilename ./layers/generated/gpu_pre_draw_shader.h ./layers/gpu_pre_draw_shader.vert
1770// ./External/glslang/build/install/bin/glslangValidator.exe
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001771#include "gpu_pre_draw_shader.h"
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001772void GpuAssisted::AllocatePreDrawValidationResources(GpuAssistedDeviceMemoryBlock output_block,
1773 GpuAssistedPreDrawResources &resources, const LAST_BOUND_STATE &state,
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001774 VkPipeline *pPipeline, const GpuAssistedCmdDrawIndirectState *cdi_state) {
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001775 VkResult result;
1776 if (!pre_draw_validation_state.globals_created) {
1777 auto shader_module_ci = LvlInitStruct<VkShaderModuleCreateInfo>();
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001778 shader_module_ci.codeSize = sizeof(gpu_pre_draw_shader_vert);
1779 shader_module_ci.pCode = gpu_pre_draw_shader_vert;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001780 result =
1781 DispatchCreateShaderModule(device, &shader_module_ci, nullptr, &pre_draw_validation_state.validation_shader_module);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001782 if (result != VK_SUCCESS) {
1783 ReportSetupProblem(device, "Unable to create shader module. Aborting GPU-AV");
1784 aborted = true;
1785 return;
1786 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001787
1788 std::vector<VkDescriptorSetLayoutBinding> bindings;
1789 VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, NULL};
1790 // 0 - output buffer, 1 - count buffer
1791 bindings.push_back(binding);
1792 binding.binding = 1;
1793 bindings.push_back(binding);
1794
1795 VkDescriptorSetLayoutCreateInfo ds_layout_ci = {};
1796 ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
1797 ds_layout_ci.bindingCount = static_cast<uint32_t>(bindings.size());
1798 ds_layout_ci.pBindings = bindings.data();
1799 result = DispatchCreateDescriptorSetLayout(device, &ds_layout_ci, nullptr, &pre_draw_validation_state.validation_ds_layout);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001800 if (result != VK_SUCCESS) {
1801 ReportSetupProblem(device, "Unable to create descriptor set layout. Aborting GPU-AV");
1802 aborted = true;
1803 return;
1804 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001805
1806 const uint32_t push_constant_range_count = 1;
1807 VkPushConstantRange push_constant_ranges[push_constant_range_count] = {};
1808 push_constant_ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
1809 push_constant_ranges[0].offset = 0;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001810 push_constant_ranges[0].size = 4 * sizeof(uint32_t);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001811 VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo[1] = {};
1812 pipelineLayoutCreateInfo[0].sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
1813 pipelineLayoutCreateInfo[0].pNext = NULL;
1814 pipelineLayoutCreateInfo[0].pushConstantRangeCount = push_constant_range_count;
1815 pipelineLayoutCreateInfo[0].pPushConstantRanges = push_constant_ranges;
1816 pipelineLayoutCreateInfo[0].setLayoutCount = 1;
1817 pipelineLayoutCreateInfo[0].pSetLayouts = &pre_draw_validation_state.validation_ds_layout;
1818 result = DispatchCreatePipelineLayout(device, pipelineLayoutCreateInfo, NULL,
1819 &pre_draw_validation_state.validation_pipeline_layout);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001820 if (result != VK_SUCCESS) {
1821 ReportSetupProblem(device, "Unable to create pipeline layout. Aborting GPU-AV");
1822 aborted = true;
1823 return;
1824 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001825
1826 pre_draw_validation_state.globals_created = true;
1827 }
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06001828 VkRenderPass render_pass = state.pipeline_state->rp_state->renderPass();
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001829 assert(render_pass != VK_NULL_HANDLE);
1830 auto pipeline = pre_draw_validation_state.renderpass_to_pipeline.find(render_pass);
1831 if (pipeline == pre_draw_validation_state.renderpass_to_pipeline.end()) {
1832 auto pipeline_stage_ci = LvlInitStruct<VkPipelineShaderStageCreateInfo>();
1833 pipeline_stage_ci.stage = VK_SHADER_STAGE_VERTEX_BIT;
1834 pipeline_stage_ci.module = pre_draw_validation_state.validation_shader_module;
1835 pipeline_stage_ci.pName = "main";
1836
1837 auto graphicsPipelineCreateInfo = LvlInitStruct<VkGraphicsPipelineCreateInfo>();
1838 auto vertexInputState = LvlInitStruct<VkPipelineVertexInputStateCreateInfo>();
1839 auto inputAssemblyState = LvlInitStruct<VkPipelineInputAssemblyStateCreateInfo>();
1840 inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1841 auto rasterizationState = LvlInitStruct<VkPipelineRasterizationStateCreateInfo>();
1842 rasterizationState.rasterizerDiscardEnable = VK_TRUE;
1843 auto colorBlendState = LvlInitStruct<VkPipelineColorBlendStateCreateInfo>();
1844
1845 graphicsPipelineCreateInfo.pVertexInputState = &vertexInputState;
1846 graphicsPipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
1847 graphicsPipelineCreateInfo.pRasterizationState = &rasterizationState;
1848 graphicsPipelineCreateInfo.pColorBlendState = &colorBlendState;
1849 graphicsPipelineCreateInfo.renderPass = render_pass;
1850 graphicsPipelineCreateInfo.layout = pre_draw_validation_state.validation_pipeline_layout;
1851 graphicsPipelineCreateInfo.stageCount = 1;
1852 graphicsPipelineCreateInfo.pStages = &pipeline_stage_ci;
1853
1854 VkPipeline new_pipeline = VK_NULL_HANDLE;
1855 result = DispatchCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, nullptr, &new_pipeline);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001856 if (result != VK_SUCCESS) {
1857 ReportSetupProblem(device, "Unable to create graphics pipeline. Aborting GPU-AV");
1858 aborted = true;
1859 return;
1860 }
1861
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001862 *pPipeline = new_pipeline;
1863 pre_draw_validation_state.renderpass_to_pipeline[render_pass] = new_pipeline;
1864 } else {
1865 *pPipeline = pipeline->second;
1866 }
1867
1868 result = desc_set_manager->GetDescriptorSet(&resources.desc_pool, pre_draw_validation_state.validation_ds_layout,
1869 &resources.desc_set);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001870 if (result != VK_SUCCESS) {
1871 ReportSetupProblem(device, "Unable to allocate descriptor set. Aborting GPU-AV");
1872 aborted = true;
1873 return;
1874 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001875
1876 VkDescriptorBufferInfo buffer_infos[3] = {};
1877 // Error output buffer
1878 buffer_infos[0].buffer = output_block.buffer;
1879 buffer_infos[0].offset = 0;
1880 buffer_infos[0].range = VK_WHOLE_SIZE;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001881 if (cdi_state->count_buffer) {
1882 // Count buffer
1883 buffer_infos[1].buffer = cdi_state->count_buffer;
1884 } else {
1885 // Draw Buffer
1886 buffer_infos[1].buffer = cdi_state->buffer;
1887 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001888 buffer_infos[1].offset = 0;
1889 buffer_infos[1].range = VK_WHOLE_SIZE;
1890
1891 VkWriteDescriptorSet desc_writes[2] = {};
1892 for (auto i = 0; i < 2; i++) {
1893 desc_writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1894 desc_writes[i].dstBinding = i;
1895 desc_writes[i].descriptorCount = 1;
1896 desc_writes[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1897 desc_writes[i].pBufferInfo = &buffer_infos[i];
1898 desc_writes[i].dstSet = resources.desc_set;
1899 }
1900 DispatchUpdateDescriptorSets(device, 2, desc_writes, 0, NULL);
1901}
1902
Tony-LunarG7de10e82020-11-24 11:31:55 -07001903void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point,
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001904 CMD_TYPE cmd_type, const GpuAssistedCmdDrawIndirectState *cdi_state) {
Jason Macnak67407e72019-07-11 11:05:09 -07001905 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1906 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
andreygca287f22019-04-10 00:15:33 +03001907 return;
1908 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001909 VkResult result;
1910
Tony-LunarG99b880b2019-09-26 11:19:52 -06001911 if (aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001912
1913 std::vector<VkDescriptorSet> desc_sets;
1914 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -06001915 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001916 assert(result == VK_SUCCESS);
1917 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001918 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001919 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001920 return;
1921 }
1922
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001923 VkDescriptorBufferInfo output_desc_buffer_info = {};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001924 output_desc_buffer_info.range = output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001925
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001926 auto cb_node = GetCBState(cmd_buffer);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001927 if (!cb_node) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001928 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001929 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001930 return;
1931 }
1932
Tony-LunarG81efe392019-03-07 15:43:27 -07001933 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001934 GpuAssistedDeviceMemoryBlock output_block = {};
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001935 VkBufferCreateInfo buffer_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
1936 buffer_info.size = output_buffer_size;
1937 buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1938 VmaAllocationCreateInfo alloc_info = {};
1939 alloc_info.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
1940 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001941 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001942 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001943 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001944 return;
1945 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001946
Tony-LunarG81efe392019-03-07 15:43:27 -07001947 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001948 uint32_t *data_ptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001949 result = vmaMapMemory(vmaAllocator, output_block.allocation, reinterpret_cast<void **>(&data_ptr));
Tony-LunarG0e564722019-03-19 16:09:14 -06001950 if (result == VK_SUCCESS) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001951 memset(data_ptr, 0, output_buffer_size);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001952 vmaUnmapMemory(vmaAllocator, output_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001953 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001954
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001955 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001956 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
1957 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
1958 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001959 GpuAssistedPreDrawResources pre_draw_resources = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001960 uint32_t desc_count = 1;
locke-lunargb8d7a7a2020-10-25 16:01:52 -06001961 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
1962 auto const &state = cb_node->lastBound[lv_bind_point];
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001963 uint32_t number_of_sets = static_cast<uint32_t>(state.per_set.size());
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001964
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001965 if (validate_draw_indirect && ((cmd_type == CMD_DRAWINDIRECTCOUNT || cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT) ||
1966 ((cmd_type == CMD_DRAWINDIRECT || cmd_type == CMD_DRAWINDEXEDINDIRECT) &&
1967 !(enabled_features.core.drawIndirectFirstInstance)))) {
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001968 // 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 -06001969 //
1970 // NOTE that this validation does not attempt to abort invalid api calls as most other validation does. A crash
1971 // or DEVICE_LOST resulting from the invalid call will prevent preceeding validation errors from being reported.
1972
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001973 assert(bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001974 assert(cdi_state != NULL);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001975 VkPipeline validation_pipeline;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001976 AllocatePreDrawValidationResources(output_block, pre_draw_resources, state, &validation_pipeline, cdi_state);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001977 if (aborted) return;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001978
1979 // Save current graphics pipeline state
1980 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
1981 restorable_state.Create(cb_node, VK_PIPELINE_BIND_POINT_GRAPHICS);
1982
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001983 // Save parameters for error message
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001984 pre_draw_resources.buffer = cdi_state->buffer;
1985 pre_draw_resources.offset = cdi_state->offset;
1986 pre_draw_resources.stride = cdi_state->stride;
1987
1988 uint32_t pushConstants[4] = {};
1989 if (cmd_type == CMD_DRAWINDIRECTCOUNT || cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT) {
1990 if (cdi_state->count_buffer_offset > std::numeric_limits<uint32_t>::max()) {
1991 ReportSetupProblem(device,
1992 "Count buffer offset is larger than can be contained in an unsigned int. Aborting GPU-AV");
1993 aborted = true;
1994 return;
1995 }
1996
1997 // Buffer size must be >= (stride * (drawCount - 1) + offset + sizeof(VkDrawIndirectCommand))
1998 uint32_t struct_size;
1999 if (cmd_type == CMD_DRAWINDIRECTCOUNT) {
2000 struct_size = sizeof(VkDrawIndirectCommand);
2001 } else {
2002 assert(cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT);
2003 struct_size = sizeof(VkDrawIndexedIndirectCommand);
2004 }
2005 BUFFER_STATE *buffer_state = GetBufferState(cdi_state->buffer);
2006 uint32_t max_count;
2007 uint64_t bufsize = buffer_state->createInfo.size;
2008 uint64_t first_command_bytes = struct_size + cdi_state->offset;
2009 if (first_command_bytes > bufsize) {
2010 max_count = 0;
2011 } else {
2012 max_count = 1 + static_cast<uint32_t>(std::floor(((bufsize - first_command_bytes) / cdi_state->stride)));
2013 }
2014 pre_draw_resources.buf_size = buffer_state->createInfo.size;
2015
2016 assert(phys_dev_props.limits.maxDrawIndirectCount > 0);
2017 pushConstants[0] = phys_dev_props.limits.maxDrawIndirectCount;
2018 pushConstants[1] = max_count;
2019 pushConstants[2] = static_cast<uint32_t>((cdi_state->count_buffer_offset / sizeof(uint32_t)));
2020 } else {
2021 pushConstants[0] = 0; // firstInstance check instead of count buffer check
2022 pushConstants[1] = cdi_state->drawCount;
2023 if (cmd_type == CMD_DRAWINDIRECT) {
2024 pushConstants[2] = static_cast<uint32_t>(
2025 ((cdi_state->offset + offsetof(struct VkDrawIndirectCommand, firstInstance)) / sizeof(uint32_t)));
2026 } else {
2027 assert(cmd_type == CMD_DRAWINDEXEDINDIRECT);
2028 pushConstants[2] = static_cast<uint32_t>(
2029 ((cdi_state->offset + offsetof(struct VkDrawIndexedIndirectCommand, firstInstance)) / sizeof(uint32_t)));
2030 }
2031 pushConstants[3] = (cdi_state->stride / sizeof(uint32_t));
2032 }
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06002033
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002034 // Insert diagnostic draw
2035 DispatchCmdBindPipeline(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, validation_pipeline);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002036 DispatchCmdPushConstants(cmd_buffer, pre_draw_validation_state.validation_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0,
2037 sizeof(pushConstants), pushConstants);
2038 DispatchCmdBindDescriptorSets(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
2039 pre_draw_validation_state.validation_pipeline_layout, 0, 1, &pre_draw_resources.desc_set, 0,
2040 nullptr);
2041 DispatchCmdDraw(cmd_buffer, 3, 1, 0, 0);
2042
2043 // Restore the previous graphics pipeline state.
2044 restorable_state.Restore(cmd_buffer);
2045 }
2046
Tony-LunarGe29097a2020-12-03 10:59:19 -07002047 bool has_buffers = false;
Tony-LunarG81efe392019-03-07 15:43:27 -07002048 // Figure out how much memory we need for the input block based on how many sets and bindings there are
2049 // and how big each of the bindings is
Tony-LunarGc28e28a2020-08-14 10:37:48 -06002050 if (number_of_sets > 0 && (descriptor_indexing || buffer_oob_enabled)) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002051 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
2052 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
John Zulauf79f06582021-02-27 18:38:39 -07002053 for (const auto &s : state.per_set) {
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002054 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06002055 if (desc && (desc->GetBindingCount() > 0)) {
2056 auto bindings = desc->GetLayout()->GetSortedBindingSet();
Tony-LunarGa77cade2019-03-06 10:49:22 -07002057 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
2058 for (auto binding : bindings) {
Tony-LunarG7564b382019-08-21 10:11:35 -06002059 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2060 // blocks
Tony-LunarGe29097a2020-12-03 10:59:19 -07002061 auto descriptor_type = desc->GetLayout()->GetTypeFromBinding(binding);
2062 if (descriptor_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
Tony-LunarG7564b382019-08-21 10:11:35 -06002063 descriptor_count++;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07002064 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
2065 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
2066 "validation");
Tony-LunarG7564b382019-08-21 10:11:35 -06002067 } else if (binding == desc->GetLayout()->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002068 descriptor_count += desc->GetVariableDescriptorCount();
2069 } else {
2070 descriptor_count += desc->GetDescriptorCountFromBinding(binding);
2071 }
Tony-LunarGe29097a2020-12-03 10:59:19 -07002072 if (!has_buffers && (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
2073 descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC ||
2074 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
Tony-LunarGe8632e42020-11-18 17:03:12 -07002075 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
2076 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
2077 descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002078 has_buffers = true;
Tony-LunarGa77cade2019-03-06 10:49:22 -07002079 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -06002080 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002081 }
2082 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002083
Tony-LunarGe29097a2020-12-03 10:59:19 -07002084 if (descriptor_indexing || has_buffers) {
2085 // Note that the size of the input buffer is dependent on the maximum binding number, which
2086 // can be very large. This is because for (set = s, binding = b, index = i), the validation
2087 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
2088 // see if descriptors have been written. In gpu_validation.md, we note this and advise
2089 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
2090 uint32_t words_needed;
2091 if (descriptor_indexing) {
2092 words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
2093 } else {
2094 words_needed = 1 + number_of_sets + binding_count + descriptor_count;
2095 }
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002096 alloc_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2097 buffer_info.size = words_needed * 4;
2098 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &di_input_block.buffer, &di_input_block.allocation,
2099 nullptr);
Tony-LunarGe29097a2020-12-03 10:59:19 -07002100 if (result != VK_SUCCESS) {
2101 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
2102 aborted = true;
2103 return;
2104 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002105
Tony-LunarGe29097a2020-12-03 10:59:19 -07002106 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
2107 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
2108 // outline of the input buffer format
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002109 result = vmaMapMemory(vmaAllocator, di_input_block.allocation, reinterpret_cast<void **>(&data_ptr));
2110 memset(data_ptr, 0, static_cast<size_t>(buffer_info.size));
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002111
Tony-LunarGe29097a2020-12-03 10:59:19 -07002112 // Descriptor indexing needs the number of descriptors at each binding.
2113 if (descriptor_indexing) {
2114 // Pointer to a sets array that points into the sizes array
2115 uint32_t *sets_to_sizes = data_ptr + 1;
2116 // Pointer to the sizes array that contains the array size of the descriptor at each binding
2117 uint32_t *sizes = sets_to_sizes + number_of_sets;
2118 // Pointer to another sets array that points into the bindings array that points into the written array
2119 uint32_t *sets_to_bindings = sizes + binding_count;
2120 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
2121 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
2122 // Index of the next entry in the written array to be updated
2123 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
2124 uint32_t bind_counter = number_of_sets + 1;
2125 // Index of the start of the sets_to_bindings array
2126 data_ptr[0] = number_of_sets + binding_count + 1;
2127
John Zulauf79f06582021-02-27 18:38:39 -07002128 for (const auto &s : state.per_set) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002129 auto desc = s.bound_descriptor_set;
2130 if (desc && (desc->GetBindingCount() > 0)) {
2131 auto layout = desc->GetLayout();
2132 auto bindings = layout->GetSortedBindingSet();
2133 // For each set, fill in index of its bindings sizes in the sizes array
2134 *sets_to_sizes++ = bind_counter;
2135 // For each set, fill in the index of its bindings in the bindings_to_written array
2136 *sets_to_bindings++ = bind_counter + number_of_sets + binding_count;
2137 for (auto binding : bindings) {
2138 // For each binding, fill in its size in the sizes array
2139 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2140 // uniform blocks
2141 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2142 sizes[binding] = 1;
2143 } else if (binding == layout->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
2144 sizes[binding] = desc->GetVariableDescriptorCount();
2145 } else {
2146 sizes[binding] = desc->GetDescriptorCountFromBinding(binding);
2147 }
2148 // Fill in the starting index for this binding in the written array in the bindings_to_written array
2149 bindings_to_written[binding] = written_index;
2150
2151 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2152 // uniform blocks
2153 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2154 data_ptr[written_index++] = UINT_MAX;
2155 continue;
2156 }
2157
2158 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
2159 // For each array element in the binding, update the written array with whether it has been written
2160 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
2161 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
2162 if (descriptor->updated) {
2163 SetDescriptorInitialized(data_ptr, written_index, descriptor);
2164 } else if (desc->IsUpdateAfterBind(binding)) {
2165 // If it hasn't been written now and it's update after bind, put it in a list to check at
2166 // QueueSubmit
2167 di_input_block.update_at_submit[written_index] = descriptor;
2168 }
2169 written_index++;
2170 }
2171 }
2172 auto last = desc->GetLayout()->GetMaxBinding();
2173 bindings_to_written += last + 1;
2174 bind_counter += last + 1;
2175 sizes += last + 1;
2176 } else {
2177 *sets_to_sizes++ = 0;
2178 *sets_to_bindings++ = 0;
2179 }
2180 }
2181 } else {
2182 // If no descriptor indexing, we don't need number of descriptors at each binding, so
2183 // no sets_to_sizes or sizes arrays, just sets_to_bindings, bindings_to_written and written_index
2184
2185 // Pointer to sets array that points into the bindings array that points into the written array
2186 uint32_t *sets_to_bindings = data_ptr + 1;
2187 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
2188 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
2189 // Index of the next entry in the written array to be updated
2190 uint32_t written_index = 1 + number_of_sets + binding_count;
2191 uint32_t bind_counter = number_of_sets + 1;
2192 data_ptr[0] = 1;
2193
John Zulauf79f06582021-02-27 18:38:39 -07002194 for (const auto &s : state.per_set) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002195 auto desc = s.bound_descriptor_set;
2196 if (desc && (desc->GetBindingCount() > 0)) {
2197 auto layout = desc->GetLayout();
2198 auto bindings = layout->GetSortedBindingSet();
2199 *sets_to_bindings++ = bind_counter;
2200 for (auto binding : bindings) {
2201 // Fill in the starting index for this binding in the written array in the bindings_to_written array
2202 bindings_to_written[binding] = written_index;
2203
2204 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2205 // uniform blocks
2206 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2207 data_ptr[written_index++] = UINT_MAX;
2208 continue;
2209 }
2210
2211 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
2212
2213 // For each array element in the binding, update the written array with whether it has been written
2214 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
2215 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
2216 if (descriptor->updated) {
2217 SetDescriptorInitialized(data_ptr, written_index, descriptor);
2218 } else if (desc->IsUpdateAfterBind(binding)) {
2219 // If it hasn't been written now and it's update after bind, put it in a list to check at
2220 // QueueSubmit
2221 di_input_block.update_at_submit[written_index] = descriptor;
2222 }
2223 written_index++;
2224 }
2225 }
2226 auto last = desc->GetLayout()->GetMaxBinding();
2227 bindings_to_written += last + 1;
2228 bind_counter += last + 1;
2229 } else {
2230 *sets_to_bindings++ = 0;
2231 }
2232 }
2233 }
2234 vmaUnmapMemory(vmaAllocator, di_input_block.allocation);
2235
2236 di_input_desc_buffer_info.range = (words_needed * 4);
2237 di_input_desc_buffer_info.buffer = di_input_block.buffer;
2238 di_input_desc_buffer_info.offset = 0;
2239
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06002240 desc_writes[1] = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarGe29097a2020-12-03 10:59:19 -07002241 desc_writes[1].dstBinding = 1;
2242 desc_writes[1].descriptorCount = 1;
2243 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2244 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
2245 desc_writes[1].dstSet = desc_sets[0];
2246
2247 desc_count = 2;
2248 }
Tony-LunarG0e564722019-03-19 16:09:14 -06002249 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002250
Tony-LunarGc111b242020-06-30 14:43:45 -06002251 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 -06002252 shaderInt64 && enabled_features.core12.bufferDeviceAddress) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002253 // Example BDA input buffer assuming 2 buffers using BDA:
2254 // Word 0 | Index of start of buffer sizes (in this case 5)
2255 // Word 1 | 0x0000000000000000
2256 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
2257 // Word 3 | Device Address of second buffer
2258 // Word 4 | 0xffffffffffffffff
2259 // Word 5 | 0 (size of pretend buffer at word 1)
2260 // Word 6 | Size in bytes of first buffer
2261 // Word 7 | Size in bytes of second buffer
2262 // Word 8 | 0 (size of pretend buffer in word 4)
2263
Tony-LunarG99b880b2019-09-26 11:19:52 -06002264 uint32_t num_buffers = static_cast<uint32_t>(buffer_map.size());
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002265 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002266 alloc_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2267 buffer_info.size = words_needed * 8; // 64 bit words
Tony-LunarG99b880b2019-09-26 11:19:52 -06002268 result =
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002269 vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &bda_input_block.buffer, &bda_input_block.allocation, nullptr);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002270 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07002271 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002272 aborted = true;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002273 return;
2274 }
2275 uint64_t *bda_data;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002276 result = vmaMapMemory(vmaAllocator, bda_input_block.allocation, reinterpret_cast<void **>(&bda_data));
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002277 uint32_t address_index = 1;
2278 uint32_t size_index = 3 + num_buffers;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002279 memset(bda_data, 0, static_cast<size_t>(buffer_info.size));
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002280 bda_data[0] = size_index; // Start of buffer sizes
2281 bda_data[address_index++] = 0; // NULL address
2282 bda_data[size_index++] = 0;
2283
John Zulauf79f06582021-02-27 18:38:39 -07002284 for (const auto &value : buffer_map) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002285 bda_data[address_index++] = value.first;
2286 bda_data[size_index++] = value.second;
2287 }
2288 bda_data[address_index] = UINTPTR_MAX;
2289 bda_data[size_index] = 0;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002290 vmaUnmapMemory(vmaAllocator, bda_input_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002291
2292 bda_input_desc_buffer_info.range = (words_needed * 8);
2293 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
2294 bda_input_desc_buffer_info.offset = 0;
2295
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06002296 desc_writes[desc_count] = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002297 desc_writes[desc_count].dstBinding = 2;
2298 desc_writes[desc_count].descriptorCount = 1;
2299 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2300 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
2301 desc_writes[desc_count].dstSet = desc_sets[0];
2302 desc_count++;
2303 }
2304
Tony-LunarGb2501d22019-01-28 09:59:13 -07002305 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002306 output_desc_buffer_info.buffer = output_block.buffer;
2307 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002308
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06002309 desc_writes[0] = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002310 desc_writes[0].descriptorCount = 1;
2311 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2312 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
2313 desc_writes[0].dstSet = desc_sets[0];
2314 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002315
locke-lunargb8d7a7a2020-10-25 16:01:52 -06002316 const auto *pipeline_state = state.pipeline_state;
2317 if (pipeline_state) {
2318 if ((pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index) &&
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06002319 !pipeline_state->pipeline_layout->Destroyed()) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -06002320 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout(), desc_set_bind_index, 1,
Tony-LunarG99b880b2019-09-26 11:19:52 -06002321 desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002322 }
Jeremy Gebben9efe1cf2021-05-15 20:05:09 -06002323 if (pipeline_state->pipeline_layout->Destroyed()) {
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002324 ReportSetupProblem(device, "Pipeline layout has been destroyed, aborting GPU-AV");
2325 aborted = true;
2326 } else {
2327 // Record buffer and memory info in CB state tracking
2328 GetBufferInfo(cmd_buffer)
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002329 .emplace_back(output_block, di_input_block, bda_input_block, pre_draw_resources, desc_sets[0], desc_pool,
2330 bind_point, cmd_type);
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002331 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002332 } else {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07002333 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002334 aborted = true;
2335 }
2336 if (aborted) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002337 vmaDestroyBuffer(vmaAllocator, di_input_block.buffer, di_input_block.allocation);
2338 vmaDestroyBuffer(vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
2339 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002340 return;
2341 }
2342}