blob: a5c1642695253cf2d468710b8aff20421e2a8f3a [file] [log] [blame]
Jeremy Gebben4d51c552022-01-06 21:27:15 -07001/* Copyright (c) 2018-2022 The Khronos Group Inc.
2 * Copyright (c) 2018-2022 Valve Corporation
3 * Copyright (c) 2018-2022 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
Tony-LunarG5c38b182020-06-10 16:15:32 -0600187bool GpuAssisted::CheckForDescriptorIndexing(DeviceFeatures enabled_features) const {
188 bool result =
189 (IsExtEnabled(device_extensions.vk_ext_descriptor_indexing) &&
190 (enabled_features.core12.descriptorIndexing || enabled_features.core12.shaderInputAttachmentArrayDynamicIndexing ||
191 enabled_features.core12.shaderUniformTexelBufferArrayDynamicIndexing ||
192 enabled_features.core12.shaderStorageTexelBufferArrayDynamicIndexing ||
193 enabled_features.core12.shaderUniformBufferArrayNonUniformIndexing ||
194 enabled_features.core12.shaderSampledImageArrayNonUniformIndexing ||
195 enabled_features.core12.shaderStorageBufferArrayNonUniformIndexing ||
196 enabled_features.core12.shaderStorageImageArrayNonUniformIndexing ||
197 enabled_features.core12.shaderInputAttachmentArrayNonUniformIndexing ||
198 enabled_features.core12.shaderUniformTexelBufferArrayNonUniformIndexing ||
199 enabled_features.core12.shaderStorageTexelBufferArrayNonUniformIndexing ||
200 enabled_features.core12.descriptorBindingUniformBufferUpdateAfterBind ||
201 enabled_features.core12.descriptorBindingSampledImageUpdateAfterBind ||
202 enabled_features.core12.descriptorBindingStorageImageUpdateAfterBind ||
203 enabled_features.core12.descriptorBindingStorageBufferUpdateAfterBind ||
204 enabled_features.core12.descriptorBindingUniformTexelBufferUpdateAfterBind ||
205 enabled_features.core12.descriptorBindingStorageTexelBufferUpdateAfterBind ||
206 enabled_features.core12.descriptorBindingUpdateUnusedWhilePending ||
207 enabled_features.core12.descriptorBindingPartiallyBound ||
208 enabled_features.core12.descriptorBindingVariableDescriptorCount || enabled_features.core12.runtimeDescriptorArray));
209 return result;
210}
211
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600212void GpuAssisted::PreCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
213 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer, void *cb_state_data) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700214 // Ray tracing acceleration structure instance buffers also need the storage buffer usage as
215 // acceleration structure build validation will find and replace invalid acceleration structure
216 // handles inside of a compute shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600217 create_buffer_api_state *cb_state = reinterpret_cast<create_buffer_api_state *>(cb_state_data);
218 if (cb_state && cb_state->modified_create_info.usage & VK_BUFFER_USAGE_RAY_TRACING_BIT_NV) {
219 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
Jason Macnak83cfd582019-07-31 10:14:24 -0700220 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600221
222 // Validating DrawIndirectCount countBuffer will require validation shader to bind the count buffer as a storage buffer
Tony-LunarG3723a3a2021-05-04 14:52:39 -0600223 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 -0600224 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
225 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -0600226 ValidationStateTracker::PreCallRecordCreateBuffer(device, pCreateInfo, pAllocator, pBuffer, cb_state_data);
Jason Macnak83cfd582019-07-31 10:14:24 -0700227}
228
Karl Schultz7b024b42018-08-30 16:18:18 -0600229// Perform initializations that can be done at Create Device time.
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600230void GpuAssisted::CreateDevice(const VkDeviceCreateInfo *pCreateInfo) {
Jeremy Gebben33717862022-03-28 15:53:56 -0600231 // GpuAssistedBase::CreateDevice will set up bindings
232 VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
233 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT |
234 VK_SHADER_STAGE_MESH_BIT_NV | VK_SHADER_STAGE_TASK_BIT_NV |
235 kShaderStageAllRayTracing,
236 NULL};
237 bindings_.push_back(binding);
238 for (auto i = 1; i < 3; i++) {
239 binding.binding = i;
240 bindings_.push_back(binding);
241 }
242 GpuAssistedBase::CreateDevice(pCreateInfo);
Mark Lobodzinski5dc3dcd2019-04-23 14:26:28 -0600243
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600244 if (enabled_features.core.robustBufferAccess || enabled_features.robustness2_features.robustBufferAccess2) {
245 buffer_oob_enabled = false;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700246 } else {
Tony-LunarGc99dbef2021-06-14 15:11:50 -0600247 std::string bufferoob_string = getLayerOption("khronos_validation.gpuav_buffer_oob");
248 transform(bufferoob_string.begin(), bufferoob_string.end(), bufferoob_string.begin(), ::tolower);
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600249 buffer_oob_enabled = !bufferoob_string.empty() ? !bufferoob_string.compare("true") : true;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700250 }
Tony-LunarGaef435b2021-10-14 14:49:06 -0600251 std::string descriptor_indexing_string = getLayerOption("khronos_validation.gpuav_descriptor_indexing");
252 transform(descriptor_indexing_string.begin(), descriptor_indexing_string.end(), descriptor_indexing_string.begin(), ::tolower);
253 bool validate_descriptor_indexing = !descriptor_indexing_string.empty() ? !descriptor_indexing_string.compare("true") : true;
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600254
Tony-LunarGc99dbef2021-06-14 15:11:50 -0600255 std::string draw_indirect_string = getLayerOption("khronos_validation.validate_draw_indirect");
256 transform(draw_indirect_string.begin(), draw_indirect_string.end(), draw_indirect_string.begin(), ::tolower);
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600257 validate_draw_indirect = !draw_indirect_string.empty() ? !draw_indirect_string.compare("true") : true;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600258
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600259 if (phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700260 ReportSetupProblem(device, "GPU-Assisted validation requires Vulkan 1.1 or later. GPU-Assisted Validation disabled.");
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600261 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600262 return;
263 }
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600264
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600265 DispatchGetPhysicalDeviceFeatures(physical_device, &supported_features);
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600266 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700267 ReportSetupProblem(device,
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600268 "GPU-Assisted validation requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
269 "GPU-Assisted Validation disabled.");
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600270 aborted = true;
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600271 return;
272 }
273
sfricke-samsung45996a42021-09-16 13:45:27 -0700274 if ((IsExtEnabled(device_extensions.vk_ext_buffer_device_address) ||
275 IsExtEnabled(device_extensions.vk_khr_buffer_device_address)) &&
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600276 !supported_features.shaderInt64) {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700277 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
278 "shaderInt64 feature is not available. No buffer device address checking will be attempted");
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600279 }
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600280 shaderInt64 = supported_features.shaderInt64;
281 output_buffer_size = sizeof(uint32_t) * (spvtools::kInstMaxOutCnt + 1);
Tony-LunarGaef435b2021-10-14 14:49:06 -0600282 if (validate_descriptor_indexing) {
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600283 descriptor_indexing = CheckForDescriptorIndexing(enabled_features);
Tony-LunarGaef435b2021-10-14 14:49:06 -0600284 }
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600285 CreateAccelerationStructureBuildValidationState();
Karl Schultz7b024b42018-08-30 16:18:18 -0600286}
287
288// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600289void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600290 DestroyAccelerationStructureBuildValidationState();
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600291 if (pre_draw_validation_state.globals_created) {
292 DispatchDestroyShaderModule(device, pre_draw_validation_state.validation_shader_module, nullptr);
293 DispatchDestroyDescriptorSetLayout(device, pre_draw_validation_state.validation_ds_layout, nullptr);
294 DispatchDestroyPipelineLayout(device, pre_draw_validation_state.validation_pipeline_layout, nullptr);
295 for (auto it = pre_draw_validation_state.renderpass_to_pipeline.begin();
296 it != pre_draw_validation_state.renderpass_to_pipeline.end(); ++it) {
297 DispatchDestroyPipeline(device, it->second, nullptr);
298 }
299 pre_draw_validation_state.renderpass_to_pipeline.clear();
300 pre_draw_validation_state.globals_created = false;
301 }
Jeremy Gebben33717862022-03-28 15:53:56 -0600302 GpuAssistedBase::PreCallRecordDestroyDevice(device, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -0600303}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600304
Jeremy Gebben21782012022-03-15 16:23:27 -0600305void GpuAssisted::CreateAccelerationStructureBuildValidationState() {
306 if (aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700307 return;
308 }
309
Jeremy Gebben21782012022-03-15 16:23:27 -0600310 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700311 if (as_validation_state.initialized) {
312 return;
313 }
314
sfricke-samsung45996a42021-09-16 13:45:27 -0700315 if (!IsExtEnabled(device_extensions.vk_nv_ray_tracing)) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700316 return;
317 }
318
319 // Outline:
320 // - Create valid bottom level acceleration structure which acts as replacement
321 // - Create and load vertex buffer
322 // - Create and load index buffer
323 // - Create, allocate memory for, and bind memory for acceleration structure
324 // - Query acceleration structure handle
325 // - Create command pool and command buffer
326 // - Record build acceleration structure command
327 // - Submit command buffer and wait for completion
328 // - Cleanup
329 // - Create compute pipeline for validating instance buffers
330 // - Create descriptor set layout
331 // - Create pipeline layout
332 // - Create pipeline
333 // - Cleanup
334
335 VkResult result = VK_SUCCESS;
336
337 VkBuffer vbo = VK_NULL_HANDLE;
338 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
339 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600340 auto vbo_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700341 vbo_ci.size = sizeof(float) * 9;
342 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
343
344 VmaAllocationCreateInfo vbo_ai = {};
345 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
346 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
347
Jeremy Gebben21782012022-03-15 16:23:27 -0600348 result = vmaCreateBuffer(vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700349 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700350 ReportSetupProblem(device, "Failed to create vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700351 }
352 }
353
354 if (result == VK_SUCCESS) {
355 uint8_t *mapped_vbo_buffer = nullptr;
Jeremy Gebben21782012022-03-15 16:23:27 -0600356 result = vmaMapMemory(vmaAllocator, vbo_allocation, reinterpret_cast<void **>(&mapped_vbo_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700357 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700358 ReportSetupProblem(device, "Failed to map vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700359 } else {
360 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
361 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Jeremy Gebben21782012022-03-15 16:23:27 -0600362 vmaUnmapMemory(vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700363 }
364 }
365
366 VkBuffer ibo = VK_NULL_HANDLE;
367 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
368 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600369 auto ibo_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700370 ibo_ci.size = sizeof(uint32_t) * 3;
371 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
372
373 VmaAllocationCreateInfo ibo_ai = {};
374 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
375 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
376
Jeremy Gebben21782012022-03-15 16:23:27 -0600377 result = vmaCreateBuffer(vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700378 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700379 ReportSetupProblem(device, "Failed to create index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700380 }
381 }
382
383 if (result == VK_SUCCESS) {
384 uint8_t *mapped_ibo_buffer = nullptr;
Jeremy Gebben21782012022-03-15 16:23:27 -0600385 result = vmaMapMemory(vmaAllocator, ibo_allocation, reinterpret_cast<void **>(&mapped_ibo_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700386 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700387 ReportSetupProblem(device, "Failed to map index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700388 } else {
389 const std::vector<uint32_t> indicies = {0, 1, 2};
390 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Jeremy Gebben21782012022-03-15 16:23:27 -0600391 vmaUnmapMemory(vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700392 }
393 }
394
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600395 auto geometry = LvlInitStruct<VkGeometryNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700396 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600397 geometry.geometry.triangles = LvlInitStruct<VkGeometryTrianglesNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700398 geometry.geometry.triangles.vertexData = vbo;
399 geometry.geometry.triangles.vertexOffset = 0;
400 geometry.geometry.triangles.vertexCount = 3;
401 geometry.geometry.triangles.vertexStride = 12;
402 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
403 geometry.geometry.triangles.indexData = ibo;
404 geometry.geometry.triangles.indexOffset = 0;
405 geometry.geometry.triangles.indexCount = 3;
406 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
407 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
408 geometry.geometry.triangles.transformOffset = 0;
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600409 geometry.geometry.aabbs = LvlInitStruct<VkGeometryAABBNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700410
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600411 auto as_ci = LvlInitStruct<VkAccelerationStructureCreateInfoNV>();
412 as_ci.info = LvlInitStruct<VkAccelerationStructureInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700413 as_ci.info.instanceCount = 0;
414 as_ci.info.geometryCount = 1;
415 as_ci.info.pGeometries = &geometry;
416 if (result == VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600417 result = DispatchCreateAccelerationStructureNV(device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700418 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600419 ReportSetupProblem(device, "Failed to create acceleration structure for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700420 }
421 }
422
423 VkMemoryRequirements2 as_mem_requirements = {};
424 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600425 auto as_mem_requirements_info = LvlInitStruct<VkAccelerationStructureMemoryRequirementsInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700426 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
427 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
428
Jeremy Gebben21782012022-03-15 16:23:27 -0600429 DispatchGetAccelerationStructureMemoryRequirementsNV(device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700430 }
431
432 VmaAllocationInfo as_memory_ai = {};
433 if (result == VK_SUCCESS) {
434 VmaAllocationCreateInfo as_memory_aci = {};
435 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
436
Jeremy Gebben21782012022-03-15 16:23:27 -0600437 result = vmaAllocateMemory(vmaAllocator, &as_mem_requirements.memoryRequirements, &as_memory_aci,
Tony-LunarG99b880b2019-09-26 11:19:52 -0600438 &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700439 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600440 ReportSetupProblem(device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700441 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
442 }
443 }
444
445 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600446 auto as_bind_info = LvlInitStruct<VkBindAccelerationStructureMemoryInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700447 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
448 as_bind_info.memory = as_memory_ai.deviceMemory;
449 as_bind_info.memoryOffset = as_memory_ai.offset;
450
Jeremy Gebben21782012022-03-15 16:23:27 -0600451 result = DispatchBindAccelerationStructureMemoryNV(device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700452 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600453 ReportSetupProblem(device, "Failed to bind acceleration structure memory for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700454 }
455 }
456
457 if (result == VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600458 result = DispatchGetAccelerationStructureHandleNV(device, as_validation_state.replacement_as, sizeof(uint64_t),
459 &as_validation_state.replacement_as_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700460 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600461 ReportSetupProblem(device, "Failed to get acceleration structure handle for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700462 }
463 }
464
465 VkMemoryRequirements2 scratch_mem_requirements = {};
466 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600467 auto scratch_mem_requirements_info = LvlInitStruct<VkAccelerationStructureMemoryRequirementsInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700468 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
469 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
470
Jeremy Gebben21782012022-03-15 16:23:27 -0600471 DispatchGetAccelerationStructureMemoryRequirementsNV(device, &scratch_mem_requirements_info, &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700472 }
473
474 VkBuffer scratch = VK_NULL_HANDLE;
Tony-LunarG18900282020-05-20 12:34:33 -0600475 VmaAllocation scratch_allocation = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700476 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600477 auto scratch_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700478 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
479 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
Jason Macnak83cfd582019-07-31 10:14:24 -0700480 VmaAllocationCreateInfo scratch_aci = {};
481 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
482
Jeremy Gebben21782012022-03-15 16:23:27 -0600483 result = vmaCreateBuffer(vmaAllocator, &scratch_ci, &scratch_aci, &scratch, &scratch_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700484 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600485 ReportSetupProblem(device, "Failed to create scratch buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700486 }
487 }
488
489 VkCommandPool command_pool = VK_NULL_HANDLE;
490 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600491 auto command_pool_ci = LvlInitStruct<VkCommandPoolCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700492 command_pool_ci.queueFamilyIndex = 0;
493
Jeremy Gebben21782012022-03-15 16:23:27 -0600494 result = DispatchCreateCommandPool(device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700495 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600496 ReportSetupProblem(device, "Failed to create command pool for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700497 }
498 }
499
500 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
501
502 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600503 auto command_buffer_ai = LvlInitStruct<VkCommandBufferAllocateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700504 command_buffer_ai.commandPool = command_pool;
505 command_buffer_ai.commandBufferCount = 1;
506 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
507
Jeremy Gebben21782012022-03-15 16:23:27 -0600508 result = DispatchAllocateCommandBuffers(device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700509 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600510 ReportSetupProblem(device, "Failed to create command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700511 }
512
513 // Hook up command buffer dispatch
Jeremy Gebben21782012022-03-15 16:23:27 -0600514 vkSetDeviceLoaderData(device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700515 }
516
517 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600518 auto command_buffer_bi = LvlInitStruct<VkCommandBufferBeginInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700519
520 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
521 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600522 ReportSetupProblem(device, "Failed to begin command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700523 }
524 }
525
526 if (result == VK_SUCCESS) {
527 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
528 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
529 DispatchEndCommandBuffer(command_buffer);
530 }
531
532 VkQueue queue = VK_NULL_HANDLE;
533 if (result == VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600534 DispatchGetDeviceQueue(device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700535
536 // Hook up queue dispatch
Jeremy Gebben21782012022-03-15 16:23:27 -0600537 vkSetDeviceLoaderData(device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700538
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600539 auto submit_info = LvlInitStruct<VkSubmitInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700540 submit_info.commandBufferCount = 1;
541 submit_info.pCommandBuffers = &command_buffer;
542 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
543 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600544 ReportSetupProblem(device, "Failed to submit command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700545 }
546 }
547
548 if (result == VK_SUCCESS) {
549 result = DispatchQueueWaitIdle(queue);
550 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600551 ReportSetupProblem(device, "Failed to wait for queue idle for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700552 }
553 }
554
555 if (vbo != VK_NULL_HANDLE) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600556 vmaDestroyBuffer(vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700557 }
558 if (ibo != VK_NULL_HANDLE) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600559 vmaDestroyBuffer(vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700560 }
561 if (scratch != VK_NULL_HANDLE) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600562 vmaDestroyBuffer(vmaAllocator, scratch, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700563 }
564 if (command_pool != VK_NULL_HANDLE) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600565 DispatchDestroyCommandPool(device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700566 }
567
Jeremy Gebben21782012022-03-15 16:23:27 -0600568 if (debug_desc_layout == VK_NULL_HANDLE) {
569 ReportSetupProblem(device, "Failed to find descriptor set layout for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700570 result = VK_INCOMPLETE;
571 }
572
573 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600574 auto pipeline_layout_ci = LvlInitStruct<VkPipelineLayoutCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700575 pipeline_layout_ci.setLayoutCount = 1;
Jeremy Gebben21782012022-03-15 16:23:27 -0600576 pipeline_layout_ci.pSetLayouts = &debug_desc_layout;
577 result = DispatchCreatePipelineLayout(device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700578 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600579 ReportSetupProblem(device, "Failed to create pipeline layout for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700580 }
581 }
582
583 VkShaderModule shader_module = VK_NULL_HANDLE;
584 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600585 auto shader_module_ci = LvlInitStruct<VkShaderModuleCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700586 shader_module_ci.codeSize = sizeof(kComputeShaderSpirv);
587 shader_module_ci.pCode = (uint32_t *)kComputeShaderSpirv;
588
Jeremy Gebben21782012022-03-15 16:23:27 -0600589 result = DispatchCreateShaderModule(device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700590 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600591 ReportSetupProblem(device, "Failed to create compute shader module for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700592 }
593 }
594
595 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600596 auto pipeline_stage_ci = LvlInitStruct<VkPipelineShaderStageCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700597 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
598 pipeline_stage_ci.module = shader_module;
599 pipeline_stage_ci.pName = "main";
600
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600601 auto pipeline_ci = LvlInitStruct<VkComputePipelineCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700602 pipeline_ci.stage = pipeline_stage_ci;
603 pipeline_ci.layout = as_validation_state.pipeline_layout;
604
Jeremy Gebben21782012022-03-15 16:23:27 -0600605 result = DispatchCreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr, &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700606 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600607 ReportSetupProblem(device, "Failed to create compute pipeline for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700608 }
609 }
610
611 if (shader_module != VK_NULL_HANDLE) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600612 DispatchDestroyShaderModule(device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700613 }
614
615 if (result == VK_SUCCESS) {
616 as_validation_state.initialized = true;
Jeremy Gebben21782012022-03-15 16:23:27 -0600617 LogInfo(device, "UNASSIGNED-GPU-Assisted Validation.", "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700618 } else {
Jeremy Gebben21782012022-03-15 16:23:27 -0600619 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700620 }
621}
622
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600623void GpuAssisted::DestroyAccelerationStructureBuildValidationState() {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600624 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700625 if (as_validation_state.pipeline != VK_NULL_HANDLE) {
626 DispatchDestroyPipeline(device, as_validation_state.pipeline, nullptr);
627 }
628 if (as_validation_state.pipeline_layout != VK_NULL_HANDLE) {
629 DispatchDestroyPipelineLayout(device, as_validation_state.pipeline_layout, nullptr);
630 }
631 if (as_validation_state.replacement_as != VK_NULL_HANDLE) {
632 DispatchDestroyAccelerationStructureNV(device, as_validation_state.replacement_as, nullptr);
633 }
634 if (as_validation_state.replacement_as_allocation != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600635 vmaFreeMemory(vmaAllocator, as_validation_state.replacement_as_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700636 }
637}
638
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600639struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700640 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
641 VkPipeline pipeline = VK_NULL_HANDLE;
642 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
643 std::vector<VkDescriptorSet> descriptor_sets;
644 std::vector<std::vector<uint32_t>> dynamic_offsets;
645 uint32_t push_descriptor_set_index = 0;
646 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
647 std::vector<uint8_t> push_constants_data;
648 PushConstantRangesId push_constants_ranges;
649
650 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
651 pipeline_bind_point = bind_point;
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600652 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
Jason Macnak83cfd582019-07-31 10:14:24 -0700653
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600654 LAST_BOUND_STATE &last_bound = cb_state->lastBound[lv_bind_point];
Jason Macnak83cfd582019-07-31 10:14:24 -0700655 if (last_bound.pipeline_state) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600656 pipeline = last_bound.pipeline_state->pipeline();
Jason Macnak83cfd582019-07-31 10:14:24 -0700657 pipeline_layout = last_bound.pipeline_layout;
658 descriptor_sets.reserve(last_bound.per_set.size());
659 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700660 const auto &bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
ziga-lunarge0b552b2021-09-05 21:39:57 +0200661 if (bound_descriptor_set) {
662 descriptor_sets.push_back(bound_descriptor_set->GetSet());
663 if (bound_descriptor_set->IsPushDescriptor()) {
664 push_descriptor_set_index = static_cast<uint32_t>(i);
665 }
666 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
Jason Macnak83cfd582019-07-31 10:14:24 -0700667 }
Jason Macnak83cfd582019-07-31 10:14:24 -0700668 }
669
670 if (last_bound.push_descriptor_set) {
671 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
672 }
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700673 const auto &pipeline_layout = last_bound.pipeline_state->PipelineLayoutState();
674 if (pipeline_layout->push_constant_ranges == cb_state->push_constant_data_ranges) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700675 push_constants_data = cb_state->push_constant_data;
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700676 push_constants_ranges = pipeline_layout->push_constant_ranges;
Jason Macnak83cfd582019-07-31 10:14:24 -0700677 }
678 }
679 }
680
681 void Restore(VkCommandBuffer command_buffer) const {
682 if (pipeline != VK_NULL_HANDLE) {
683 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
684 if (!descriptor_sets.empty()) {
685 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
686 VkDescriptorSet descriptor_set = descriptor_sets[i];
687 if (descriptor_set != VK_NULL_HANDLE) {
688 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
689 static_cast<uint32_t>(i), 1, &descriptor_set,
690 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
691 }
692 }
693 }
694 if (!push_descriptor_set_writes.empty()) {
695 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
696 static_cast<uint32_t>(push_descriptor_set_writes.size()),
697 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
698 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600699 if (!push_constants_data.empty()) {
700 for (const auto &push_constant_range : *push_constants_ranges) {
701 if (push_constant_range.size == 0) continue;
702 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
703 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
704 }
Jason Macnak83cfd582019-07-31 10:14:24 -0700705 }
706 }
707 }
708};
709
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600710void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
711 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
712 VkDeviceSize instanceOffset, VkBool32 update,
713 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
714 VkBuffer scratch, VkDeviceSize scratchOffset) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -0600715 ValidationStateTracker::PreCallRecordCmdBuildAccelerationStructureNV(commandBuffer, pInfo, instanceData, instanceOffset, update,
716 dst, src, scratch, scratchOffset);
Jason Macnak83cfd582019-07-31 10:14:24 -0700717 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
718 return;
719 }
720
Tony-LunarG99b880b2019-09-26 11:19:52 -0600721 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700722 if (!as_validation_state.initialized) {
723 return;
724 }
725
726 // Empty acceleration structure is valid according to the spec.
727 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
728 return;
729 }
730
Jeremy Gebben135550d2022-03-21 07:15:07 -0600731 auto cb_state = Get<gpuav_state::CommandBuffer>(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700732 assert(cb_state != nullptr);
733
734 std::vector<uint64_t> current_valid_handles;
Jeremy Gebbenb7bfbd02021-11-01 15:17:50 -0600735 ForEach<ACCELERATION_STRUCTURE_STATE>([&current_valid_handles](const ACCELERATION_STRUCTURE_STATE &as_state) {
Jeff Bolz95176d02020-04-01 00:36:16 -0500736 if (as_state.built && as_state.create_infoNV.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700737 current_valid_handles.push_back(as_state.opaque_handle);
738 }
Jeremy Gebbenb7bfbd02021-11-01 15:17:50 -0600739 });
Jason Macnak83cfd582019-07-31 10:14:24 -0700740
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600741 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700742 as_validation_buffer_info.acceleration_structure = dst;
743
744 const VkDeviceSize validation_buffer_size =
745 // One uint for number of instances to validate
746 4 +
747 // Two uint for the replacement acceleration structure handle
748 8 +
749 // One uint for number of invalid handles found
750 4 +
751 // Two uint for the first invalid handle found
752 8 +
753 // One uint for the number of current valid handles
754 4 +
755 // Two uint for each current valid handle
756 (8 * current_valid_handles.size());
757
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600758 auto validation_buffer_create_info = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700759 validation_buffer_create_info.size = validation_buffer_size;
760 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
761
762 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
763 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
764
Tony-LunarG99b880b2019-09-26 11:19:52 -0600765 VkResult result = vmaCreateBuffer(vmaAllocator, &validation_buffer_create_info, &validation_buffer_alloc_info,
766 &as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -0700767 &as_validation_buffer_info.validation_buffer_allocation, nullptr);
768 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700769 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600770 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700771 return;
772 }
773
774 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700775 result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation,
776 reinterpret_cast<void **>(&mapped_validation_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700777 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700778 ReportSetupProblem(device, "Unable to allocate device memory for acceleration structure build val buffer.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600779 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700780 return;
781 }
782
783 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
784 mapped_validation_buffer->replacement_handle_bits_0 =
785 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
786 mapped_validation_buffer->replacement_handle_bits_1 =
787 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
788 mapped_validation_buffer->invalid_handle_found = 0;
789 mapped_validation_buffer->invalid_handle_bits_0 = 0;
790 mapped_validation_buffer->invalid_handle_bits_1 = 0;
791 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
792
793 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
794 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
795 const uint64_t current_valid_handle = current_valid_handles[i];
796
797 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
798 ++mapped_valid_handles;
799 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
800 ++mapped_valid_handles;
801 }
802
Tony-LunarG99b880b2019-09-26 11:19:52 -0600803 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700804
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700805 static constexpr const VkDeviceSize k_instance_size = 64;
806 const VkDeviceSize instance_buffer_size = k_instance_size * pInfo->instanceCount;
Jason Macnak83cfd582019-07-31 10:14:24 -0700807
Tony-LunarG1dce2392019-10-23 16:49:29 -0600808 result = desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool, debug_desc_layout,
809 &as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700810 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700811 ReportSetupProblem(device, "Unable to get descriptor set for acceleration structure build.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600812 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700813 return;
814 }
815
816 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
817 descriptor_buffer_infos[0].buffer = instanceData;
818 descriptor_buffer_infos[0].offset = instanceOffset;
819 descriptor_buffer_infos[0].range = instance_buffer_size;
820 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.validation_buffer;
821 descriptor_buffer_infos[1].offset = 0;
822 descriptor_buffer_infos[1].range = validation_buffer_size;
823
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600824 VkWriteDescriptorSet descriptor_set_writes[2] = {
825 LvlInitStruct<VkWriteDescriptorSet>(),
826 LvlInitStruct<VkWriteDescriptorSet>(),
827 };
Jason Macnak83cfd582019-07-31 10:14:24 -0700828 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
829 descriptor_set_writes[0].dstBinding = 0;
830 descriptor_set_writes[0].descriptorCount = 1;
831 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
832 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
Jason Macnak83cfd582019-07-31 10:14:24 -0700833 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
834 descriptor_set_writes[1].dstBinding = 1;
835 descriptor_set_writes[1].descriptorCount = 1;
836 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
837 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
838
839 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
840
841 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600842 auto memory_barrier = LvlInitStruct<VkMemoryBarrier>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700843 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
844 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
845 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
846 &memory_barrier, 0, nullptr, 0, nullptr);
847
848 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600849 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jeremy Gebben9f537102021-10-05 16:37:12 -0600850 restorable_state.Create(cb_state.get(), VK_PIPELINE_BIND_POINT_COMPUTE);
Jason Macnak83cfd582019-07-31 10:14:24 -0700851
852 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
853 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
854 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
855 &as_validation_buffer_info.descriptor_set, 0, nullptr);
856 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
857
858 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
859 // have been replaced by the validation compute shader before any builds take place.
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600860 auto instance_buffer_barrier = LvlInitStruct<VkBufferMemoryBarrier>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700861 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
862 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
863 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
864 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
865 instance_buffer_barrier.buffer = instanceData;
866 instance_buffer_barrier.offset = instanceOffset;
867 instance_buffer_barrier.size = instance_buffer_size;
868 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
869 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
870 nullptr);
871
872 // Restore the previous compute pipeline state.
873 restorable_state.Restore(commandBuffer);
874
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600875 cb_state->as_validation_buffers.emplace_back(std::move(as_validation_buffer_info));
Jason Macnak83cfd582019-07-31 10:14:24 -0700876}
877
Jeremy Gebben135550d2022-03-21 07:15:07 -0600878void GpuAssisted::ProcessAccelerationStructureBuildValidationBuffer(VkQueue queue, gpuav_state::CommandBuffer *cb_node) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700879 if (cb_node == nullptr || !cb_node->hasBuildAccelerationStructureCmd) {
880 return;
881 }
882
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600883 for (const auto &as_validation_buffer_info : cb_node->as_validation_buffers) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700884 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
885
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700886 VkResult result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation,
887 reinterpret_cast<void **>(&mapped_validation_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700888 if (result == VK_SUCCESS) {
889 if (mapped_validation_buffer->invalid_handle_found > 0) {
890 uint64_t invalid_handle = 0;
891 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
892 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
893
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700894 LogError(as_validation_buffer_info.acceleration_structure, "UNASSIGNED-AccelerationStructure",
895 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
896 "handle (%" PRIu64 ")",
897 invalid_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700898 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600899 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700900 }
901 }
902}
903
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600904void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
905 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
906 VkResult result) {
907 if (VK_SUCCESS != result) return;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600908 ValidationStateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600909 for (uint32_t i = 0; i < bindInfoCount; i++) {
910 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
Jeremy Gebbenb20a8242021-11-05 15:14:43 -0600911 auto as_state = Get<ACCELERATION_STRUCTURE_STATE>(info.accelerationStructure);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600912 if (as_state) {
913 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
914 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600915 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600916}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700917
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600918// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
919void GpuAssisted::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
920 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
921 void *cpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600922 if (aborted) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600923 return;
924 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600925
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600926 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
927
Tony-LunarG99b880b2019-09-26 11:19:52 -0600928 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600929 std::ostringstream strm;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600930 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Karl Schultz7b024b42018-08-30 16:18:18 -0600931 << "Application has too many descriptor sets in the pipeline layout to continue with gpu validation. "
932 << "Validation is not modifying the pipeline layout. "
933 << "Instrumented shaders are replaced with non-instrumented shaders.";
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700934 ReportSetupProblem(device, strm.str().c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -0600935 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700936 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Karl Schultz7b024b42018-08-30 16:18:18 -0600937 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -0600938 ValidationStateTracker::PreCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, cpl_state_data);
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700939}
940
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600941void GpuAssisted::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
942 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
943 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600944 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
945
Karl Schultz7b024b42018-08-30 16:18:18 -0600946 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700947 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600948 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600949 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600950}
951
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600952// Free the device memory and descriptor set(s) associated with a command buffer.
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600953void GpuAssisted::DestroyBuffer(GpuAssistedBufferInfo &buffer_info) {
954 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
955 if (buffer_info.di_input_mem_block.buffer) {
956 vmaDestroyBuffer(vmaAllocator, buffer_info.di_input_mem_block.buffer, buffer_info.di_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -0600957 }
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600958 if (buffer_info.bda_input_mem_block.buffer) {
959 vmaDestroyBuffer(vmaAllocator, buffer_info.bda_input_mem_block.buffer, buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -0600960 }
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600961 if (buffer_info.desc_set != VK_NULL_HANDLE) {
962 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700963 }
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600964 if (buffer_info.pre_draw_resources.desc_set != VK_NULL_HANDLE) {
965 desc_set_manager->PutBackDescriptorSet(buffer_info.pre_draw_resources.desc_pool, buffer_info.pre_draw_resources.desc_set);
966 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600967}
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600968
969void GpuAssisted::DestroyBuffer(GpuAssistedAccelerationStructureBuildValidationBufferInfo &as_validation_buffer_info) {
970 vmaDestroyBuffer(vmaAllocator, as_validation_buffer_info.validation_buffer,
971 as_validation_buffer_info.validation_buffer_allocation);
972
973 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
974 desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool, as_validation_buffer_info.descriptor_set);
975 }
976}
977
Karl Schultz7b024b42018-08-30 16:18:18 -0600978// Just gives a warning about a possible deadlock.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600979bool GpuAssisted::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
980 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
981 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
982 uint32_t bufferMemoryBarrierCount,
983 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
Jeff Bolz5c801d12019-10-09 10:38:45 -0500984 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600985 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700986 ReportSetupProblem(commandBuffer,
Karl Schultz7b024b42018-08-30 16:18:18 -0600987 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
Jeremy Gebbenf18d4362022-01-27 14:37:25 -0700988 "GPU-Assisted validation waits on queue completion. "
Karl Schultz7b024b42018-08-30 16:18:18 -0600989 "This wait could block the host's signaling of this event, resulting in deadlock.");
990 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -0600991 ValidationStateTracker::PreCallValidateCmdWaitEvents(commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask,
992 memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
993 pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600994 return false;
Karl Schultz7b024b42018-08-30 16:18:18 -0600995}
996
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700997bool GpuAssisted::PreCallValidateCmdWaitEvents2KHR(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
998 const VkDependencyInfoKHR *pDependencyInfos) const {
Jeremy Gebbenf18d4362022-01-27 14:37:25 -0700999 VkPipelineStageFlags2KHR src_stage_mask = 0;
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001000
1001 for (uint32_t i = 0; i < eventCount; i++) {
1002 auto stage_masks = sync_utils::GetGlobalStageMasks(pDependencyInfos[i]);
Jeremy Gebbenf18d4362022-01-27 14:37:25 -07001003 src_stage_mask |= stage_masks.src;
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001004 }
1005
Jeremy Gebbenf18d4362022-01-27 14:37:25 -07001006 if (src_stage_mask & VK_PIPELINE_STAGE_HOST_BIT) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001007 ReportSetupProblem(commandBuffer,
1008 "CmdWaitEvents2KHR recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
Jeremy Gebbenf18d4362022-01-27 14:37:25 -07001009 "GPU-Assisted validation waits on queue completion. "
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001010 "This wait could block the host's signaling of this event, resulting in deadlock.");
1011 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001012 ValidationStateTracker::PreCallValidateCmdWaitEvents2KHR(commandBuffer, eventCount, pEvents, pDependencyInfos);
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001013 return false;
1014}
1015
Tony-LunarG1364cf52021-11-17 16:10:11 -07001016bool GpuAssisted::PreCallValidateCmdWaitEvents2(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
1017 const VkDependencyInfo *pDependencyInfos) const {
Jeremy Gebbenf18d4362022-01-27 14:37:25 -07001018 VkPipelineStageFlags2 src_stage_mask = 0;
Tony-LunarG1364cf52021-11-17 16:10:11 -07001019
1020 for (uint32_t i = 0; i < eventCount; i++) {
1021 auto stage_masks = sync_utils::GetGlobalStageMasks(pDependencyInfos[i]);
Jeremy Gebbenf18d4362022-01-27 14:37:25 -07001022 src_stage_mask |= stage_masks.src;
Tony-LunarG1364cf52021-11-17 16:10:11 -07001023 }
1024
Jeremy Gebbenf18d4362022-01-27 14:37:25 -07001025 if (src_stage_mask & VK_PIPELINE_STAGE_HOST_BIT) {
Tony-LunarG1364cf52021-11-17 16:10:11 -07001026 ReportSetupProblem(commandBuffer,
1027 "CmdWaitEvents2 recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
Jeremy Gebbenf18d4362022-01-27 14:37:25 -07001028 "GPU-Assisted validation waits on queue completion. "
Tony-LunarG1364cf52021-11-17 16:10:11 -07001029 "This wait could block the host's signaling of this event, resulting in deadlock.");
1030 }
1031 ValidationStateTracker::PreCallValidateCmdWaitEvents2(commandBuffer, eventCount, pEvents, pDependencyInfos);
1032 return false;
1033}
1034
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001035void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1036 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
1037 // 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 -06001038 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001039 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
1040 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
1041 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001042 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1043 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001044 }
1045 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001046 ValidationStateTracker::PostCallRecordGetPhysicalDeviceProperties(physicalDevice, pPhysicalDeviceProperties);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001047}
1048
1049void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1050 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
1051 // 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 -06001052 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001053 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
1054 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
1055 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001056 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1057 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001058 }
1059 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001060 ValidationStateTracker::PostCallRecordGetPhysicalDeviceProperties2(physicalDevice, pPhysicalDeviceProperties2);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001061}
1062
1063void GpuAssisted::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1064 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1065 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1066 void *cgpl_state_data) {
Tony-LunarG00e7b7d2021-06-30 12:59:43 -06001067 if (aborted) return;
Karl Schultz7b024b42018-08-30 16:18:18 -06001068 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001069 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001070 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
1071 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001072 cgpl_state->gpu_create_infos = new_pipeline_create_infos;
1073 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->gpu_create_infos.data());
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001074 ValidationStateTracker::PreCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1075 cgpl_state_data);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001076}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001077
1078void GpuAssisted::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1079 const VkComputePipelineCreateInfo *pCreateInfos,
1080 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1081 void *ccpl_state_data) {
Tony-LunarG00e7b7d2021-06-30 12:59:43 -06001082 if (aborted) return;
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001083 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001084 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001085 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
1086 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001087 ccpl_state->gpu_create_infos = new_pipeline_create_infos;
1088 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001089 ValidationStateTracker::PreCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1090 ccpl_state_data);
Jason Macnak67407e72019-07-11 11:05:09 -07001091}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001092
1093void GpuAssisted::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1094 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1095 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1096 void *crtpl_state_data) {
Tony-LunarG00e7b7d2021-06-30 12:59:43 -06001097 if (aborted) return;
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001098 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001099 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001100 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1101 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001102 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1103 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001104 ValidationStateTracker::PreCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
1105 pPipelines, crtpl_state_data);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001106}
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001107
sourav parmarcd5fb182020-07-17 12:58:44 -07001108void GpuAssisted::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
1109 VkPipelineCache pipelineCache, uint32_t count,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001110 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1111 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1112 void *crtpl_state_data) {
Tony-LunarG00e7b7d2021-06-30 12:59:43 -06001113 if (aborted) return;
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001114 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
1115 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001116 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1117 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001118 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1119 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->gpu_create_infos.data());
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001120 ValidationStateTracker::PreCallRecordCreateRayTracingPipelinesKHR(device, deferredOperation, pipelineCache, count, pCreateInfos,
1121 pAllocator, pPipelines, crtpl_state_data);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001122}
Karl Schultz7b024b42018-08-30 16:18:18 -06001123
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001124void GpuAssisted::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1125 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1126 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1127 VkResult result, void *cgpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001128 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
1129 pPipelines, result, cgpl_state_data);
Tony-LunarG00e7b7d2021-06-30 12:59:43 -06001130 if (aborted) return;
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001131 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
1132 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, cgpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001133 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001134}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001135
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001136void GpuAssisted::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1137 const VkComputePipelineCreateInfo *pCreateInfos,
1138 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1139 VkResult result, void *ccpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001140 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1141 result, ccpl_state_data);
Tony-LunarG00e7b7d2021-06-30 12:59:43 -06001142 if (aborted) return;
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001143 create_compute_pipeline_api_state *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
1144 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, ccpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001145 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001146}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001147
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001148void GpuAssisted::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1149 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1150 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1151 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001152 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001153 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
1154 pPipelines, result, crtpl_state_data);
Tony-LunarG00e7b7d2021-06-30 12:59:43 -06001155 if (aborted) return;
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001156 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001157 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Jason Macnak67407e72019-07-11 11:05:09 -07001158}
1159
sourav parmarcd5fb182020-07-17 12:58:44 -07001160void GpuAssisted::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
1161 VkPipelineCache pipelineCache, uint32_t count,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001162 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1163 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1164 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001165 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
sourav parmarcd5fb182020-07-17 12:58:44 -07001166 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesKHR(
1167 device, deferredOperation, pipelineCache, count, pCreateInfos, pAllocator, pPipelines, result, crtpl_state_data);
Tony-LunarG00e7b7d2021-06-30 12:59:43 -06001168 if (aborted) return;
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001169 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
aitor-lunarg3c145292022-03-25 17:30:11 +01001170
1171 bool is_operation_deferred = (deferredOperation != VK_NULL_HANDLE && result == VK_OPERATION_DEFERRED_KHR);
1172 if (is_operation_deferred) {
1173 std::vector<safe_VkRayTracingPipelineCreateInfoKHR> infos{pCreateInfos, pCreateInfos + count};
1174 auto register_fn = [this, infos, pAllocator](const std::vector<VkPipeline> &pipelines) {
1175 UtilPostCallRecordPipelineCreations(static_cast<uint32_t>(infos.size()),
1176 reinterpret_cast<const VkRayTracingPipelineCreateInfoKHR *>(infos.data()),
1177 pAllocator, pipelines.data(), VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
1178 };
1179
1180 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
1181 if (wrap_handles) {
1182 deferredOperation = layer_data->Unwrap(deferredOperation);
1183 }
1184 std::vector<std::function<void(const std::vector<VkPipeline> &)>> cleanup_fn;
1185 auto find_res = layer_data->deferred_operation_post_check.pop(deferredOperation);
1186 if (find_res->first) {
1187 cleanup_fn = std::move(find_res->second);
1188 }
1189 cleanup_fn.emplace_back(register_fn);
1190 layer_data->deferred_operation_post_check.insert(deferredOperation, cleanup_fn);
1191 } else {
1192 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR,
1193 this);
1194 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001195}
1196
1197// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001198void GpuAssisted::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001199 for (auto it = shader_map.begin(); it != shader_map.end();) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001200 if (it->second.pipeline == pipeline) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001201 it = shader_map.erase(it);
Karl Schultz7b024b42018-08-30 16:18:18 -06001202 } else {
1203 ++it;
1204 }
1205 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001206 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001207}
1208
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001209void GpuAssisted::PreCallRecordDestroyRenderPass(VkDevice device, VkRenderPass renderPass,
1210 const VkAllocationCallbacks *pAllocator) {
1211 auto pipeline = pre_draw_validation_state.renderpass_to_pipeline.find(renderPass);
1212 if (pipeline != pre_draw_validation_state.renderpass_to_pipeline.end()) {
1213 DispatchDestroyPipeline(device, pipeline->second, nullptr);
1214 pre_draw_validation_state.renderpass_to_pipeline.erase(pipeline);
1215 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001216 ValidationStateTracker::PreCallRecordDestroyRenderPass(device, renderPass, pAllocator);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001217}
1218
Karl Schultz7b024b42018-08-30 16:18:18 -06001219// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
sfricke-samsung7fac88a2022-01-26 11:44:22 -08001220bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<uint32_t> &new_pgm,
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001221 uint32_t *unique_shader_id) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001222 if (aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001223 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
1224
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001225 const spvtools::MessageConsumer gpu_console_message_consumer =
Tony-LunarG79641702020-07-13 15:43:05 -06001226 [this](spv_message_level_t level, const char *, const spv_position_t &position, const char *message) -> void {
1227 switch (level) {
1228 case SPV_MSG_FATAL:
1229 case SPV_MSG_INTERNAL_ERROR:
1230 case SPV_MSG_ERROR:
1231 this->LogError(this->device, "UNASSIGNED-GPU-Assisted", "Error during shader instrumentation: line %zu: %s",
1232 position.index, message);
1233 break;
1234 default:
1235 break;
1236 }
1237 };
1238
Karl Schultz7b024b42018-08-30 16:18:18 -06001239 // Load original shader SPIR-V
1240 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
1241 new_pgm.clear();
1242 new_pgm.reserve(num_words);
1243 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
1244
1245 // Call the optimizer to instrument the shader.
1246 // 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 -07001247 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Karl Schultz7b024b42018-08-30 16:18:18 -06001248 using namespace spvtools;
sfricke-samsung45996a42021-09-16 13:45:27 -07001249 spv_target_env target_env = PickSpirvEnv(api_version, IsExtEnabled(device_extensions.vk_khr_spirv_1_4));
Tony-LunarGf29f77f2020-08-26 15:48:00 -06001250 spvtools::ValidatorOptions val_options;
1251 AdjustValidatorOptions(device_extensions, enabled_features, val_options);
1252 spvtools::OptimizerOptions opt_options;
1253 opt_options.set_run_validator(true);
1254 opt_options.set_validator_options(val_options);
Karl Schultz7b024b42018-08-30 16:18:18 -06001255 Optimizer optimizer(target_env);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001256 optimizer.SetMessageConsumer(gpu_console_message_consumer);
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001257 optimizer.RegisterPass(CreateInstBindlessCheckPass(desc_set_bind_index, unique_shader_module_id, descriptor_indexing,
Tony-LunarGe8632e42020-11-18 17:03:12 -07001258 descriptor_indexing, buffer_oob_enabled, buffer_oob_enabled));
Tony-LunarG57400d42021-10-14 11:18:43 -06001259 // Call CreateAggressiveDCEPass with preserve_interface == true
1260 optimizer.RegisterPass(CreateAggressiveDCEPass(true));
sfricke-samsung45996a42021-09-16 13:45:27 -07001261 if ((IsExtEnabled(device_extensions.vk_ext_buffer_device_address) ||
1262 IsExtEnabled(device_extensions.vk_khr_buffer_device_address)) &&
1263 shaderInt64 && enabled_features.core12.bufferDeviceAddress) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001264 optimizer.RegisterPass(CreateInstBuffAddrCheckPass(desc_set_bind_index, unique_shader_module_id));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001265 }
Tony-LunarGf29f77f2020-08-26 15:48:00 -06001266 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm, opt_options);
Karl Schultz7b024b42018-08-30 16:18:18 -06001267 if (!pass) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001268 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Karl Schultz7b024b42018-08-30 16:18:18 -06001269 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001270 *unique_shader_id = unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -06001271 return pass;
1272}
Mark Lobodzinski01734072019-02-13 17:39:15 -07001273// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001274void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
1275 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
1276 void *csm_state_data) {
1277 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
1278 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -06001279 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001280 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
sfricke-samsung7fac88a2022-01-26 11:44:22 -08001281 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(uint32_t);
Karl Schultz7b024b42018-08-30 16:18:18 -06001282 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001283 ValidationStateTracker::PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, csm_state_data);
Karl Schultz7b024b42018-08-30 16:18:18 -06001284}
Tony-LunarG20678ff2021-05-07 14:56:26 -06001285
Tony-LunarG7345a062021-06-24 13:16:38 -06001286static const int kInstErrorPreDrawValidate = spvtools::kInstErrorMax + 1;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001287static const int kPreDrawValidateSubError = spvtools::kInstValidationOutError + 1;
Karl Schultz7b024b42018-08-30 16:18:18 -06001288// Generate the part of the message describing the violation.
Tony-LunarG1a7c9f92021-04-29 16:04:42 -06001289bool 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 -06001290 using namespace spvtools;
1291 std::ostringstream strm;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001292 bool return_code = true;
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001293 assert(kInstErrorPreDrawValidate == _kInstErrorPreDrawValidate);
1294 assert(kInstValidationOutError == _kInstValidationOutError);
Tony-LunarGab47cac2019-12-20 15:28:01 -07001295 switch (debug_record[kInstValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001296 case kInstErrorBindlessBounds: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001297 strm << "Index of " << debug_record[kInstBindlessBoundsOutDescIndex] << " used to index descriptor array of length "
1298 << debug_record[kInstBindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001299 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -06001300 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001301 case kInstErrorBindlessUninit: {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001302 strm << "Descriptor index " << debug_record[kInstBindlessUninitOutDescIndex] << " is uninitialized.";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001303 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -06001304 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001305 case kInstErrorBuffAddrUnallocRef: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001306 uint64_t *ptr = (uint64_t *)&debug_record[kInstBuffAddrUnallocOutDescPtrLo];
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001307 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
1308 vuid_msg = "UNASSIGNED-Device address out of bounds";
1309 } break;
Tony-LunarG7de10e82020-11-24 11:31:55 -07001310 case kInstErrorBuffOOBUniform:
1311 case kInstErrorBuffOOBStorage: {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001312 auto size = debug_record[kInstBindlessBuffOOBOutBuffSize];
1313 if (size == 0) {
1314 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex] << " is uninitialized.";
1315 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
1316 } else {
1317 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex]
1318 << " access out of bounds. Descriptor size is " << debug_record[kInstBindlessBuffOOBOutBuffSize]
Tony-LunarG7de10e82020-11-24 11:31:55 -07001319 << " and highest byte accessed was " << debug_record[kInstBindlessBuffOOBOutBuffOff];
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001320 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001321 if (debug_record[kInstValidationOutError] == kInstErrorBuffOOBUniform)
1322 vuid_msg = vuid.uniform_access_oob;
1323 else
1324 vuid_msg = vuid.storage_access_oob;
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001325 }
1326 } break;
Tony-LunarG7de10e82020-11-24 11:31:55 -07001327 case kInstErrorBuffOOBUniformTexel:
1328 case kInstErrorBuffOOBStorageTexel: {
1329 auto size = debug_record[kInstBindlessBuffOOBOutBuffSize];
1330 if (size == 0) {
1331 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex] << " is uninitialized.";
1332 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001333 } else {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001334 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex]
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001335 << " access out of bounds. Descriptor size is " << debug_record[kInstBindlessBuffOOBOutBuffSize]
1336 << " texels and highest texel accessed was " << debug_record[kInstBindlessBuffOOBOutBuffOff];
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001337 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001338 if (debug_record[kInstValidationOutError] == kInstErrorBuffOOBUniformTexel)
1339 vuid_msg = vuid.uniform_access_oob;
1340 else
1341 vuid_msg = vuid.storage_access_oob;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001342 }
Tony-LunarG63f82e02021-04-12 16:13:48 -06001343 } break;
1344 case kInstErrorPreDrawValidate: {
Tim Van Patten38bdcdd2021-05-14 16:41:00 -06001345 // Buffer size must be >= (stride * (drawCount - 1) + offset + sizeof(VkDrawIndexedIndirectCommand))
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001346 if (debug_record[kPreDrawValidateSubError] == pre_draw_count_exceeds_bufsize_error) {
Tony-LunarG63f82e02021-04-12 16:13:48 -06001347 uint32_t count = debug_record[kPreDrawValidateSubError + 1];
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001348 uint32_t stride = buf_info.pre_draw_resources.stride;
1349 uint32_t offset = static_cast<uint32_t>(buf_info.pre_draw_resources.offset);
1350 uint32_t draw_size = (stride * (count - 1) + offset + sizeof(VkDrawIndexedIndirectCommand));
1351 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
1352 strm << "Indirect draw count of " << count << " would exceed buffer size " << buf_info.pre_draw_resources.buf_size
1353 << " of buffer " << buf_info.pre_draw_resources.buffer << " stride = " << stride << " offset = " << offset
1354 << " (stride * (drawCount - 1) + offset + sizeof(VkDrawIndexedIndirectCommand)) = " << draw_size;
Tony-LunarG64aeaf72021-04-14 11:13:35 -06001355 if (count == 1) {
1356 vuid_msg = vuid.count_exceeds_bufsize_1;
1357 } else {
1358 vuid_msg = vuid.count_exceeds_bufsize;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001359 }
Tony-LunarG1a7c9f92021-04-29 16:04:42 -06001360 } else if (debug_record[kPreDrawValidateSubError] == pre_draw_count_exceeds_limit_error) {
1361 uint32_t count = debug_record[kPreDrawValidateSubError + 1];
1362 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
1363 strm << "Indirect draw count of " << count << " would exceed maxDrawIndirectCount limit of "
1364 << gpu_assisted->phys_dev_props.limits.maxDrawIndirectCount;
1365 vuid_msg = vuid.count_exceeds_device_limit;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001366 } else if (debug_record[kPreDrawValidateSubError] == pre_draw_first_instance_error) {
1367 uint32_t index = debug_record[kPreDrawValidateSubError + 1];
1368 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
1369 strm << "The drawIndirectFirstInstance feature is not enabled, but the firstInstance member of the "
1370 "VkDrawIndirectCommand structure at index "
1371 << index << " is not zero";
1372 vuid_msg = vuid.first_instance_not_zero;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001373 }
1374 return_code = false;
1375 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001376 default: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001377 strm << "Internal Error (unexpected error type = " << debug_record[kInstValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001378 vuid_msg = "UNASSIGNED-Internal Error";
1379 assert(false);
1380 } break;
1381 }
1382 msg = strm.str();
Tony-LunarG63f82e02021-04-12 16:13:48 -06001383 return return_code;
Karl Schultz7b024b42018-08-30 16:18:18 -06001384}
1385
Karl Schultz7b024b42018-08-30 16:18:18 -06001386// Pull together all the information from the debug record to build the error message strings,
1387// and then assemble them into a single message string.
1388// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
1389// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
1390// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
1391// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
1392//
Tony-LunarG7de10e82020-11-24 11:31:55 -07001393void GpuAssisted::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, GpuAssistedBufferInfo &buffer_info,
Tony-LunarG1dce2392019-10-23 16:49:29 -06001394 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001395 using namespace spvtools;
1396 const uint32_t total_words = debug_output_buffer[0];
1397 // A zero here means that the shader instrumentation didn't write anything.
1398 // If you have nothing to say, don't say it here.
1399 if (0 == total_words) {
1400 return;
1401 }
1402 // The first word in the debug output buffer is the number of words that would have
1403 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
1404 // The number of words actually written by the shaders is determined by the size of the buffer
1405 // we provide via the descriptor. So, we process only the number of words that can fit in the
1406 // buffer.
1407 // Each "report" written by the shader instrumentation is considered a "record". This function
1408 // is hard-coded to process only one record because it expects the buffer to be large enough to
1409 // hold only one record. If there is a desire to process more than one record, this function needs
1410 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06001411 std::string validation_message;
1412 std::string stage_message;
1413 std::string common_message;
1414 std::string filename_message;
1415 std::string source_message;
1416 std::string vuid_msg;
1417 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
1418 VkPipeline pipeline_handle = VK_NULL_HANDLE;
sfricke-samsung7fac88a2022-01-26 11:44:22 -08001419 std::vector<uint32_t> pgm;
Karl Schultz7b024b42018-08-30 16:18:18 -06001420 // The first record starts at this offset after the total_words.
1421 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
1422 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
1423 // by the instrumented shader.
Tony-LunarG99b880b2019-09-26 11:19:52 -06001424 auto it = shader_map.find(debug_record[kInstCommonOutShaderId]);
1425 if (it != shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001426 shader_module_handle = it->second.shader_module;
1427 pipeline_handle = it->second.pipeline;
1428 pgm = it->second.pgm;
1429 }
Tony-LunarG1a7c9f92021-04-29 16:04:42 -06001430 bool gen_full_message = GenerateValidationMessage(debug_record, validation_message, vuid_msg, buffer_info, this);
Tony-LunarG63f82e02021-04-12 16:13:48 -06001431 if (gen_full_message) {
1432 UtilGenerateStageMessage(debug_record, stage_message);
1433 UtilGenerateCommonMessage(report_data, command_buffer, debug_record, shader_module_handle, pipeline_handle,
1434 buffer_info.pipeline_bind_point, operation_index, common_message);
1435 UtilGenerateSourceMessages(pgm, debug_record, false, filename_message, source_message);
1436 LogError(queue, vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
1437 filename_message.c_str(), source_message.c_str());
1438 }
1439 else {
1440 LogError(queue, vuid_msg.c_str(), "%s", validation_message.c_str());
1441 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001442 // The debug record at word kInstCommonOutSize is the number of words in the record
1443 // written by the shader. Clear the entire record plus the total_words word at the start.
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001444 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], static_cast<uint32_t>(kInstMaxOutCnt));
Karl Schultz7b024b42018-08-30 16:18:18 -06001445 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
1446}
1447
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001448// For the given command buffer, map its debug data buffers and read their contents for analysis.
1449void GpuAssisted::ProcessInstrumentationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_base) {
1450 auto *cb_node = static_cast<gpuav_state::CommandBuffer *>(cb_base);
1451 if (cb_node && (cb_node->hasDrawCmd || cb_node->hasTraceRaysCmd || cb_node->hasDispatchCmd)) {
1452 auto &gpu_buffer_list = cb_node->gpuav_buffer_list;
1453 uint32_t draw_index = 0;
1454 uint32_t compute_index = 0;
1455 uint32_t ray_trace_index = 0;
1456
1457 for (auto &buffer_info : gpu_buffer_list) {
1458 char *pData;
1459
1460 uint32_t operation_index = 0;
1461 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1462 operation_index = draw_index;
1463 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1464 operation_index = compute_index;
1465 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1466 operation_index = ray_trace_index;
1467 } else {
1468 assert(false);
1469 }
1470
1471 VkResult result = vmaMapMemory(vmaAllocator, buffer_info.output_mem_block.allocation, (void **)&pData);
1472 if (result == VK_SUCCESS) {
1473 AnalyzeAndGenerateMessages(cb_node->commandBuffer(), queue, buffer_info, operation_index, (uint32_t *)pData);
1474 vmaUnmapMemory(vmaAllocator, buffer_info.output_mem_block.allocation);
1475 }
1476
1477 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1478 draw_index++;
1479 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1480 compute_index++;
1481 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1482 ray_trace_index++;
1483 } else {
1484 assert(false);
1485 }
1486 }
1487 }
1488}
1489
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001490void GpuAssisted::SetDescriptorInitialized(uint32_t *pData, uint32_t index, const cvdescriptorset::Descriptor *descriptor) {
1491 if (descriptor->GetClass() == cvdescriptorset::DescriptorClass::GeneralBuffer) {
1492 auto buffer = static_cast<const cvdescriptorset::BufferDescriptor *>(descriptor)->GetBuffer();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001493 if (buffer == VK_NULL_HANDLE) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001494 pData[index] = UINT_MAX;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001495 } else {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001496 auto buffer_state = static_cast<const cvdescriptorset::BufferDescriptor *>(descriptor)->GetBufferState();
1497 pData[index] = static_cast<uint32_t>(buffer_state->createInfo.size);
1498 }
1499 } else if (descriptor->GetClass() == cvdescriptorset::DescriptorClass::TexelBuffer) {
1500 auto buffer_view = static_cast<const cvdescriptorset::TexelDescriptor *>(descriptor)->GetBufferView();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001501 if (buffer_view == VK_NULL_HANDLE) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001502 pData[index] = UINT_MAX;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001503 } else {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001504 auto buffer_view_state = static_cast<const cvdescriptorset::TexelDescriptor *>(descriptor)->GetBufferViewState();
1505 pData[index] = static_cast<uint32_t>(buffer_view_state->buffer_state->createInfo.size);
1506 }
ziga7a255fb2021-11-20 21:17:07 +01001507 } else if (descriptor->GetClass() == cvdescriptorset::DescriptorClass::Mutable) {
1508 if (descriptor->active_descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
1509 descriptor->active_descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
1510 descriptor->active_descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
1511 descriptor->active_descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) {
1512 const auto size = static_cast<const cvdescriptorset::MutableDescriptor *>(descriptor)->GetBufferSize();
1513 pData[index] = static_cast<uint32_t>(size);
1514 } else {
1515 pData[index] = 1;
1516 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001517 } else {
1518 pData[index] = 1;
1519 }
1520}
1521
Tony-LunarG81efe392019-03-07 15:43:27 -07001522// For the given command buffer, map its debug data buffers and update the status of any update after bind descriptors
Jeremy Gebben135550d2022-03-21 07:15:07 -06001523void GpuAssisted::UpdateInstrumentationBuffer(gpuav_state::CommandBuffer *cb_node) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001524 uint32_t *data;
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06001525 for (auto &buffer_info : cb_node->gpuav_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001526 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001527 VkResult result =
1528 vmaMapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation, reinterpret_cast<void **>(&data));
Tony-LunarG81efe392019-03-07 15:43:27 -07001529 if (result == VK_SUCCESS) {
John Zulauf79f06582021-02-27 18:38:39 -07001530 for (const auto &update : buffer_info.di_input_mem_block.update_at_submit) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001531 if (update.second->updated) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001532 SetDescriptorInitialized(data, update.first, update.second);
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001533 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001534 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001535 vmaUnmapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07001536 }
1537 }
1538 }
1539}
1540
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001541void GpuAssisted::PreRecordCommandBuffer(VkCommandBuffer command_buffer) {
Jeremy Gebben135550d2022-03-21 07:15:07 -06001542 auto cb_node = Get<gpuav_state::CommandBuffer>(command_buffer);
Jeremy Gebben9f537102021-10-05 16:37:12 -06001543 UpdateInstrumentationBuffer(cb_node.get());
John Zulauf79f06582021-02-27 18:38:39 -07001544 for (auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebben135550d2022-03-21 07:15:07 -06001545 UpdateInstrumentationBuffer(static_cast<gpuav_state::CommandBuffer *>(secondary_cmd_buffer));
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001546 }
1547}
1548
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001549void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001550 ValidationStateTracker::PreCallRecordQueueSubmit(queue, submitCount, pSubmits, fence);
Tony-LunarG81efe392019-03-07 15:43:27 -07001551 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1552 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1553 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001554 PreRecordCommandBuffer(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07001555 }
1556 }
1557}
Tony-LunarG26fe2842021-11-16 14:07:59 -07001558
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001559void GpuAssisted::PreCallRecordQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR *pSubmits,
1560 VkFence fence) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001561 ValidationStateTracker::PreCallRecordQueueSubmit2KHR(queue, submitCount, pSubmits, fence);
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001562 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1563 const VkSubmitInfo2KHR *submit = &pSubmits[submit_idx];
1564 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
1565 PreRecordCommandBuffer(submit->pCommandBufferInfos[i].commandBuffer);
1566 }
1567 }
1568}
1569
Tony-LunarG26fe2842021-11-16 14:07:59 -07001570void GpuAssisted::PreCallRecordQueueSubmit2(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2 *pSubmits, VkFence fence) {
1571 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1572 const VkSubmitInfo2 *submit = &pSubmits[submit_idx];
1573 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
1574 PreRecordCommandBuffer(submit->pCommandBufferInfos[i].commandBuffer);
1575 }
1576 }
1577}
1578
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001579bool GpuAssisted::CommandBufferNeedsProcessing(VkCommandBuffer command_buffer) {
1580 bool buffers_present = false;
Jeremy Gebben135550d2022-03-21 07:15:07 -06001581 auto cb_node = Get<gpuav_state::CommandBuffer>(command_buffer);
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001582
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06001583 if (cb_node->gpuav_buffer_list.size() || cb_node->hasBuildAccelerationStructureCmd) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001584 buffers_present = true;
1585 }
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06001586 for (const auto *secondary : cb_node->linkedCommandBuffers) {
Jeremy Gebben135550d2022-03-21 07:15:07 -06001587 auto secondary_cmd_buffer = static_cast<const gpuav_state::CommandBuffer *>(secondary);
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06001588 if (secondary_cmd_buffer->gpuav_buffer_list.size() || cb_node->hasBuildAccelerationStructureCmd) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001589 buffers_present = true;
1590 }
1591 }
1592 return buffers_present;
1593}
1594
1595void GpuAssisted::ProcessCommandBuffer(VkQueue queue, VkCommandBuffer command_buffer) {
Jeremy Gebben135550d2022-03-21 07:15:07 -06001596 auto cb_node = Get<gpuav_state::CommandBuffer>(command_buffer);
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001597
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001598 ProcessInstrumentationBuffer(queue, cb_node.get());
Jeremy Gebben9f537102021-10-05 16:37:12 -06001599 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node.get());
John Zulauf79f06582021-02-27 18:38:39 -07001600 for (auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001601 ProcessInstrumentationBuffer(queue, static_cast<gpuav_state::CommandBuffer *>(secondary_cmd_buffer));
Jeremy Gebben9f537102021-10-05 16:37:12 -06001602 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node.get());
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001603 }
1604}
Tony-LunarG81efe392019-03-07 15:43:27 -07001605
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001606void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
1607 uint32_t firstVertex, uint32_t firstInstance) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001608 ValidationStateTracker::PreCallRecordCmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001609 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAW);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001610}
1611
Tony-LunarG745150c2021-07-02 15:07:31 -06001612void GpuAssisted::PreCallRecordCmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint32_t drawCount,
1613 const VkMultiDrawInfoEXT *pVertexInfo, uint32_t instanceCount,
1614 uint32_t firstInstance, uint32_t stride) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001615 ValidationStateTracker::PreCallRecordCmdDrawMultiEXT(commandBuffer, drawCount, pVertexInfo, instanceCount, firstInstance,
1616 stride);
Tony-LunarG745150c2021-07-02 15:07:31 -06001617 for (uint32_t i = 0; i < drawCount; i++) {
1618 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMULTIEXT);
1619 }
1620}
1621
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001622void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
1623 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001624 ValidationStateTracker::PreCallRecordCmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset,
1625 firstInstance);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001626 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXED);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001627}
1628
Tony-LunarG745150c2021-07-02 15:07:31 -06001629void GpuAssisted::PreCallRecordCmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer, uint32_t drawCount,
1630 const VkMultiDrawIndexedInfoEXT *pIndexInfo, uint32_t instanceCount,
1631 uint32_t firstInstance, uint32_t stride, const int32_t *pVertexOffset) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001632 ValidationStateTracker::PreCallRecordCmdDrawMultiIndexedEXT(commandBuffer, drawCount, pIndexInfo, instanceCount, firstInstance,
1633 stride, pVertexOffset);
Tony-LunarG745150c2021-07-02 15:07:31 -06001634 for (uint32_t i = 0; i < drawCount; i++) {
1635 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMULTIINDEXEDEXT);
1636 }
1637}
1638
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001639void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
1640 uint32_t stride) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001641 ValidationStateTracker::PreCallRecordCmdDrawIndirect(commandBuffer, buffer, offset, count, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001642 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, count, stride, 0, 0};
1643 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECT, &cdi_state);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001644}
1645
1646void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1647 uint32_t count, uint32_t stride) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001648 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001649 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, count, stride, 0, 0};
1650 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECT, &cdi_state);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001651}
1652
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001653void GpuAssisted::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1654 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1655 uint32_t stride) {
1656 ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1657 maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001658 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
sfricke-samsung85584a72021-09-30 21:43:38 -07001659 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTCOUNTKHR, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001660}
1661
1662void GpuAssisted::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1663 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001664
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001665 uint32_t stride) {
1666 ValidationStateTracker::PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1667 maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001668 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1669 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTCOUNT, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001670}
1671
Tony-LunarG54176fb2020-12-02 10:47:22 -07001672void GpuAssisted::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
1673 uint32_t firstInstance, VkBuffer counterBuffer,
1674 VkDeviceSize counterBufferOffset, uint32_t counterOffset,
1675 uint32_t vertexStride) {
1676 ValidationStateTracker::PreCallRecordCmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer,
1677 counterBufferOffset, counterOffset, vertexStride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001678 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTBYTECOUNTEXT);
Tony-LunarG54176fb2020-12-02 10:47:22 -07001679}
1680
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001681void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1682 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1683 uint32_t maxDrawCount, uint32_t stride) {
1684 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer,
1685 countBufferOffset, maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001686 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
sfricke-samsung85584a72021-09-30 21:43:38 -07001687 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECTCOUNTKHR, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001688}
1689
1690void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1691 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1692 uint32_t maxDrawCount, uint32_t stride) {
1693 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1694 maxDrawCount, stride);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001695 GpuAssistedCmdDrawIndirectState cdi_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1696 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECTCOUNT, &cdi_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001697}
1698
1699void GpuAssisted::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
1700 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001701 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001702}
1703
1704void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1705 uint32_t drawCount, uint32_t stride) {
1706 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001707 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSINDIRECTNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001708}
1709
1710void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1711 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1712 uint32_t maxDrawCount, uint32_t stride) {
1713 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer,
1714 countBufferOffset, maxDrawCount, stride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001715 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSINDIRECTCOUNTNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001716}
1717
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001718void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001719 ValidationStateTracker::PreCallRecordCmdDispatch(commandBuffer, x, y, z);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001720 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCH);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001721}
1722
1723void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001724 ValidationStateTracker::PreCallRecordCmdDispatchIndirect(commandBuffer, buffer, offset);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001725 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHINDIRECT);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001726}
1727
Tony-LunarGd13f9b52020-09-08 15:45:45 -06001728void GpuAssisted::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1729 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1730 uint32_t groupCountZ) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001731 ValidationStateTracker::PreCallRecordCmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX,
1732 groupCountY, groupCountZ);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001733 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHBASE);
Tony-LunarGd13f9b52020-09-08 15:45:45 -06001734}
1735
Tony-LunarG52c8c602020-09-10 16:29:56 -06001736void GpuAssisted::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1737 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1738 uint32_t groupCountZ) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001739 ValidationStateTracker::PreCallRecordCmdDispatchBaseKHR(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX,
1740 groupCountY, groupCountZ);
sfricke-samsung85584a72021-09-30 21:43:38 -07001741 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHBASEKHR);
Tony-LunarG52c8c602020-09-10 16:29:56 -06001742}
1743
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001744void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1745 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1746 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1747 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1748 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1749 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1750 uint32_t width, uint32_t height, uint32_t depth) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001751 ValidationStateTracker::PreCallRecordCmdTraceRaysNV(
1752 commandBuffer, raygenShaderBindingTableBuffer, raygenShaderBindingOffset, missShaderBindingTableBuffer,
1753 missShaderBindingOffset, missShaderBindingStride, hitShaderBindingTableBuffer, hitShaderBindingOffset,
1754 hitShaderBindingStride, callableShaderBindingTableBuffer, callableShaderBindingOffset, callableShaderBindingStride, width,
1755 height, depth);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001756 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, CMD_TRACERAYSNV);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001757}
1758
1759void GpuAssisted::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1760 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1761 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1762 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1763 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1764 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1765 uint32_t width, uint32_t height, uint32_t depth) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001766 ValidationStateTracker::PostCallRecordCmdTraceRaysNV(
1767 commandBuffer, raygenShaderBindingTableBuffer, raygenShaderBindingOffset, missShaderBindingTableBuffer,
1768 missShaderBindingOffset, missShaderBindingStride, hitShaderBindingTableBuffer, hitShaderBindingOffset,
1769 hitShaderBindingStride, callableShaderBindingTableBuffer, callableShaderBindingOffset, callableShaderBindingStride, width,
1770 height, depth);
Jeremy Gebben9f537102021-10-05 16:37:12 -06001771 auto cb_state = Get<CMD_BUFFER_STATE>(commandBuffer);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001772 cb_state->hasTraceRaysCmd = true;
1773}
1774
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001775void GpuAssisted::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001776 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1777 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1778 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1779 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001780 uint32_t height, uint32_t depth) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001781 ValidationStateTracker::PreCallRecordCmdTraceRaysKHR(commandBuffer, pRaygenShaderBindingTable, pMissShaderBindingTable,
1782 pHitShaderBindingTable, pCallableShaderBindingTable, width, height, depth);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001783 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, CMD_TRACERAYSKHR);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001784}
1785
1786void GpuAssisted::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001787 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1788 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1789 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1790 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001791 uint32_t height, uint32_t depth) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001792 ValidationStateTracker::PostCallRecordCmdTraceRaysKHR(commandBuffer, pRaygenShaderBindingTable, pMissShaderBindingTable,
1793 pHitShaderBindingTable, pCallableShaderBindingTable, width, height,
1794 depth);
Jeremy Gebben9f537102021-10-05 16:37:12 -06001795 auto cb_state = Get<CMD_BUFFER_STATE>(commandBuffer);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001796 cb_state->hasTraceRaysCmd = true;
1797}
1798
1799void GpuAssisted::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001800 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1801 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1802 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1803 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -07001804 VkDeviceAddress indirectDeviceAddress) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001805 ValidationStateTracker::PreCallRecordCmdTraceRaysIndirectKHR(commandBuffer, pRaygenShaderBindingTable, pMissShaderBindingTable,
1806 pHitShaderBindingTable, pCallableShaderBindingTable,
1807 indirectDeviceAddress);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001808 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, CMD_TRACERAYSINDIRECTKHR);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001809}
1810
1811void GpuAssisted::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001812 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1813 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1814 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1815 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -07001816 VkDeviceAddress indirectDeviceAddress) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001817 ValidationStateTracker::PostCallRecordCmdTraceRaysIndirectKHR(commandBuffer, pRaygenShaderBindingTable, pMissShaderBindingTable,
1818 pHitShaderBindingTable, pCallableShaderBindingTable,
1819 indirectDeviceAddress);
Jeremy Gebben9f537102021-10-05 16:37:12 -06001820 auto cb_state = Get<CMD_BUFFER_STATE>(commandBuffer);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001821 cb_state->hasTraceRaysCmd = true;
1822}
1823
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001824// To generate the pre draw validation shader, run the following from the repository base level
Tony-LunarG20678ff2021-05-07 14:56:26 -06001825// python ./scripts/generate_spirv.py --outfilename ./layers/generated/gpu_pre_draw_shader.h ./layers/gpu_pre_draw_shader.vert
1826// ./External/glslang/build/install/bin/glslangValidator.exe
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001827#include "gpu_pre_draw_shader.h"
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001828void GpuAssisted::AllocatePreDrawValidationResources(GpuAssistedDeviceMemoryBlock output_block,
1829 GpuAssistedPreDrawResources &resources, const LAST_BOUND_STATE &state,
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001830 VkPipeline *pPipeline, const GpuAssistedCmdDrawIndirectState *cdi_state) {
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001831 VkResult result;
1832 if (!pre_draw_validation_state.globals_created) {
1833 auto shader_module_ci = LvlInitStruct<VkShaderModuleCreateInfo>();
Tony-LunarG9d7a3bc2021-04-26 15:55:18 -06001834 shader_module_ci.codeSize = sizeof(gpu_pre_draw_shader_vert);
1835 shader_module_ci.pCode = gpu_pre_draw_shader_vert;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001836 result =
1837 DispatchCreateShaderModule(device, &shader_module_ci, nullptr, &pre_draw_validation_state.validation_shader_module);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001838 if (result != VK_SUCCESS) {
1839 ReportSetupProblem(device, "Unable to create shader module. Aborting GPU-AV");
1840 aborted = true;
1841 return;
1842 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001843
1844 std::vector<VkDescriptorSetLayoutBinding> bindings;
1845 VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, NULL};
1846 // 0 - output buffer, 1 - count buffer
1847 bindings.push_back(binding);
1848 binding.binding = 1;
1849 bindings.push_back(binding);
1850
1851 VkDescriptorSetLayoutCreateInfo ds_layout_ci = {};
1852 ds_layout_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
1853 ds_layout_ci.bindingCount = static_cast<uint32_t>(bindings.size());
1854 ds_layout_ci.pBindings = bindings.data();
1855 result = DispatchCreateDescriptorSetLayout(device, &ds_layout_ci, nullptr, &pre_draw_validation_state.validation_ds_layout);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001856 if (result != VK_SUCCESS) {
1857 ReportSetupProblem(device, "Unable to create descriptor set layout. Aborting GPU-AV");
1858 aborted = true;
1859 return;
1860 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001861
1862 const uint32_t push_constant_range_count = 1;
1863 VkPushConstantRange push_constant_ranges[push_constant_range_count] = {};
1864 push_constant_ranges[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
1865 push_constant_ranges[0].offset = 0;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001866 push_constant_ranges[0].size = 4 * sizeof(uint32_t);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001867 VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo[1] = {};
1868 pipelineLayoutCreateInfo[0].sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
1869 pipelineLayoutCreateInfo[0].pNext = NULL;
1870 pipelineLayoutCreateInfo[0].pushConstantRangeCount = push_constant_range_count;
1871 pipelineLayoutCreateInfo[0].pPushConstantRanges = push_constant_ranges;
1872 pipelineLayoutCreateInfo[0].setLayoutCount = 1;
1873 pipelineLayoutCreateInfo[0].pSetLayouts = &pre_draw_validation_state.validation_ds_layout;
1874 result = DispatchCreatePipelineLayout(device, pipelineLayoutCreateInfo, NULL,
1875 &pre_draw_validation_state.validation_pipeline_layout);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001876 if (result != VK_SUCCESS) {
1877 ReportSetupProblem(device, "Unable to create pipeline layout. Aborting GPU-AV");
1878 aborted = true;
1879 return;
1880 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001881
1882 pre_draw_validation_state.globals_created = true;
1883 }
Tony-LunarG463bae32022-02-25 09:31:17 -07001884
1885 VkPipeline pipeline = VK_NULL_HANDLE;
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -07001886 VkRenderPass render_pass = state.pipeline_state->RenderPassState()->renderPass();
Tony-LunarG463bae32022-02-25 09:31:17 -07001887 if (render_pass != VK_NULL_HANDLE) {
1888 auto pipeentry = pre_draw_validation_state.renderpass_to_pipeline.find(render_pass);
1889 if (pipeentry != pre_draw_validation_state.renderpass_to_pipeline.end()) {
1890 pipeline = pipeentry->second;
1891 }
1892 } else {
1893 // Dynamic Rendering
1894 pipeline = pre_draw_validation_state.dyn_rendering_pipeline;
1895 }
1896 if (pipeline == VK_NULL_HANDLE) {
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001897 auto pipeline_stage_ci = LvlInitStruct<VkPipelineShaderStageCreateInfo>();
1898 pipeline_stage_ci.stage = VK_SHADER_STAGE_VERTEX_BIT;
1899 pipeline_stage_ci.module = pre_draw_validation_state.validation_shader_module;
1900 pipeline_stage_ci.pName = "main";
1901
1902 auto graphicsPipelineCreateInfo = LvlInitStruct<VkGraphicsPipelineCreateInfo>();
1903 auto vertexInputState = LvlInitStruct<VkPipelineVertexInputStateCreateInfo>();
1904 auto inputAssemblyState = LvlInitStruct<VkPipelineInputAssemblyStateCreateInfo>();
1905 inputAssemblyState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1906 auto rasterizationState = LvlInitStruct<VkPipelineRasterizationStateCreateInfo>();
1907 rasterizationState.rasterizerDiscardEnable = VK_TRUE;
1908 auto colorBlendState = LvlInitStruct<VkPipelineColorBlendStateCreateInfo>();
1909
1910 graphicsPipelineCreateInfo.pVertexInputState = &vertexInputState;
1911 graphicsPipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
1912 graphicsPipelineCreateInfo.pRasterizationState = &rasterizationState;
1913 graphicsPipelineCreateInfo.pColorBlendState = &colorBlendState;
1914 graphicsPipelineCreateInfo.renderPass = render_pass;
1915 graphicsPipelineCreateInfo.layout = pre_draw_validation_state.validation_pipeline_layout;
1916 graphicsPipelineCreateInfo.stageCount = 1;
1917 graphicsPipelineCreateInfo.pStages = &pipeline_stage_ci;
1918
1919 VkPipeline new_pipeline = VK_NULL_HANDLE;
1920 result = DispatchCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, nullptr, &new_pipeline);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001921 if (result != VK_SUCCESS) {
1922 ReportSetupProblem(device, "Unable to create graphics pipeline. Aborting GPU-AV");
1923 aborted = true;
1924 return;
1925 }
1926
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001927 *pPipeline = new_pipeline;
Tony-LunarG463bae32022-02-25 09:31:17 -07001928 if (render_pass != VK_NULL_HANDLE)
1929 pre_draw_validation_state.renderpass_to_pipeline[render_pass] = new_pipeline;
1930 else
1931 pre_draw_validation_state.dyn_rendering_pipeline = new_pipeline;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001932 } else {
Tony-LunarG463bae32022-02-25 09:31:17 -07001933 *pPipeline = pipeline;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001934 }
1935
1936 result = desc_set_manager->GetDescriptorSet(&resources.desc_pool, pre_draw_validation_state.validation_ds_layout,
1937 &resources.desc_set);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001938 if (result != VK_SUCCESS) {
1939 ReportSetupProblem(device, "Unable to allocate descriptor set. Aborting GPU-AV");
1940 aborted = true;
1941 return;
1942 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001943
1944 VkDescriptorBufferInfo buffer_infos[3] = {};
1945 // Error output buffer
1946 buffer_infos[0].buffer = output_block.buffer;
1947 buffer_infos[0].offset = 0;
1948 buffer_infos[0].range = VK_WHOLE_SIZE;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001949 if (cdi_state->count_buffer) {
1950 // Count buffer
1951 buffer_infos[1].buffer = cdi_state->count_buffer;
1952 } else {
1953 // Draw Buffer
1954 buffer_infos[1].buffer = cdi_state->buffer;
1955 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001956 buffer_infos[1].offset = 0;
1957 buffer_infos[1].range = VK_WHOLE_SIZE;
1958
1959 VkWriteDescriptorSet desc_writes[2] = {};
1960 for (auto i = 0; i < 2; i++) {
1961 desc_writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1962 desc_writes[i].dstBinding = i;
1963 desc_writes[i].descriptorCount = 1;
1964 desc_writes[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1965 desc_writes[i].pBufferInfo = &buffer_infos[i];
1966 desc_writes[i].dstSet = resources.desc_set;
1967 }
1968 DispatchUpdateDescriptorSets(device, 2, desc_writes, 0, NULL);
1969}
1970
Tony-LunarG7de10e82020-11-24 11:31:55 -07001971void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point,
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001972 CMD_TYPE cmd_type, const GpuAssistedCmdDrawIndirectState *cdi_state) {
Jason Macnak67407e72019-07-11 11:05:09 -07001973 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1974 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
andreygca287f22019-04-10 00:15:33 +03001975 return;
1976 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001977 VkResult result;
1978
Tony-LunarG99b880b2019-09-26 11:19:52 -06001979 if (aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001980
Nathaniel Cesariobcb79682022-03-31 21:13:52 -06001981 auto cb_node = Get<gpuav_state::CommandBuffer>(cmd_buffer);
1982 if (!cb_node) {
1983 ReportSetupProblem(device, "Unrecognized command buffer");
1984 aborted = true;
1985 return;
1986 }
1987 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
1988 auto const &state = cb_node->lastBound[lv_bind_point];
1989 const auto *pipeline_state = state.pipeline_state;
1990
1991 // TODO (ncesario) remove once VK_EXT_graphics_pipeline_library support is added for GPU-AV
1992 if (pipeline_state->IsGraphicsLibrary()) {
1993 ReportSetupProblem(device, "GPU-AV does not currently support VK_EXT_graphics_pipeline_library");
1994 aborted = true;
1995 return;
1996 }
1997
Tony-LunarGb2501d22019-01-28 09:59:13 -07001998 std::vector<VkDescriptorSet> desc_sets;
1999 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -06002000 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002001 assert(result == VK_SUCCESS);
2002 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07002003 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002004 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002005 return;
2006 }
2007
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002008 VkDescriptorBufferInfo output_desc_buffer_info = {};
Tony-LunarG99b880b2019-09-26 11:19:52 -06002009 output_desc_buffer_info.range = output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002010
Tony-LunarG81efe392019-03-07 15:43:27 -07002011 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002012 GpuAssistedDeviceMemoryBlock output_block = {};
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002013 VkBufferCreateInfo buffer_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
2014 buffer_info.size = output_buffer_size;
2015 buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
2016 VmaAllocationCreateInfo alloc_info = {};
2017 alloc_info.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
2018 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002019 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07002020 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002021 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002022 return;
2023 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002024
Tony-LunarG81efe392019-03-07 15:43:27 -07002025 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGc28e28a2020-08-14 10:37:48 -06002026 uint32_t *data_ptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002027 result = vmaMapMemory(vmaAllocator, output_block.allocation, reinterpret_cast<void **>(&data_ptr));
Tony-LunarG0e564722019-03-19 16:09:14 -06002028 if (result == VK_SUCCESS) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06002029 memset(data_ptr, 0, output_buffer_size);
Tony-LunarG99b880b2019-09-26 11:19:52 -06002030 vmaUnmapMemory(vmaAllocator, output_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002031 }
Tony-LunarG81efe392019-03-07 15:43:27 -07002032
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002033 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002034 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
2035 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
2036 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002037 GpuAssistedPreDrawResources pre_draw_resources = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002038 uint32_t desc_count = 1;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002039 uint32_t number_of_sets = static_cast<uint32_t>(state.per_set.size());
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002040
sfricke-samsung85584a72021-09-30 21:43:38 -07002041 if (validate_draw_indirect && ((cmd_type == CMD_DRAWINDIRECTCOUNT || cmd_type == CMD_DRAWINDIRECTCOUNTKHR ||
2042 cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT || cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNTKHR) ||
Tony-LunarG3723a3a2021-05-04 14:52:39 -06002043 ((cmd_type == CMD_DRAWINDIRECT || cmd_type == CMD_DRAWINDEXEDINDIRECT) &&
2044 !(enabled_features.core.drawIndirectFirstInstance)))) {
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002045 // 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 -06002046 //
2047 // NOTE that this validation does not attempt to abort invalid api calls as most other validation does. A crash
2048 // or DEVICE_LOST resulting from the invalid call will prevent preceeding validation errors from being reported.
2049
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002050 assert(bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06002051 assert(cdi_state != NULL);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002052 VkPipeline validation_pipeline;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06002053 AllocatePreDrawValidationResources(output_block, pre_draw_resources, state, &validation_pipeline, cdi_state);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06002054 if (aborted) return;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002055
2056 // Save current graphics pipeline state
2057 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jeremy Gebben9f537102021-10-05 16:37:12 -06002058 restorable_state.Create(cb_node.get(), VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002059
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06002060 // Save parameters for error message
Tony-LunarG3723a3a2021-05-04 14:52:39 -06002061 pre_draw_resources.buffer = cdi_state->buffer;
2062 pre_draw_resources.offset = cdi_state->offset;
2063 pre_draw_resources.stride = cdi_state->stride;
2064
2065 uint32_t pushConstants[4] = {};
sfricke-samsung85584a72021-09-30 21:43:38 -07002066 if (cmd_type == CMD_DRAWINDIRECTCOUNT || cmd_type == CMD_DRAWINDIRECTCOUNTKHR || cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT ||
2067 cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNTKHR) {
Tony-LunarG3723a3a2021-05-04 14:52:39 -06002068 if (cdi_state->count_buffer_offset > std::numeric_limits<uint32_t>::max()) {
2069 ReportSetupProblem(device,
2070 "Count buffer offset is larger than can be contained in an unsigned int. Aborting GPU-AV");
2071 aborted = true;
2072 return;
2073 }
2074
2075 // Buffer size must be >= (stride * (drawCount - 1) + offset + sizeof(VkDrawIndirectCommand))
2076 uint32_t struct_size;
sfricke-samsung85584a72021-09-30 21:43:38 -07002077 if (cmd_type == CMD_DRAWINDIRECTCOUNT || cmd_type == CMD_DRAWINDIRECTCOUNTKHR) {
Tony-LunarG3723a3a2021-05-04 14:52:39 -06002078 struct_size = sizeof(VkDrawIndirectCommand);
2079 } else {
sfricke-samsung85584a72021-09-30 21:43:38 -07002080 assert(cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT || cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNTKHR);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06002081 struct_size = sizeof(VkDrawIndexedIndirectCommand);
2082 }
Jeremy Gebbenb20a8242021-11-05 15:14:43 -06002083 auto buffer_state = Get<BUFFER_STATE>(cdi_state->buffer);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06002084 uint32_t max_count;
2085 uint64_t bufsize = buffer_state->createInfo.size;
2086 uint64_t first_command_bytes = struct_size + cdi_state->offset;
2087 if (first_command_bytes > bufsize) {
2088 max_count = 0;
2089 } else {
2090 max_count = 1 + static_cast<uint32_t>(std::floor(((bufsize - first_command_bytes) / cdi_state->stride)));
2091 }
2092 pre_draw_resources.buf_size = buffer_state->createInfo.size;
2093
2094 assert(phys_dev_props.limits.maxDrawIndirectCount > 0);
2095 pushConstants[0] = phys_dev_props.limits.maxDrawIndirectCount;
2096 pushConstants[1] = max_count;
2097 pushConstants[2] = static_cast<uint32_t>((cdi_state->count_buffer_offset / sizeof(uint32_t)));
2098 } else {
2099 pushConstants[0] = 0; // firstInstance check instead of count buffer check
2100 pushConstants[1] = cdi_state->drawCount;
2101 if (cmd_type == CMD_DRAWINDIRECT) {
2102 pushConstants[2] = static_cast<uint32_t>(
2103 ((cdi_state->offset + offsetof(struct VkDrawIndirectCommand, firstInstance)) / sizeof(uint32_t)));
2104 } else {
2105 assert(cmd_type == CMD_DRAWINDEXEDINDIRECT);
2106 pushConstants[2] = static_cast<uint32_t>(
2107 ((cdi_state->offset + offsetof(struct VkDrawIndexedIndirectCommand, firstInstance)) / sizeof(uint32_t)));
2108 }
2109 pushConstants[3] = (cdi_state->stride / sizeof(uint32_t));
2110 }
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06002111
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002112 // Insert diagnostic draw
2113 DispatchCmdBindPipeline(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, validation_pipeline);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06002114 DispatchCmdPushConstants(cmd_buffer, pre_draw_validation_state.validation_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0,
2115 sizeof(pushConstants), pushConstants);
2116 DispatchCmdBindDescriptorSets(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
2117 pre_draw_validation_state.validation_pipeline_layout, 0, 1, &pre_draw_resources.desc_set, 0,
2118 nullptr);
2119 DispatchCmdDraw(cmd_buffer, 3, 1, 0, 0);
2120
2121 // Restore the previous graphics pipeline state.
2122 restorable_state.Restore(cmd_buffer);
2123 }
2124
Tony-LunarGe29097a2020-12-03 10:59:19 -07002125 bool has_buffers = false;
Tony-LunarG81efe392019-03-07 15:43:27 -07002126 // Figure out how much memory we need for the input block based on how many sets and bindings there are
2127 // and how big each of the bindings is
Tony-LunarGc28e28a2020-08-14 10:37:48 -06002128 if (number_of_sets > 0 && (descriptor_indexing || buffer_oob_enabled)) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002129 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
2130 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
John Zulauf79f06582021-02-27 18:38:39 -07002131 for (const auto &s : state.per_set) {
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002132 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06002133 if (desc && (desc->GetBindingCount() > 0)) {
2134 auto bindings = desc->GetLayout()->GetSortedBindingSet();
Tony-LunarGa77cade2019-03-06 10:49:22 -07002135 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
2136 for (auto binding : bindings) {
Tony-LunarG7564b382019-08-21 10:11:35 -06002137 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2138 // blocks
Tony-LunarGe29097a2020-12-03 10:59:19 -07002139 auto descriptor_type = desc->GetLayout()->GetTypeFromBinding(binding);
2140 if (descriptor_type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
Tony-LunarG7564b382019-08-21 10:11:35 -06002141 descriptor_count++;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07002142 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
2143 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
2144 "validation");
Tony-LunarG7564b382019-08-21 10:11:35 -06002145 } else if (binding == desc->GetLayout()->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002146 descriptor_count += desc->GetVariableDescriptorCount();
2147 } else {
2148 descriptor_count += desc->GetDescriptorCountFromBinding(binding);
2149 }
Tony-LunarGe29097a2020-12-03 10:59:19 -07002150 if (!has_buffers && (descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
2151 descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC ||
2152 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
Tony-LunarGe8632e42020-11-18 17:03:12 -07002153 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
2154 descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
2155 descriptor_type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002156 has_buffers = true;
Tony-LunarGa77cade2019-03-06 10:49:22 -07002157 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -06002158 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002159 }
2160 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002161
Tony-LunarGe29097a2020-12-03 10:59:19 -07002162 if (descriptor_indexing || has_buffers) {
2163 // Note that the size of the input buffer is dependent on the maximum binding number, which
2164 // can be very large. This is because for (set = s, binding = b, index = i), the validation
2165 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
2166 // see if descriptors have been written. In gpu_validation.md, we note this and advise
2167 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
2168 uint32_t words_needed;
2169 if (descriptor_indexing) {
2170 words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
2171 } else {
2172 words_needed = 1 + number_of_sets + binding_count + descriptor_count;
2173 }
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002174 alloc_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2175 buffer_info.size = words_needed * 4;
2176 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &di_input_block.buffer, &di_input_block.allocation,
2177 nullptr);
Tony-LunarGe29097a2020-12-03 10:59:19 -07002178 if (result != VK_SUCCESS) {
2179 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
2180 aborted = true;
2181 return;
2182 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002183
Tony-LunarGe29097a2020-12-03 10:59:19 -07002184 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
2185 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
2186 // outline of the input buffer format
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07002187 result = vmaMapMemory(vmaAllocator, di_input_block.allocation, reinterpret_cast<void **>(&data_ptr));
2188 memset(data_ptr, 0, static_cast<size_t>(buffer_info.size));
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002189
Tony-LunarGe29097a2020-12-03 10:59:19 -07002190 // Descriptor indexing needs the number of descriptors at each binding.
2191 if (descriptor_indexing) {
2192 // Pointer to a sets array that points into the sizes array
2193 uint32_t *sets_to_sizes = data_ptr + 1;
2194 // Pointer to the sizes array that contains the array size of the descriptor at each binding
2195 uint32_t *sizes = sets_to_sizes + number_of_sets;
2196 // Pointer to another sets array that points into the bindings array that points into the written array
2197 uint32_t *sets_to_bindings = sizes + binding_count;
2198 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
2199 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
2200 // Index of the next entry in the written array to be updated
2201 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
2202 uint32_t bind_counter = number_of_sets + 1;
2203 // Index of the start of the sets_to_bindings array
2204 data_ptr[0] = number_of_sets + binding_count + 1;
2205
John Zulauf79f06582021-02-27 18:38:39 -07002206 for (const auto &s : state.per_set) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002207 auto desc = s.bound_descriptor_set;
2208 if (desc && (desc->GetBindingCount() > 0)) {
2209 auto layout = desc->GetLayout();
2210 auto bindings = layout->GetSortedBindingSet();
2211 // For each set, fill in index of its bindings sizes in the sizes array
2212 *sets_to_sizes++ = bind_counter;
2213 // For each set, fill in the index of its bindings in the bindings_to_written array
2214 *sets_to_bindings++ = bind_counter + number_of_sets + binding_count;
2215 for (auto binding : bindings) {
2216 // For each binding, fill in its size in the sizes array
2217 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2218 // uniform blocks
2219 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2220 sizes[binding] = 1;
2221 } else if (binding == layout->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
2222 sizes[binding] = desc->GetVariableDescriptorCount();
2223 } else {
2224 sizes[binding] = desc->GetDescriptorCountFromBinding(binding);
2225 }
2226 // Fill in the starting index for this binding in the written array in the bindings_to_written array
2227 bindings_to_written[binding] = written_index;
2228
2229 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2230 // uniform blocks
2231 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2232 data_ptr[written_index++] = UINT_MAX;
2233 continue;
2234 }
2235
2236 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
2237 // For each array element in the binding, update the written array with whether it has been written
2238 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
2239 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
2240 if (descriptor->updated) {
2241 SetDescriptorInitialized(data_ptr, written_index, descriptor);
2242 } else if (desc->IsUpdateAfterBind(binding)) {
2243 // If it hasn't been written now and it's update after bind, put it in a list to check at
2244 // QueueSubmit
2245 di_input_block.update_at_submit[written_index] = descriptor;
2246 }
2247 written_index++;
2248 }
2249 }
2250 auto last = desc->GetLayout()->GetMaxBinding();
2251 bindings_to_written += last + 1;
2252 bind_counter += last + 1;
2253 sizes += last + 1;
2254 } else {
2255 *sets_to_sizes++ = 0;
2256 *sets_to_bindings++ = 0;
2257 }
2258 }
2259 } else {
2260 // If no descriptor indexing, we don't need number of descriptors at each binding, so
2261 // no sets_to_sizes or sizes arrays, just sets_to_bindings, bindings_to_written and written_index
2262
2263 // Pointer to sets array that points into the bindings array that points into the written array
2264 uint32_t *sets_to_bindings = data_ptr + 1;
2265 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
2266 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
2267 // Index of the next entry in the written array to be updated
2268 uint32_t written_index = 1 + number_of_sets + binding_count;
2269 uint32_t bind_counter = number_of_sets + 1;
2270 data_ptr[0] = 1;
2271
John Zulauf79f06582021-02-27 18:38:39 -07002272 for (const auto &s : state.per_set) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002273 auto desc = s.bound_descriptor_set;
2274 if (desc && (desc->GetBindingCount() > 0)) {
2275 auto layout = desc->GetLayout();
2276 auto bindings = layout->GetSortedBindingSet();
2277 *sets_to_bindings++ = bind_counter;
2278 for (auto binding : bindings) {
2279 // Fill in the starting index for this binding in the written array in the bindings_to_written array
2280 bindings_to_written[binding] = written_index;
2281
2282 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2283 // uniform blocks
2284 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2285 data_ptr[written_index++] = UINT_MAX;
2286 continue;
2287 }
2288
2289 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
2290
2291 // For each array element in the binding, update the written array with whether it has been written
2292 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
2293 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
2294 if (descriptor->updated) {
2295 SetDescriptorInitialized(data_ptr, written_index, descriptor);
2296 } else if (desc->IsUpdateAfterBind(binding)) {
2297 // If it hasn't been written now and it's update after bind, put it in a list to check at
2298 // QueueSubmit
2299 di_input_block.update_at_submit[written_index] = descriptor;
2300 }
2301 written_index++;
2302 }
2303 }
2304 auto last = desc->GetLayout()->GetMaxBinding();
2305 bindings_to_written += last + 1;
2306 bind_counter += last + 1;
2307 } else {
2308 *sets_to_bindings++ = 0;
2309 }
2310 }
2311 }
2312 vmaUnmapMemory(vmaAllocator, di_input_block.allocation);
2313
2314 di_input_desc_buffer_info.range = (words_needed * 4);
2315 di_input_desc_buffer_info.buffer = di_input_block.buffer;
2316 di_input_desc_buffer_info.offset = 0;
2317
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06002318 desc_writes[1] = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarGe29097a2020-12-03 10:59:19 -07002319 desc_writes[1].dstBinding = 1;
2320 desc_writes[1].descriptorCount = 1;
2321 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2322 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
2323 desc_writes[1].dstSet = desc_sets[0];
2324
2325 desc_count = 2;
2326 }
Tony-LunarG0e564722019-03-19 16:09:14 -06002327 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002328
sfricke-samsung45996a42021-09-16 13:45:27 -07002329 if ((IsExtEnabled(device_extensions.vk_ext_buffer_device_address) ||
2330 IsExtEnabled(device_extensions.vk_khr_buffer_device_address)) &&
Jeremy Gebbenb0171bb2022-03-18 13:46:13 -06002331 shaderInt64 && enabled_features.core12.bufferDeviceAddress) {
2332 auto address_ranges = GetBufferAddressRanges();
2333 if (address_ranges.size() > 0) {
2334 // Example BDA input buffer assuming 2 buffers using BDA:
2335 // Word 0 | Index of start of buffer sizes (in this case 5)
2336 // Word 1 | 0x0000000000000000
2337 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
2338 // Word 3 | Device Address of second buffer
2339 // Word 4 | 0xffffffffffffffff
2340 // Word 5 | 0 (size of pretend buffer at word 1)
2341 // Word 6 | Size in bytes of first buffer
2342 // Word 7 | Size in bytes of second buffer
2343 // Word 8 | 0 (size of pretend buffer in word 4)
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002344
Jeremy Gebbenb0171bb2022-03-18 13:46:13 -06002345 uint32_t num_buffers = static_cast<uint32_t>(address_ranges.size());
2346 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
2347 alloc_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2348 buffer_info.size = words_needed * 8; // 64 bit words
2349 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &bda_input_block.buffer, &bda_input_block.allocation,
2350 nullptr);
2351 if (result != VK_SUCCESS) {
2352 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
2353 aborted = true;
2354 return;
2355 }
2356 uint64_t *bda_data;
2357 result = vmaMapMemory(vmaAllocator, bda_input_block.allocation, reinterpret_cast<void **>(&bda_data));
2358 uint32_t address_index = 1;
2359 uint32_t size_index = 3 + num_buffers;
2360 memset(bda_data, 0, static_cast<size_t>(buffer_info.size));
2361 bda_data[0] = size_index; // Start of buffer sizes
2362 bda_data[address_index++] = 0; // NULL address
2363 bda_data[size_index++] = 0;
2364
2365 for (const auto &range : address_ranges) {
2366 bda_data[address_index++] = range.begin;
2367 bda_data[size_index++] = range.end - range.begin;
2368 }
2369 bda_data[address_index] = UINTPTR_MAX;
2370 bda_data[size_index] = 0;
2371 vmaUnmapMemory(vmaAllocator, bda_input_block.allocation);
2372
2373 bda_input_desc_buffer_info.range = (words_needed * 8);
2374 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
2375 bda_input_desc_buffer_info.offset = 0;
2376
2377 desc_writes[desc_count] = LvlInitStruct<VkWriteDescriptorSet>();
2378 desc_writes[desc_count].dstBinding = 2;
2379 desc_writes[desc_count].descriptorCount = 1;
2380 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2381 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
2382 desc_writes[desc_count].dstSet = desc_sets[0];
2383 desc_count++;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002384 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002385 }
2386
Tony-LunarGb2501d22019-01-28 09:59:13 -07002387 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002388 output_desc_buffer_info.buffer = output_block.buffer;
2389 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002390
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06002391 desc_writes[0] = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002392 desc_writes[0].descriptorCount = 1;
2393 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2394 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
2395 desc_writes[0].dstSet = desc_sets[0];
2396 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002397
locke-lunargb8d7a7a2020-10-25 16:01:52 -06002398 if (pipeline_state) {
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -07002399 const auto &pipeline_layout = pipeline_state->PipelineLayoutState();
2400 if ((pipeline_layout->set_layouts.size() <= desc_set_bind_index) && !pipeline_layout->Destroyed()) {
2401 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_layout->layout(), desc_set_bind_index, 1,
Tony-LunarG99b880b2019-09-26 11:19:52 -06002402 desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002403 }
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -07002404 if (pipeline_layout->Destroyed()) {
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002405 ReportSetupProblem(device, "Pipeline layout has been destroyed, aborting GPU-AV");
2406 aborted = true;
2407 } else {
2408 // Record buffer and memory info in CB state tracking
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06002409 cb_node->gpuav_buffer_list.emplace_back(output_block, di_input_block, bda_input_block, pre_draw_resources, desc_sets[0],
2410 desc_pool, bind_point, cmd_type);
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002411 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002412 } else {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07002413 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002414 aborted = true;
2415 }
2416 if (aborted) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002417 vmaDestroyBuffer(vmaAllocator, di_input_block.buffer, di_input_block.allocation);
2418 vmaDestroyBuffer(vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
2419 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002420 return;
2421 }
2422}
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06002423
2424std::shared_ptr<CMD_BUFFER_STATE> GpuAssisted::CreateCmdBufferState(VkCommandBuffer cb,
2425 const VkCommandBufferAllocateInfo *pCreateInfo,
Jeremy Gebbencd7fa282021-10-27 10:25:32 -06002426 const COMMAND_POOL_STATE *pool) {
Jeremy Gebben135550d2022-03-21 07:15:07 -06002427 return std::static_pointer_cast<CMD_BUFFER_STATE>(std::make_shared<gpuav_state::CommandBuffer>(this, cb, pCreateInfo, pool));
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06002428}
2429
Jeremy Gebben135550d2022-03-21 07:15:07 -06002430gpuav_state::CommandBuffer::CommandBuffer(GpuAssisted *ga, VkCommandBuffer cb, const VkCommandBufferAllocateInfo *pCreateInfo,
2431 const COMMAND_POOL_STATE *pool)
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06002432 : CMD_BUFFER_STATE(ga, cb, pCreateInfo, pool) {}
2433
Jeremy Gebben135550d2022-03-21 07:15:07 -06002434void gpuav_state::CommandBuffer::Reset() {
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06002435 CMD_BUFFER_STATE::Reset();
2436 auto gpuav = static_cast<GpuAssisted *>(dev_data);
2437 // Free the device memory and descriptor set(s) associated with a command buffer.
2438 if (gpuav->aborted) {
2439 return;
2440 }
2441 for (auto &buffer_info : gpuav_buffer_list) {
2442 gpuav->DestroyBuffer(buffer_info);
2443 }
2444 gpuav_buffer_list.clear();
2445
2446 for (auto &as_validation_buffer_info : as_validation_buffers) {
2447 gpuav->DestroyBuffer(as_validation_buffer_info);
2448 }
2449 as_validation_buffers.clear();
2450}