blob: a92af389f3b92aa5f737b3292494e6789ce15a4a [file] [log] [blame]
Mark Lobodzinski103c58a2020-01-29 13:20:00 -07001/* Copyright (c) 2018-2020 The Khronos Group Inc.
2 * Copyright (c) 2018-2020 Valve Corporation
3 * Copyright (c) 2018-2020 LunarG, Inc.
Karl Schultz7b024b42018-08-30 16:18:18 -06004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060017 * Author: Karl Schultz <karl@lunarg.com>
18 * Author: Tony Barbour <tony@lunarg.com>
Karl Schultz7b024b42018-08-30 16:18:18 -060019 */
20
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -070021#include "gpu_validation.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060022#include "spirv-tools/optimizer.hpp"
23#include "spirv-tools/instrument.hpp"
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060024#include "layer_chassis_dispatch.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060025
Jason Macnak67407e72019-07-11 11:05:09 -070026static const VkShaderStageFlags kShaderStageAllRayTracing =
27 VK_SHADER_STAGE_ANY_HIT_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV | VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV |
28 VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV | VK_SHADER_STAGE_RAYGEN_BIT_NV;
29
Jason Macnak83cfd582019-07-31 10:14:24 -070030// Keep in sync with the GLSL shader below.
31struct GpuAccelerationStructureBuildValidationBuffer {
32 uint32_t instances_to_validate;
33 uint32_t replacement_handle_bits_0;
34 uint32_t replacement_handle_bits_1;
35 uint32_t invalid_handle_found;
36 uint32_t invalid_handle_bits_0;
37 uint32_t invalid_handle_bits_1;
38 uint32_t valid_handles_count;
39};
40
41// This is the GLSL source for the compute shader that is used during ray tracing acceleration structure
42// building validation which inspects instance buffers for top level acceleration structure builds and
43// reports and replaces invalid bottom level acceleration structure handles with good bottom level
44// acceleration structure handle so that applications can continue without undefined behavior long enough
45// to report errors.
46//
47// #version 450
48// layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
49// struct VkGeometryInstanceNV {
50// uint unused[14];
51// uint handle_bits_0;
52// uint handle_bits_1;
53// };
54// layout(set=0, binding=0, std430) buffer InstanceBuffer {
55// VkGeometryInstanceNV instances[];
56// };
57// layout(set=0, binding=1, std430) buffer ValidationBuffer {
58// uint instances_to_validate;
59// uint replacement_handle_bits_0;
60// uint replacement_handle_bits_1;
61// uint invalid_handle_found;
62// uint invalid_handle_bits_0;
63// uint invalid_handle_bits_1;
64// uint valid_handles_count;
65// uint valid_handles[];
66// };
67// void main() {
68// for (uint instance_index = 0; instance_index < instances_to_validate; instance_index++) {
69// uint instance_handle_bits_0 = instances[instance_index].handle_bits_0;
70// uint instance_handle_bits_1 = instances[instance_index].handle_bits_1;
71// bool valid = false;
72// for (uint valid_handle_index = 0; valid_handle_index < valid_handles_count; valid_handle_index++) {
73// if (instance_handle_bits_0 == valid_handles[2*valid_handle_index+0] &&
74// instance_handle_bits_1 == valid_handles[2*valid_handle_index+1]) {
75// valid = true;
76// break;
77// }
78// }
79// if (!valid) {
80// invalid_handle_found += 1;
81// invalid_handle_bits_0 = instance_handle_bits_0;
82// invalid_handle_bits_1 = instance_handle_bits_1;
83// instances[instance_index].handle_bits_0 = replacement_handle_bits_0;
84// instances[instance_index].handle_bits_1 = replacement_handle_bits_1;
85// }
86// }
87// }
88//
89// To regenerate the spirv below:
90// 1. Save the above GLSL source to a file called validation_shader.comp.
91// 2. Run in terminal
92//
93// glslangValidator.exe -x -V validation_shader.comp -o validation_shader.comp.spv
94//
95// 4. Copy-paste the contents of validation_shader.comp.spv here (clang-format will fix up the alignment).
96static const uint32_t kComputeShaderSpirv[] = {
97 0x07230203, 0x00010000, 0x00080007, 0x0000006d, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, 0x00000001, 0x4c534c47,
98 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0005000f, 0x00000005, 0x00000004, 0x6e69616d,
99 0x00000000, 0x00060010, 0x00000004, 0x00000011, 0x00000001, 0x00000001, 0x00000001, 0x00030003, 0x00000002, 0x000001c2,
100 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00060005, 0x00000008, 0x74736e69, 0x65636e61, 0x646e695f, 0x00007865,
101 0x00070005, 0x00000011, 0x696c6156, 0x69746164, 0x75426e6f, 0x72656666, 0x00000000, 0x00090006, 0x00000011, 0x00000000,
102 0x74736e69, 0x65636e61, 0x6f745f73, 0x6c61765f, 0x74616469, 0x00000065, 0x000a0006, 0x00000011, 0x00000001, 0x6c706572,
103 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x000a0006, 0x00000011, 0x00000002, 0x6c706572,
104 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00090006, 0x00000011, 0x00000003, 0x61766e69,
105 0x5f64696c, 0x646e6168, 0x665f656c, 0x646e756f, 0x00000000, 0x00090006, 0x00000011, 0x00000004, 0x61766e69, 0x5f64696c,
106 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00090006, 0x00000011, 0x00000005, 0x61766e69, 0x5f64696c, 0x646e6168,
107 0x625f656c, 0x5f737469, 0x00000031, 0x00080006, 0x00000011, 0x00000006, 0x696c6176, 0x61685f64, 0x656c646e, 0x6f635f73,
108 0x00746e75, 0x00070006, 0x00000011, 0x00000007, 0x696c6176, 0x61685f64, 0x656c646e, 0x00000073, 0x00030005, 0x00000013,
109 0x00000000, 0x00080005, 0x0000001b, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000305f, 0x00080005,
110 0x0000001e, 0x65476b56, 0x74656d6f, 0x6e497972, 0x6e617473, 0x564e6563, 0x00000000, 0x00050006, 0x0000001e, 0x00000000,
111 0x73756e75, 0x00006465, 0x00070006, 0x0000001e, 0x00000001, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00070006,
112 0x0000001e, 0x00000002, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00060005, 0x00000020, 0x74736e49, 0x65636e61,
113 0x66667542, 0x00007265, 0x00060006, 0x00000020, 0x00000000, 0x74736e69, 0x65636e61, 0x00000073, 0x00030005, 0x00000022,
114 0x00000000, 0x00080005, 0x00000027, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000315f, 0x00040005,
115 0x0000002d, 0x696c6176, 0x00000064, 0x00070005, 0x0000002f, 0x696c6176, 0x61685f64, 0x656c646e, 0x646e695f, 0x00007865,
116 0x00040047, 0x00000010, 0x00000006, 0x00000004, 0x00050048, 0x00000011, 0x00000000, 0x00000023, 0x00000000, 0x00050048,
117 0x00000011, 0x00000001, 0x00000023, 0x00000004, 0x00050048, 0x00000011, 0x00000002, 0x00000023, 0x00000008, 0x00050048,
118 0x00000011, 0x00000003, 0x00000023, 0x0000000c, 0x00050048, 0x00000011, 0x00000004, 0x00000023, 0x00000010, 0x00050048,
119 0x00000011, 0x00000005, 0x00000023, 0x00000014, 0x00050048, 0x00000011, 0x00000006, 0x00000023, 0x00000018, 0x00050048,
120 0x00000011, 0x00000007, 0x00000023, 0x0000001c, 0x00030047, 0x00000011, 0x00000003, 0x00040047, 0x00000013, 0x00000022,
121 0x00000000, 0x00040047, 0x00000013, 0x00000021, 0x00000001, 0x00040047, 0x0000001d, 0x00000006, 0x00000004, 0x00050048,
122 0x0000001e, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x0000001e, 0x00000001, 0x00000023, 0x00000038, 0x00050048,
123 0x0000001e, 0x00000002, 0x00000023, 0x0000003c, 0x00040047, 0x0000001f, 0x00000006, 0x00000040, 0x00050048, 0x00000020,
124 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x00000020, 0x00000003, 0x00040047, 0x00000022, 0x00000022, 0x00000000,
125 0x00040047, 0x00000022, 0x00000021, 0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00040015,
126 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, 0x00000006, 0x0004002b, 0x00000006, 0x00000009,
127 0x00000000, 0x0003001d, 0x00000010, 0x00000006, 0x000a001e, 0x00000011, 0x00000006, 0x00000006, 0x00000006, 0x00000006,
128 0x00000006, 0x00000006, 0x00000006, 0x00000010, 0x00040020, 0x00000012, 0x00000002, 0x00000011, 0x0004003b, 0x00000012,
129 0x00000013, 0x00000002, 0x00040015, 0x00000014, 0x00000020, 0x00000001, 0x0004002b, 0x00000014, 0x00000015, 0x00000000,
130 0x00040020, 0x00000016, 0x00000002, 0x00000006, 0x00020014, 0x00000019, 0x0004002b, 0x00000006, 0x0000001c, 0x0000000e,
131 0x0004001c, 0x0000001d, 0x00000006, 0x0000001c, 0x0005001e, 0x0000001e, 0x0000001d, 0x00000006, 0x00000006, 0x0003001d,
132 0x0000001f, 0x0000001e, 0x0003001e, 0x00000020, 0x0000001f, 0x00040020, 0x00000021, 0x00000002, 0x00000020, 0x0004003b,
133 0x00000021, 0x00000022, 0x00000002, 0x0004002b, 0x00000014, 0x00000024, 0x00000001, 0x0004002b, 0x00000014, 0x00000029,
134 0x00000002, 0x00040020, 0x0000002c, 0x00000007, 0x00000019, 0x0003002a, 0x00000019, 0x0000002e, 0x0004002b, 0x00000014,
135 0x00000036, 0x00000006, 0x0004002b, 0x00000014, 0x0000003b, 0x00000007, 0x0004002b, 0x00000006, 0x0000003c, 0x00000002,
136 0x0004002b, 0x00000006, 0x00000048, 0x00000001, 0x00030029, 0x00000019, 0x00000050, 0x0004002b, 0x00000014, 0x00000058,
137 0x00000003, 0x0004002b, 0x00000014, 0x0000005d, 0x00000004, 0x0004002b, 0x00000014, 0x00000060, 0x00000005, 0x00050036,
138 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007,
139 0x0004003b, 0x00000007, 0x0000001b, 0x00000007, 0x0004003b, 0x00000007, 0x00000027, 0x00000007, 0x0004003b, 0x0000002c,
140 0x0000002d, 0x00000007, 0x0004003b, 0x00000007, 0x0000002f, 0x00000007, 0x0003003e, 0x00000008, 0x00000009, 0x000200f9,
141 0x0000000a, 0x000200f8, 0x0000000a, 0x000400f6, 0x0000000c, 0x0000000d, 0x00000000, 0x000200f9, 0x0000000e, 0x000200f8,
142 0x0000000e, 0x0004003d, 0x00000006, 0x0000000f, 0x00000008, 0x00050041, 0x00000016, 0x00000017, 0x00000013, 0x00000015,
143 0x0004003d, 0x00000006, 0x00000018, 0x00000017, 0x000500b0, 0x00000019, 0x0000001a, 0x0000000f, 0x00000018, 0x000400fa,
144 0x0000001a, 0x0000000b, 0x0000000c, 0x000200f8, 0x0000000b, 0x0004003d, 0x00000006, 0x00000023, 0x00000008, 0x00070041,
145 0x00000016, 0x00000025, 0x00000022, 0x00000015, 0x00000023, 0x00000024, 0x0004003d, 0x00000006, 0x00000026, 0x00000025,
146 0x0003003e, 0x0000001b, 0x00000026, 0x0004003d, 0x00000006, 0x00000028, 0x00000008, 0x00070041, 0x00000016, 0x0000002a,
147 0x00000022, 0x00000015, 0x00000028, 0x00000029, 0x0004003d, 0x00000006, 0x0000002b, 0x0000002a, 0x0003003e, 0x00000027,
148 0x0000002b, 0x0003003e, 0x0000002d, 0x0000002e, 0x0003003e, 0x0000002f, 0x00000009, 0x000200f9, 0x00000030, 0x000200f8,
149 0x00000030, 0x000400f6, 0x00000032, 0x00000033, 0x00000000, 0x000200f9, 0x00000034, 0x000200f8, 0x00000034, 0x0004003d,
150 0x00000006, 0x00000035, 0x0000002f, 0x00050041, 0x00000016, 0x00000037, 0x00000013, 0x00000036, 0x0004003d, 0x00000006,
151 0x00000038, 0x00000037, 0x000500b0, 0x00000019, 0x00000039, 0x00000035, 0x00000038, 0x000400fa, 0x00000039, 0x00000031,
152 0x00000032, 0x000200f8, 0x00000031, 0x0004003d, 0x00000006, 0x0000003a, 0x0000001b, 0x0004003d, 0x00000006, 0x0000003d,
153 0x0000002f, 0x00050084, 0x00000006, 0x0000003e, 0x0000003c, 0x0000003d, 0x00050080, 0x00000006, 0x0000003f, 0x0000003e,
154 0x00000009, 0x00060041, 0x00000016, 0x00000040, 0x00000013, 0x0000003b, 0x0000003f, 0x0004003d, 0x00000006, 0x00000041,
155 0x00000040, 0x000500aa, 0x00000019, 0x00000042, 0x0000003a, 0x00000041, 0x000300f7, 0x00000044, 0x00000000, 0x000400fa,
156 0x00000042, 0x00000043, 0x00000044, 0x000200f8, 0x00000043, 0x0004003d, 0x00000006, 0x00000045, 0x00000027, 0x0004003d,
157 0x00000006, 0x00000046, 0x0000002f, 0x00050084, 0x00000006, 0x00000047, 0x0000003c, 0x00000046, 0x00050080, 0x00000006,
158 0x00000049, 0x00000047, 0x00000048, 0x00060041, 0x00000016, 0x0000004a, 0x00000013, 0x0000003b, 0x00000049, 0x0004003d,
159 0x00000006, 0x0000004b, 0x0000004a, 0x000500aa, 0x00000019, 0x0000004c, 0x00000045, 0x0000004b, 0x000200f9, 0x00000044,
160 0x000200f8, 0x00000044, 0x000700f5, 0x00000019, 0x0000004d, 0x00000042, 0x00000031, 0x0000004c, 0x00000043, 0x000300f7,
161 0x0000004f, 0x00000000, 0x000400fa, 0x0000004d, 0x0000004e, 0x0000004f, 0x000200f8, 0x0000004e, 0x0003003e, 0x0000002d,
162 0x00000050, 0x000200f9, 0x00000032, 0x000200f8, 0x0000004f, 0x000200f9, 0x00000033, 0x000200f8, 0x00000033, 0x0004003d,
163 0x00000006, 0x00000052, 0x0000002f, 0x00050080, 0x00000006, 0x00000053, 0x00000052, 0x00000024, 0x0003003e, 0x0000002f,
164 0x00000053, 0x000200f9, 0x00000030, 0x000200f8, 0x00000032, 0x0004003d, 0x00000019, 0x00000054, 0x0000002d, 0x000400a8,
165 0x00000019, 0x00000055, 0x00000054, 0x000300f7, 0x00000057, 0x00000000, 0x000400fa, 0x00000055, 0x00000056, 0x00000057,
166 0x000200f8, 0x00000056, 0x00050041, 0x00000016, 0x00000059, 0x00000013, 0x00000058, 0x0004003d, 0x00000006, 0x0000005a,
167 0x00000059, 0x00050080, 0x00000006, 0x0000005b, 0x0000005a, 0x00000048, 0x00050041, 0x00000016, 0x0000005c, 0x00000013,
168 0x00000058, 0x0003003e, 0x0000005c, 0x0000005b, 0x0004003d, 0x00000006, 0x0000005e, 0x0000001b, 0x00050041, 0x00000016,
169 0x0000005f, 0x00000013, 0x0000005d, 0x0003003e, 0x0000005f, 0x0000005e, 0x0004003d, 0x00000006, 0x00000061, 0x00000027,
170 0x00050041, 0x00000016, 0x00000062, 0x00000013, 0x00000060, 0x0003003e, 0x00000062, 0x00000061, 0x0004003d, 0x00000006,
171 0x00000063, 0x00000008, 0x00050041, 0x00000016, 0x00000064, 0x00000013, 0x00000024, 0x0004003d, 0x00000006, 0x00000065,
172 0x00000064, 0x00070041, 0x00000016, 0x00000066, 0x00000022, 0x00000015, 0x00000063, 0x00000024, 0x0003003e, 0x00000066,
173 0x00000065, 0x0004003d, 0x00000006, 0x00000067, 0x00000008, 0x00050041, 0x00000016, 0x00000068, 0x00000013, 0x00000029,
174 0x0004003d, 0x00000006, 0x00000069, 0x00000068, 0x00070041, 0x00000016, 0x0000006a, 0x00000022, 0x00000015, 0x00000067,
175 0x00000029, 0x0003003e, 0x0000006a, 0x00000069, 0x000200f9, 0x00000057, 0x000200f8, 0x00000057, 0x000200f9, 0x0000000d,
176 0x000200f8, 0x0000000d, 0x0004003d, 0x00000006, 0x0000006b, 0x00000008, 0x00050080, 0x00000006, 0x0000006c, 0x0000006b,
177 0x00000024, 0x0003003e, 0x00000008, 0x0000006c, 0x000200f9, 0x0000000a, 0x000200f8, 0x0000000c, 0x000100fd, 0x00010038};
178
Karl Schultz7b024b42018-08-30 16:18:18 -0600179// Convenience function for reporting problems with setting up GPU Validation.
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700180template <typename T>
181void GpuAssisted::ReportSetupProblem(T object, const char *const specific_message) const {
182 LogError(object, "UNASSIGNED-GPU-Assisted Validation Error. ", "Detail: (%s)", specific_message);
Karl Schultz7b024b42018-08-30 16:18:18 -0600183}
184
Tony-LunarG5c38b182020-06-10 16:15:32 -0600185bool GpuAssisted::CheckForDescriptorIndexing(DeviceFeatures enabled_features) const {
186 bool result =
187 (IsExtEnabled(device_extensions.vk_ext_descriptor_indexing) &&
188 (enabled_features.core12.descriptorIndexing || enabled_features.core12.shaderInputAttachmentArrayDynamicIndexing ||
189 enabled_features.core12.shaderUniformTexelBufferArrayDynamicIndexing ||
190 enabled_features.core12.shaderStorageTexelBufferArrayDynamicIndexing ||
191 enabled_features.core12.shaderUniformBufferArrayNonUniformIndexing ||
192 enabled_features.core12.shaderSampledImageArrayNonUniformIndexing ||
193 enabled_features.core12.shaderStorageBufferArrayNonUniformIndexing ||
194 enabled_features.core12.shaderStorageImageArrayNonUniformIndexing ||
195 enabled_features.core12.shaderInputAttachmentArrayNonUniformIndexing ||
196 enabled_features.core12.shaderUniformTexelBufferArrayNonUniformIndexing ||
197 enabled_features.core12.shaderStorageTexelBufferArrayNonUniformIndexing ||
198 enabled_features.core12.descriptorBindingUniformBufferUpdateAfterBind ||
199 enabled_features.core12.descriptorBindingSampledImageUpdateAfterBind ||
200 enabled_features.core12.descriptorBindingStorageImageUpdateAfterBind ||
201 enabled_features.core12.descriptorBindingStorageBufferUpdateAfterBind ||
202 enabled_features.core12.descriptorBindingUniformTexelBufferUpdateAfterBind ||
203 enabled_features.core12.descriptorBindingStorageTexelBufferUpdateAfterBind ||
204 enabled_features.core12.descriptorBindingUpdateUnusedWhilePending ||
205 enabled_features.core12.descriptorBindingPartiallyBound ||
206 enabled_features.core12.descriptorBindingVariableDescriptorCount || enabled_features.core12.runtimeDescriptorArray));
207 return result;
208}
209
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600210void GpuAssisted::PreCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
211 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer, void *cb_state_data) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700212 // Ray tracing acceleration structure instance buffers also need the storage buffer usage as
213 // acceleration structure build validation will find and replace invalid acceleration structure
214 // handles inside of a compute shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600215 create_buffer_api_state *cb_state = reinterpret_cast<create_buffer_api_state *>(cb_state_data);
216 if (cb_state && cb_state->modified_create_info.usage & VK_BUFFER_USAGE_RAY_TRACING_BIT_NV) {
217 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
Jason Macnak83cfd582019-07-31 10:14:24 -0700218 }
219}
220
Karl Schultz7b024b42018-08-30 16:18:18 -0600221// Turn on necessary device features.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600222void GpuAssisted::PreCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info,
223 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
224 safe_VkDeviceCreateInfo *modified_create_info) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600225 DispatchGetPhysicalDeviceFeatures(gpu, &supported_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600226 VkPhysicalDeviceFeatures features = {};
227 features.vertexPipelineStoresAndAtomics = true;
228 features.fragmentStoresAndAtomics = true;
229 features.shaderInt64 = true;
Tony-LunarGb5fae462020-03-05 12:43:25 -0700230 UtilPreCallRecordCreateDevice(gpu, modified_create_info, supported_features, features);
Karl Schultz7b024b42018-08-30 16:18:18 -0600231}
Karl Schultz7b024b42018-08-30 16:18:18 -0600232// Perform initializations that can be done at Create Device time.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600233void GpuAssisted::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
234 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result) {
235 // The state tracker sets up the device state
Tony-LunarG99b880b2019-09-26 11:19:52 -0600236 ValidationStateTracker::PostCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski5dc3dcd2019-04-23 14:26:28 -0600237
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600238 ValidationObject *device_object = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
239 ValidationObject *validation_data = GetValidationObject(device_object->object_dispatch, this->container_type);
240 GpuAssisted *device_gpu_assisted = static_cast<GpuAssisted *>(validation_data);
Tony-LunarG65f9c492019-01-17 14:24:42 -0700241
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600242 if (device_gpu_assisted->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700243 ReportSetupProblem(device, "GPU-Assisted validation requires Vulkan 1.1 or later. GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600244 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600245 return;
246 }
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600247
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600248 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700249 ReportSetupProblem(device,
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600250 "GPU-Assisted validation requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
251 "GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600252 device_gpu_assisted->aborted = true;
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600253 return;
254 }
255
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700256 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) &&
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600257 !supported_features.shaderInt64) {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700258 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
259 "shaderInt64 feature is not available. No buffer device address checking will be attempted");
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600260 }
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600261 device_gpu_assisted->shaderInt64 = supported_features.shaderInt64;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600262 device_gpu_assisted->physicalDevice = physicalDevice;
263 device_gpu_assisted->device = *pDevice;
Tony-LunarGbb145f32020-04-27 13:41:29 -0600264 device_gpu_assisted->output_buffer_size = sizeof(uint32_t) * (spvtools::kInstMaxOutCnt + 1);
Tony-LunarG5c38b182020-06-10 16:15:32 -0600265 device_gpu_assisted->descriptor_indexing = CheckForDescriptorIndexing(device_gpu_assisted->enabled_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600266 std::vector<VkDescriptorSetLayoutBinding> bindings;
267 VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
Tony-LunarGc7ed2082020-06-11 14:00:04 -0600268 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT |
269 VK_SHADER_STAGE_MESH_BIT_NV | VK_SHADER_STAGE_TASK_BIT_NV |
270 kShaderStageAllRayTracing,
Tony-LunarG1dce2392019-10-23 16:49:29 -0600271 NULL};
272 bindings.push_back(binding);
273 for (auto i = 1; i < 3; i++) {
274 binding.binding = i;
275 bindings.push_back(binding);
Karl Schultz7b024b42018-08-30 16:18:18 -0600276 }
Tony-LunarGb5fae462020-03-05 12:43:25 -0700277 UtilPostCallRecordCreateDevice(pCreateInfo, bindings, device_gpu_assisted, device_gpu_assisted->phys_dev_props);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600278 CreateAccelerationStructureBuildValidationState(device_gpu_assisted);
Karl Schultz7b024b42018-08-30 16:18:18 -0600279}
280
Tony-LunarG588c7052020-04-23 10:47:21 -0600281void GpuAssisted::PostCallRecordGetBufferDeviceAddress(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
282 VkDeviceAddress address) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600283 BUFFER_STATE *buffer_state = GetBufferState(pInfo->buffer);
284 // Validate against the size requested when the buffer was created
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600285 if (buffer_state) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600286 buffer_map[address] = buffer_state->createInfo.size;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600287 buffer_state->deviceAddress = address;
288 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600289}
290
Tony-LunarG588c7052020-04-23 10:47:21 -0600291void GpuAssisted::PostCallRecordGetBufferDeviceAddressEXT(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
292 VkDeviceAddress address) {
293 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
294}
295
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700296void GpuAssisted::PostCallRecordGetBufferDeviceAddressKHR(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
297 VkDeviceAddress address) {
Tony-LunarG588c7052020-04-23 10:47:21 -0600298 PostCallRecordGetBufferDeviceAddress(device, pInfo, address);
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700299}
300
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600301void GpuAssisted::PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600302 BUFFER_STATE *buffer_state = GetBufferState(buffer);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600303 if (buffer_state) buffer_map.erase(buffer_state->deviceAddress);
Tony-LunarG2966c732020-05-21 10:33:53 -0600304 ValidationStateTracker::PreCallRecordDestroyBuffer(device, buffer, pAllocator);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600305}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600306
Karl Schultz7b024b42018-08-30 16:18:18 -0600307// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600308void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600309 DestroyAccelerationStructureBuildValidationState();
Tony-LunarGb5fae462020-03-05 12:43:25 -0700310 UtilPreCallRecordDestroyDevice(this);
Tony-LunarG2966c732020-05-21 10:33:53 -0600311 ValidationStateTracker::PreCallRecordDestroyDevice(device, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -0600312}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600313
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600314void GpuAssisted::CreateAccelerationStructureBuildValidationState(GpuAssisted *device_gpuav) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600315 if (device_gpuav->aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700316 return;
317 }
318
Tony-LunarG99b880b2019-09-26 11:19:52 -0600319 auto &as_validation_state = device_gpuav->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700320 if (as_validation_state.initialized) {
321 return;
322 }
323
324 if (!device_extensions.vk_nv_ray_tracing) {
325 return;
326 }
327
328 // Outline:
329 // - Create valid bottom level acceleration structure which acts as replacement
330 // - Create and load vertex buffer
331 // - Create and load index buffer
332 // - Create, allocate memory for, and bind memory for acceleration structure
333 // - Query acceleration structure handle
334 // - Create command pool and command buffer
335 // - Record build acceleration structure command
336 // - Submit command buffer and wait for completion
337 // - Cleanup
338 // - Create compute pipeline for validating instance buffers
339 // - Create descriptor set layout
340 // - Create pipeline layout
341 // - Create pipeline
342 // - Cleanup
343
344 VkResult result = VK_SUCCESS;
345
346 VkBuffer vbo = VK_NULL_HANDLE;
347 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
348 if (result == VK_SUCCESS) {
349 VkBufferCreateInfo vbo_ci = {};
350 vbo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
351 vbo_ci.size = sizeof(float) * 9;
352 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
353
354 VmaAllocationCreateInfo vbo_ai = {};
355 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
356 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
357
Tony-LunarG99b880b2019-09-26 11:19:52 -0600358 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700359 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700360 ReportSetupProblem(device, "Failed to create vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700361 }
362 }
363
364 if (result == VK_SUCCESS) {
365 uint8_t *mapped_vbo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600366 result = vmaMapMemory(device_gpuav->vmaAllocator, vbo_allocation, (void **)&mapped_vbo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700367 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700368 ReportSetupProblem(device, "Failed to map vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700369 } else {
370 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
371 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600372 vmaUnmapMemory(device_gpuav->vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700373 }
374 }
375
376 VkBuffer ibo = VK_NULL_HANDLE;
377 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
378 if (result == VK_SUCCESS) {
379 VkBufferCreateInfo ibo_ci = {};
380 ibo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
381 ibo_ci.size = sizeof(uint32_t) * 3;
382 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
383
384 VmaAllocationCreateInfo ibo_ai = {};
385 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
386 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
387
Tony-LunarG99b880b2019-09-26 11:19:52 -0600388 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700389 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700390 ReportSetupProblem(device, "Failed to create index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700391 }
392 }
393
394 if (result == VK_SUCCESS) {
395 uint8_t *mapped_ibo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600396 result = vmaMapMemory(device_gpuav->vmaAllocator, ibo_allocation, (void **)&mapped_ibo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700397 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700398 ReportSetupProblem(device, "Failed to map index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700399 } else {
400 const std::vector<uint32_t> indicies = {0, 1, 2};
401 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600402 vmaUnmapMemory(device_gpuav->vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700403 }
404 }
405
406 VkGeometryNV geometry = {};
407 geometry.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
408 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
409 geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
410 geometry.geometry.triangles.vertexData = vbo;
411 geometry.geometry.triangles.vertexOffset = 0;
412 geometry.geometry.triangles.vertexCount = 3;
413 geometry.geometry.triangles.vertexStride = 12;
414 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
415 geometry.geometry.triangles.indexData = ibo;
416 geometry.geometry.triangles.indexOffset = 0;
417 geometry.geometry.triangles.indexCount = 3;
418 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
419 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
420 geometry.geometry.triangles.transformOffset = 0;
421 geometry.geometry.aabbs = {};
422 geometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
423
424 VkAccelerationStructureCreateInfoNV as_ci = {};
425 as_ci.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
426 as_ci.info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
427 as_ci.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV;
428 as_ci.info.instanceCount = 0;
429 as_ci.info.geometryCount = 1;
430 as_ci.info.pGeometries = &geometry;
431 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600432 result = DispatchCreateAccelerationStructureNV(device_gpuav->device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700433 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700434 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700435 "Failed to create acceleration structure for acceleration structure build validation.");
436 }
437 }
438
439 VkMemoryRequirements2 as_mem_requirements = {};
440 if (result == VK_SUCCESS) {
441 VkAccelerationStructureMemoryRequirementsInfoNV as_mem_requirements_info = {};
442 as_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
443 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
444 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
445
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600446 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700447 }
448
449 VmaAllocationInfo as_memory_ai = {};
450 if (result == VK_SUCCESS) {
451 VmaAllocationCreateInfo as_memory_aci = {};
452 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
453
Tony-LunarG99b880b2019-09-26 11:19:52 -0600454 result = vmaAllocateMemory(device_gpuav->vmaAllocator, &as_mem_requirements.memoryRequirements, &as_memory_aci,
455 &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700456 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700457 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700458 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
459 }
460 }
461
462 if (result == VK_SUCCESS) {
463 VkBindAccelerationStructureMemoryInfoNV as_bind_info = {};
464 as_bind_info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
465 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
466 as_bind_info.memory = as_memory_ai.deviceMemory;
467 as_bind_info.memoryOffset = as_memory_ai.offset;
468
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600469 result = DispatchBindAccelerationStructureMemoryNV(device_gpuav->device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700470 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700471 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700472 "Failed to bind acceleration structure memory for acceleration structure build validation.");
473 }
474 }
475
476 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600477 result = DispatchGetAccelerationStructureHandleNV(device_gpuav->device, as_validation_state.replacement_as,
478 sizeof(uint64_t), &as_validation_state.replacement_as_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700479 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700480 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700481 "Failed to get acceleration structure handle for acceleration structure build validation.");
482 }
483 }
484
485 VkMemoryRequirements2 scratch_mem_requirements = {};
486 if (result == VK_SUCCESS) {
487 VkAccelerationStructureMemoryRequirementsInfoNV scratch_mem_requirements_info = {};
488 scratch_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
489 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
490 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
491
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600492 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &scratch_mem_requirements_info,
493 &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700494 }
495
496 VkBuffer scratch = VK_NULL_HANDLE;
Tony-LunarG18900282020-05-20 12:34:33 -0600497 VmaAllocation scratch_allocation = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700498 if (result == VK_SUCCESS) {
499 VkBufferCreateInfo scratch_ci = {};
500 scratch_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
501 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
502 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
Jason Macnak83cfd582019-07-31 10:14:24 -0700503 VmaAllocationCreateInfo scratch_aci = {};
504 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
505
Tony-LunarG18900282020-05-20 12:34:33 -0600506 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &scratch_ci, &scratch_aci, &scratch, &scratch_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700507 if (result != VK_SUCCESS) {
Tony-LunarG18900282020-05-20 12:34:33 -0600508 ReportSetupProblem(device_gpuav->device,
509 "Failed to create scratch buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700510 }
511 }
512
513 VkCommandPool command_pool = VK_NULL_HANDLE;
514 if (result == VK_SUCCESS) {
515 VkCommandPoolCreateInfo command_pool_ci = {};
516 command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
517 command_pool_ci.queueFamilyIndex = 0;
518
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600519 result = DispatchCreateCommandPool(device_gpuav->device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700520 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700521 ReportSetupProblem(device_gpuav->device, "Failed to create command pool for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700522 }
523 }
524
525 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
526
527 if (result == VK_SUCCESS) {
528 VkCommandBufferAllocateInfo command_buffer_ai = {};
529 command_buffer_ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
530 command_buffer_ai.commandPool = command_pool;
531 command_buffer_ai.commandBufferCount = 1;
532 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
533
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600534 result = DispatchAllocateCommandBuffers(device_gpuav->device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700535 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700536 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700537 "Failed to create command buffer for acceleration structure build validation.");
538 }
539
540 // Hook up command buffer dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600541 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700542 }
543
544 if (result == VK_SUCCESS) {
545 VkCommandBufferBeginInfo command_buffer_bi = {};
546 command_buffer_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
547
548 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
549 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700550 ReportSetupProblem(device_gpuav->device, "Failed to begin command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700551 }
552 }
553
554 if (result == VK_SUCCESS) {
555 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
556 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
557 DispatchEndCommandBuffer(command_buffer);
558 }
559
560 VkQueue queue = VK_NULL_HANDLE;
561 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600562 DispatchGetDeviceQueue(device_gpuav->device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700563
564 // Hook up queue dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600565 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700566
567 VkSubmitInfo submit_info = {};
568 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
569 submit_info.commandBufferCount = 1;
570 submit_info.pCommandBuffers = &command_buffer;
571 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
572 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700573 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700574 "Failed to submit command buffer for acceleration structure build validation.");
575 }
576 }
577
578 if (result == VK_SUCCESS) {
579 result = DispatchQueueWaitIdle(queue);
580 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700581 ReportSetupProblem(device_gpuav->device, "Failed to wait for queue idle for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700582 }
583 }
584
585 if (vbo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600586 vmaDestroyBuffer(device_gpuav->vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700587 }
588 if (ibo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600589 vmaDestroyBuffer(device_gpuav->vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700590 }
591 if (scratch != VK_NULL_HANDLE) {
Tony-LunarG18900282020-05-20 12:34:33 -0600592 vmaDestroyBuffer(device_gpuav->vmaAllocator, scratch, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700593 }
594 if (command_pool != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600595 DispatchDestroyCommandPool(device_gpuav->device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700596 }
597
Tony-LunarG99b880b2019-09-26 11:19:52 -0600598 if (device_gpuav->debug_desc_layout == VK_NULL_HANDLE) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700599 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700600 "Failed to find descriptor set layout for acceleration structure build validation.");
601 result = VK_INCOMPLETE;
602 }
603
604 if (result == VK_SUCCESS) {
605 VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
606 pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
607 pipeline_layout_ci.setLayoutCount = 1;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600608 pipeline_layout_ci.pSetLayouts = &device_gpuav->debug_desc_layout;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600609 result = DispatchCreatePipelineLayout(device_gpuav->device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700610 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700611 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700612 "Failed to create pipeline layout for acceleration structure build validation.");
613 }
614 }
615
616 VkShaderModule shader_module = VK_NULL_HANDLE;
617 if (result == VK_SUCCESS) {
618 VkShaderModuleCreateInfo shader_module_ci = {};
619 shader_module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
620 shader_module_ci.codeSize = sizeof(kComputeShaderSpirv);
621 shader_module_ci.pCode = (uint32_t *)kComputeShaderSpirv;
622
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600623 result = DispatchCreateShaderModule(device_gpuav->device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700624 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700625 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700626 "Failed to create compute shader module for acceleration structure build validation.");
627 }
628 }
629
630 if (result == VK_SUCCESS) {
631 VkPipelineShaderStageCreateInfo pipeline_stage_ci = {};
632 pipeline_stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
633 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
634 pipeline_stage_ci.module = shader_module;
635 pipeline_stage_ci.pName = "main";
636
637 VkComputePipelineCreateInfo pipeline_ci = {};
638 pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
639 pipeline_ci.stage = pipeline_stage_ci;
640 pipeline_ci.layout = as_validation_state.pipeline_layout;
641
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600642 result = DispatchCreateComputePipelines(device_gpuav->device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr,
643 &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700644 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700645 ReportSetupProblem(device_gpuav->device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700646 "Failed to create compute pipeline for acceleration structure build validation.");
647 }
648 }
649
650 if (shader_module != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600651 DispatchDestroyShaderModule(device_gpuav->device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700652 }
653
654 if (result == VK_SUCCESS) {
655 as_validation_state.initialized = true;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700656 LogInfo(device_gpuav->device, "UNASSIGNED-GPU-Assisted Validation.",
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600657 "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700658 } else {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600659 device_gpuav->aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700660 }
661}
662
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600663void GpuAssisted::DestroyAccelerationStructureBuildValidationState() {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600664 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700665 if (as_validation_state.pipeline != VK_NULL_HANDLE) {
666 DispatchDestroyPipeline(device, as_validation_state.pipeline, nullptr);
667 }
668 if (as_validation_state.pipeline_layout != VK_NULL_HANDLE) {
669 DispatchDestroyPipelineLayout(device, as_validation_state.pipeline_layout, nullptr);
670 }
671 if (as_validation_state.replacement_as != VK_NULL_HANDLE) {
672 DispatchDestroyAccelerationStructureNV(device, as_validation_state.replacement_as, nullptr);
673 }
674 if (as_validation_state.replacement_as_allocation != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600675 vmaFreeMemory(vmaAllocator, as_validation_state.replacement_as_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700676 }
677}
678
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600679struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700680 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
681 VkPipeline pipeline = VK_NULL_HANDLE;
682 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
683 std::vector<VkDescriptorSet> descriptor_sets;
684 std::vector<std::vector<uint32_t>> dynamic_offsets;
685 uint32_t push_descriptor_set_index = 0;
686 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
687 std::vector<uint8_t> push_constants_data;
688 PushConstantRangesId push_constants_ranges;
689
690 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
691 pipeline_bind_point = bind_point;
692
693 LAST_BOUND_STATE &last_bound = cb_state->lastBound[bind_point];
694 if (last_bound.pipeline_state) {
695 pipeline = last_bound.pipeline_state->pipeline;
696 pipeline_layout = last_bound.pipeline_layout;
697 descriptor_sets.reserve(last_bound.per_set.size());
698 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
699 const auto *bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
700
701 descriptor_sets.push_back(bound_descriptor_set->GetSet());
702 if (bound_descriptor_set->IsPushDescriptor()) {
703 push_descriptor_set_index = static_cast<uint32_t>(i);
704 }
705 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
706 }
707
708 if (last_bound.push_descriptor_set) {
709 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
710 }
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500711 if (last_bound.pipeline_state->pipeline_layout->push_constant_ranges == cb_state->push_constant_data_ranges) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700712 push_constants_data = cb_state->push_constant_data;
Jeff Bolze7fc67b2019-10-04 12:29:31 -0500713 push_constants_ranges = last_bound.pipeline_state->pipeline_layout->push_constant_ranges;
Jason Macnak83cfd582019-07-31 10:14:24 -0700714 }
715 }
716 }
717
718 void Restore(VkCommandBuffer command_buffer) const {
719 if (pipeline != VK_NULL_HANDLE) {
720 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
721 if (!descriptor_sets.empty()) {
722 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
723 VkDescriptorSet descriptor_set = descriptor_sets[i];
724 if (descriptor_set != VK_NULL_HANDLE) {
725 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
726 static_cast<uint32_t>(i), 1, &descriptor_set,
727 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
728 }
729 }
730 }
731 if (!push_descriptor_set_writes.empty()) {
732 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
733 static_cast<uint32_t>(push_descriptor_set_writes.size()),
734 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
735 }
736 for (const auto &push_constant_range : *push_constants_ranges) {
737 if (push_constant_range.size == 0) continue;
738 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
739 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
740 }
741 }
742 }
743};
744
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600745void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
746 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
747 VkDeviceSize instanceOffset, VkBool32 update,
748 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
749 VkBuffer scratch, VkDeviceSize scratchOffset) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700750 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
751 return;
752 }
753
Tony-LunarG99b880b2019-09-26 11:19:52 -0600754 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700755 if (!as_validation_state.initialized) {
756 return;
757 }
758
759 // Empty acceleration structure is valid according to the spec.
760 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
761 return;
762 }
763
764 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
765 assert(cb_state != nullptr);
766
767 std::vector<uint64_t> current_valid_handles;
768 for (const auto &as_state_kv : accelerationStructureMap) {
769 const ACCELERATION_STRUCTURE_STATE &as_state = *as_state_kv.second;
Jeff Bolz95176d02020-04-01 00:36:16 -0500770 if (as_state.built && as_state.create_infoNV.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700771 current_valid_handles.push_back(as_state.opaque_handle);
772 }
773 }
774
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600775 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700776 as_validation_buffer_info.acceleration_structure = dst;
777
778 const VkDeviceSize validation_buffer_size =
779 // One uint for number of instances to validate
780 4 +
781 // Two uint for the replacement acceleration structure handle
782 8 +
783 // One uint for number of invalid handles found
784 4 +
785 // Two uint for the first invalid handle found
786 8 +
787 // One uint for the number of current valid handles
788 4 +
789 // Two uint for each current valid handle
790 (8 * current_valid_handles.size());
791
792 VkBufferCreateInfo validation_buffer_create_info = {};
793 validation_buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
794 validation_buffer_create_info.size = validation_buffer_size;
795 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
796
797 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
798 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
799
Tony-LunarG99b880b2019-09-26 11:19:52 -0600800 VkResult result = vmaCreateBuffer(vmaAllocator, &validation_buffer_create_info, &validation_buffer_alloc_info,
801 &as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -0700802 &as_validation_buffer_info.validation_buffer_allocation, nullptr);
803 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700804 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600805 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700806 return;
807 }
808
809 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600810 result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700811 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700812 ReportSetupProblem(device, "Unable to allocate device memory for acceleration structure build val buffer.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600813 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700814 return;
815 }
816
817 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
818 mapped_validation_buffer->replacement_handle_bits_0 =
819 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
820 mapped_validation_buffer->replacement_handle_bits_1 =
821 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
822 mapped_validation_buffer->invalid_handle_found = 0;
823 mapped_validation_buffer->invalid_handle_bits_0 = 0;
824 mapped_validation_buffer->invalid_handle_bits_1 = 0;
825 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
826
827 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
828 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
829 const uint64_t current_valid_handle = current_valid_handles[i];
830
831 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
832 ++mapped_valid_handles;
833 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
834 ++mapped_valid_handles;
835 }
836
Tony-LunarG99b880b2019-09-26 11:19:52 -0600837 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700838
839 static constexpr const VkDeviceSize kInstanceSize = 64;
840 const VkDeviceSize instance_buffer_size = kInstanceSize * pInfo->instanceCount;
841
Tony-LunarG1dce2392019-10-23 16:49:29 -0600842 result = desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool, debug_desc_layout,
843 &as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700844 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700845 ReportSetupProblem(device, "Unable to get descriptor set for acceleration structure build.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600846 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700847 return;
848 }
849
850 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
851 descriptor_buffer_infos[0].buffer = instanceData;
852 descriptor_buffer_infos[0].offset = instanceOffset;
853 descriptor_buffer_infos[0].range = instance_buffer_size;
854 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.validation_buffer;
855 descriptor_buffer_infos[1].offset = 0;
856 descriptor_buffer_infos[1].range = validation_buffer_size;
857
858 VkWriteDescriptorSet descriptor_set_writes[2] = {};
859 descriptor_set_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
860 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
861 descriptor_set_writes[0].dstBinding = 0;
862 descriptor_set_writes[0].descriptorCount = 1;
863 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
864 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
865 descriptor_set_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
866 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
867 descriptor_set_writes[1].dstBinding = 1;
868 descriptor_set_writes[1].descriptorCount = 1;
869 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
870 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
871
872 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
873
874 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
875 VkMemoryBarrier memory_barrier = {};
876 memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
877 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
878 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
879 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
880 &memory_barrier, 0, nullptr, 0, nullptr);
881
882 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600883 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700884 restorable_state.Create(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
885
886 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
887 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
888 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
889 &as_validation_buffer_info.descriptor_set, 0, nullptr);
890 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
891
892 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
893 // have been replaced by the validation compute shader before any builds take place.
894 VkBufferMemoryBarrier instance_buffer_barrier = {};
895 instance_buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
896 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
897 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
898 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
899 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
900 instance_buffer_barrier.buffer = instanceData;
901 instance_buffer_barrier.offset = instanceOffset;
902 instance_buffer_barrier.size = instance_buffer_size;
903 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
904 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
905 nullptr);
906
907 // Restore the previous compute pipeline state.
908 restorable_state.Restore(commandBuffer);
909
910 as_validation_state.validation_buffers[commandBuffer].push_back(std::move(as_validation_buffer_info));
911}
912
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600913void GpuAssisted::ProcessAccelerationStructureBuildValidationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700914 if (cb_node == nullptr || !cb_node->hasBuildAccelerationStructureCmd) {
915 return;
916 }
917
Tony-LunarG99b880b2019-09-26 11:19:52 -0600918 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700919 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[cb_node->commandBuffer];
920 for (const auto &as_validation_buffer_info : as_validation_buffer_infos) {
921 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
922
Tony-LunarG99b880b2019-09-26 11:19:52 -0600923 VkResult result =
924 vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700925 if (result == VK_SUCCESS) {
926 if (mapped_validation_buffer->invalid_handle_found > 0) {
927 uint64_t invalid_handle = 0;
928 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
929 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
930
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700931 LogError(as_validation_buffer_info.acceleration_structure, "UNASSIGNED-AccelerationStructure",
932 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
933 "handle (%" PRIu64 ")",
934 invalid_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700935 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600936 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700937 }
938 }
939}
940
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600941void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
942 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
943 VkResult result) {
944 if (VK_SUCCESS != result) return;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600945 ValidationStateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600946 for (uint32_t i = 0; i < bindInfoCount; i++) {
947 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
948 ACCELERATION_STRUCTURE_STATE *as_state = GetAccelerationStructureState(info.accelerationStructure);
949 if (as_state) {
950 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
951 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600952 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600953}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700954
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600955// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
956void GpuAssisted::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
957 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
958 void *cpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600959 if (aborted) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600960 return;
961 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600962
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600963 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
964
Tony-LunarG99b880b2019-09-26 11:19:52 -0600965 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600966 std::ostringstream strm;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600967 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Karl Schultz7b024b42018-08-30 16:18:18 -0600968 << "Application has too many descriptor sets in the pipeline layout to continue with gpu validation. "
969 << "Validation is not modifying the pipeline layout. "
970 << "Instrumented shaders are replaced with non-instrumented shaders.";
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700971 ReportSetupProblem(device, strm.str().c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -0600972 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700973 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Karl Schultz7b024b42018-08-30 16:18:18 -0600974 }
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700975}
976
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600977void GpuAssisted::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
978 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
979 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600980 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
981
Karl Schultz7b024b42018-08-30 16:18:18 -0600982 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700983 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600984 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600985 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600986}
987
Karl Schultz7b024b42018-08-30 16:18:18 -0600988// Free the device memory and descriptor set associated with a command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600989void GpuAssisted::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600990 if (aborted) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600991 return;
992 }
Tony-LunarG1dce2392019-10-23 16:49:29 -0600993 auto gpuav_buffer_list = GetBufferInfo(commandBuffer);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600994 for (auto buffer_info : gpuav_buffer_list) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600995 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600996 if (buffer_info.di_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600997 vmaDestroyBuffer(vmaAllocator, buffer_info.di_input_mem_block.buffer, buffer_info.di_input_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600998 }
999 if (buffer_info.bda_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001000 vmaDestroyBuffer(vmaAllocator, buffer_info.bda_input_mem_block.buffer, buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -06001001 }
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001002 if (buffer_info.desc_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001003 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001004 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001005 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001006 command_buffer_map.erase(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001007
Tony-LunarG99b880b2019-09-26 11:19:52 -06001008 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001009 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[commandBuffer];
1010 for (auto &as_validation_buffer_info : as_validation_buffer_infos) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001011 vmaDestroyBuffer(vmaAllocator, as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -07001012 as_validation_buffer_info.validation_buffer_allocation);
1013
1014 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001015 desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool,
1016 as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -07001017 }
1018 }
1019 as_validation_info.validation_buffers.erase(commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -06001020}
Karl Schultz7b024b42018-08-30 16:18:18 -06001021// Just gives a warning about a possible deadlock.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001022bool GpuAssisted::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
1023 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
1024 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1025 uint32_t bufferMemoryBarrierCount,
1026 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
Jeff Bolz5c801d12019-10-09 10:38:45 -05001027 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001028 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001029 ReportSetupProblem(commandBuffer,
Karl Schultz7b024b42018-08-30 16:18:18 -06001030 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1031 "GPU_Assisted validation waits on queue completion. "
1032 "This wait could block the host's signaling of this event, resulting in deadlock.");
1033 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001034 return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001035}
1036
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001037void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1038 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
1039 // 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 -06001040 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001041 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
1042 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
1043 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001044 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1045 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001046 }
1047 }
1048}
1049
1050void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1051 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
1052 // 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 -06001053 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001054 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
1055 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
1056 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001057 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1058 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001059 }
1060 }
1061}
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) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001067 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001068 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001069 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
1070 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001071 cgpl_state->gpu_create_infos = new_pipeline_create_infos;
1072 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001073}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001074
1075void GpuAssisted::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1076 const VkComputePipelineCreateInfo *pCreateInfos,
1077 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1078 void *ccpl_state_data) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001079 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001080 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001081 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
1082 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001083 ccpl_state->gpu_create_infos = new_pipeline_create_infos;
1084 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
Jason Macnak67407e72019-07-11 11:05:09 -07001085}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001086
1087void GpuAssisted::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1088 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1089 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1090 void *crtpl_state_data) {
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001091 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001092 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001093 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1094 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001095 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1096 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001097}
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001098
1099void GpuAssisted::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1100 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1101 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1102 void *crtpl_state_data) {
1103 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
1104 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001105 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
1106 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001107 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1108 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->gpu_create_infos.data());
1109}
Karl Schultz7b024b42018-08-30 16:18:18 -06001110
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001111void GpuAssisted::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1112 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1113 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1114 VkResult result, void *cgpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001115 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
1116 pPipelines, result, cgpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001117 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
1118 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, cgpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001119 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001120}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001121
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001122void GpuAssisted::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1123 const VkComputePipelineCreateInfo *pCreateInfos,
1124 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1125 VkResult result, void *ccpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001126 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1127 result, ccpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001128 create_compute_pipeline_api_state *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
1129 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, ccpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001130 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001131}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001132
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001133void GpuAssisted::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1134 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1135 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1136 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001137 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001138 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
1139 pPipelines, result, crtpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001140 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001141 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Jason Macnak67407e72019-07-11 11:05:09 -07001142}
1143
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001144void GpuAssisted::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1145 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
1146 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1147 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001148 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001149 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesKHR(device, pipelineCache, count, pCreateInfos, pAllocator,
1150 pPipelines, result, crtpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -06001151 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->gpu_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -07001152 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Karl Schultz7b024b42018-08-30 16:18:18 -06001153}
1154
1155// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001156void GpuAssisted::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001157 for (auto it = shader_map.begin(); it != shader_map.end();) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001158 if (it->second.pipeline == pipeline) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001159 it = shader_map.erase(it);
Karl Schultz7b024b42018-08-30 16:18:18 -06001160 } else {
1161 ++it;
1162 }
1163 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001164 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001165}
1166
1167// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001168bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
1169 uint32_t *unique_shader_id) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001170 if (aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001171 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
1172
Tony-LunarG79641702020-07-13 15:43:05 -06001173 const spvtools::MessageConsumer GpuConsoleMessageConsumer =
1174 [this](spv_message_level_t level, const char *, const spv_position_t &position, const char *message) -> void {
1175 switch (level) {
1176 case SPV_MSG_FATAL:
1177 case SPV_MSG_INTERNAL_ERROR:
1178 case SPV_MSG_ERROR:
1179 this->LogError(this->device, "UNASSIGNED-GPU-Assisted", "Error during shader instrumentation: line %zu: %s",
1180 position.index, message);
1181 break;
1182 default:
1183 break;
1184 }
1185 };
1186
Karl Schultz7b024b42018-08-30 16:18:18 -06001187 // Load original shader SPIR-V
1188 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
1189 new_pgm.clear();
1190 new_pgm.reserve(num_words);
1191 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
1192
1193 // Call the optimizer to instrument the shader.
1194 // 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 -07001195 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Karl Schultz7b024b42018-08-30 16:18:18 -06001196 using namespace spvtools;
Tony-LunarG8a51b7d2020-07-01 15:57:23 -06001197 spv_target_env target_env = PickSpirvEnv(api_version, (device_extensions.vk_khr_spirv_1_4 != kNotEnabled));
Tony-LunarG9fe69a42020-07-23 15:09:37 -06001198 spvtools::ValidatorOptions options;
1199 AdjustValidatorOptions(device_extensions, enabled_features, options);
Karl Schultz7b024b42018-08-30 16:18:18 -06001200 Optimizer optimizer(target_env);
Tony-LunarG79641702020-07-13 15:43:05 -06001201 optimizer.SetMessageConsumer(GpuConsoleMessageConsumer);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001202 optimizer.RegisterPass(
Tony-LunarGab47cac2019-12-20 15:28:01 -07001203 CreateInstBindlessCheckPass(desc_set_bind_index, unique_shader_module_id, descriptor_indexing, descriptor_indexing));
Karl Schultz7b024b42018-08-30 16:18:18 -06001204 optimizer.RegisterPass(CreateAggressiveDCEPass());
Tony-LunarG5c38b182020-06-10 16:15:32 -06001205 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) && shaderInt64 &&
1206 enabled_features.core12.bufferDeviceAddress)
Tony-LunarG99b880b2019-09-26 11:19:52 -06001207 optimizer.RegisterPass(CreateInstBuffAddrCheckPass(desc_set_bind_index, unique_shader_module_id));
Tony-LunarG9fe69a42020-07-23 15:09:37 -06001208 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm, options, false);
Karl Schultz7b024b42018-08-30 16:18:18 -06001209 if (!pass) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001210 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Karl Schultz7b024b42018-08-30 16:18:18 -06001211 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001212 *unique_shader_id = unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -06001213 return pass;
1214}
Mark Lobodzinski01734072019-02-13 17:39:15 -07001215// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001216void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
1217 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
1218 void *csm_state_data) {
1219 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
1220 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -06001221 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001222 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
1223 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
Karl Schultz7b024b42018-08-30 16:18:18 -06001224 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001225}
1226
Karl Schultz7b024b42018-08-30 16:18:18 -06001227// Generate the part of the message describing the violation.
1228static void GenerateValidationMessage(const uint32_t *debug_record, std::string &msg, std::string &vuid_msg) {
1229 using namespace spvtools;
1230 std::ostringstream strm;
Tony-LunarGab47cac2019-12-20 15:28:01 -07001231 switch (debug_record[kInstValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001232 case kInstErrorBindlessBounds: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001233 strm << "Index of " << debug_record[kInstBindlessBoundsOutDescIndex] << " used to index descriptor array of length "
1234 << debug_record[kInstBindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001235 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -06001236 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001237 case kInstErrorBindlessUninit: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001238 strm << "Descriptor index " << debug_record[kInstBindlessUninitOutDescIndex] << " is uninitialized. ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001239 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -06001240 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001241 case kInstErrorBuffAddrUnallocRef: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001242 uint64_t *ptr = (uint64_t *)&debug_record[kInstBuffAddrUnallocOutDescPtrLo];
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001243 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
1244 vuid_msg = "UNASSIGNED-Device address out of bounds";
1245 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001246 default: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001247 strm << "Internal Error (unexpected error type = " << debug_record[kInstValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001248 vuid_msg = "UNASSIGNED-Internal Error";
1249 assert(false);
1250 } break;
1251 }
1252 msg = strm.str();
1253}
1254
Karl Schultz7b024b42018-08-30 16:18:18 -06001255// Pull together all the information from the debug record to build the error message strings,
1256// and then assemble them into a single message string.
1257// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
1258// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
1259// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
1260// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
1261//
Tony-LunarG1dce2392019-10-23 16:49:29 -06001262void GpuAssisted::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, VkPipelineBindPoint pipeline_bind_point,
1263 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001264 using namespace spvtools;
1265 const uint32_t total_words = debug_output_buffer[0];
1266 // A zero here means that the shader instrumentation didn't write anything.
1267 // If you have nothing to say, don't say it here.
1268 if (0 == total_words) {
1269 return;
1270 }
1271 // The first word in the debug output buffer is the number of words that would have
1272 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
1273 // The number of words actually written by the shaders is determined by the size of the buffer
1274 // we provide via the descriptor. So, we process only the number of words that can fit in the
1275 // buffer.
1276 // Each "report" written by the shader instrumentation is considered a "record". This function
1277 // is hard-coded to process only one record because it expects the buffer to be large enough to
1278 // hold only one record. If there is a desire to process more than one record, this function needs
1279 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06001280 std::string validation_message;
1281 std::string stage_message;
1282 std::string common_message;
1283 std::string filename_message;
1284 std::string source_message;
1285 std::string vuid_msg;
1286 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
1287 VkPipeline pipeline_handle = VK_NULL_HANDLE;
1288 std::vector<unsigned int> pgm;
1289 // The first record starts at this offset after the total_words.
1290 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
1291 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
1292 // by the instrumented shader.
Tony-LunarG99b880b2019-09-26 11:19:52 -06001293 auto it = shader_map.find(debug_record[kInstCommonOutShaderId]);
1294 if (it != shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001295 shader_module_handle = it->second.shader_module;
1296 pipeline_handle = it->second.pipeline;
1297 pgm = it->second.pgm;
1298 }
1299 GenerateValidationMessage(debug_record, validation_message, vuid_msg);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001300 UtilGenerateStageMessage(debug_record, stage_message);
1301 UtilGenerateCommonMessage(report_data, command_buffer, debug_record, shader_module_handle, pipeline_handle, pipeline_bind_point,
1302 operation_index, common_message);
1303 UtilGenerateSourceMessages(pgm, debug_record, false, filename_message, source_message);
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001304 LogError(queue, vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
1305 filename_message.c_str(), source_message.c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -06001306 // The debug record at word kInstCommonOutSize is the number of words in the record
1307 // written by the shader. Clear the entire record plus the total_words word at the start.
Tony-LunarGab47cac2019-12-20 15:28:01 -07001308 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], (uint32_t)kInstMaxOutCnt);
Karl Schultz7b024b42018-08-30 16:18:18 -06001309 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
1310}
1311
Tony-LunarG81efe392019-03-07 15:43:27 -07001312// For the given command buffer, map its debug data buffers and update the status of any update after bind descriptors
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001313void GpuAssisted::UpdateInstrumentationBuffer(CMD_BUFFER_STATE *cb_node) {
Tony-LunarG1dce2392019-10-23 16:49:29 -06001314 auto gpu_buffer_list = GetBufferInfo(cb_node->commandBuffer);
Tony-LunarG81efe392019-03-07 15:43:27 -07001315 uint32_t *pData;
1316 for (auto &buffer_info : gpu_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001317 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001318 VkResult result = vmaMapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation, (void **)&pData);
Tony-LunarG81efe392019-03-07 15:43:27 -07001319 if (result == VK_SUCCESS) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001320 for (auto update : buffer_info.di_input_mem_block.update_at_submit) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001321 if (update.second->updated) pData[update.first] = 1;
1322 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001323 vmaUnmapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07001324 }
1325 }
1326 }
1327}
1328
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001329void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001330 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1331 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1332 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001333 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07001334 UpdateInstrumentationBuffer(cb_node);
1335 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
1336 UpdateInstrumentationBuffer(secondaryCmdBuffer);
1337 }
1338 }
1339 }
1340}
1341
Karl Schultz58674242019-01-22 15:35:02 -07001342// Issue a memory barrier to make GPU-written data available to host.
1343// Wait for the queue to complete execution.
1344// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001345void GpuAssisted::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
1346 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001347 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001348
Mark Lobodzinski09379db2020-05-07 08:22:01 -06001349 if (aborted || (result != VK_SUCCESS)) return;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001350 bool buffers_present = false;
1351 // Don't QueueWaitIdle if there's nothing to process
1352 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1353 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1354 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
1355 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG1dce2392019-10-23 16:49:29 -06001356 if (GetBufferInfo(cb_node->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd) buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001357 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarG1dce2392019-10-23 16:49:29 -06001358 if (GetBufferInfo(secondaryCmdBuffer->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd)
Jason Macnak83cfd582019-07-31 10:14:24 -07001359 buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06001360 }
1361 }
1362 }
1363 if (!buffers_present) return;
Karl Schultz58674242019-01-22 15:35:02 -07001364
Tony-LunarGb5fae462020-03-05 12:43:25 -07001365 UtilSubmitBarrier(queue, this);
Karl Schultz58674242019-01-22 15:35:02 -07001366
Tony-LunarG152a88b2019-03-20 15:42:24 -06001367 DispatchQueueWaitIdle(queue);
Karl Schultz58674242019-01-22 15:35:02 -07001368
Karl Schultz7b024b42018-08-30 16:18:18 -06001369 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1370 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1371 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001372 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarGb5fae462020-03-05 12:43:25 -07001373 UtilProcessInstrumentationBuffer(queue, cb_node, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001374 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06001375 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarGb5fae462020-03-05 12:43:25 -07001376 UtilProcessInstrumentationBuffer(queue, secondaryCmdBuffer, this);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001377 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06001378 }
1379 }
1380 }
1381}
Tony-LunarGb2501d22019-01-28 09:59:13 -07001382
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001383void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
1384 uint32_t firstVertex, uint32_t firstInstance) {
1385 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1386}
1387
1388void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
1389 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
1390 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1391}
1392
1393void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
1394 uint32_t stride) {
1395 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1396}
1397
1398void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1399 uint32_t count, uint32_t stride) {
1400 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1401}
1402
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001403void GpuAssisted::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1404 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1405 uint32_t stride) {
1406 ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1407 maxDrawCount, stride);
1408 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1409}
1410
1411void GpuAssisted::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1412 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1413 uint32_t stride) {
1414 ValidationStateTracker::PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1415 maxDrawCount, stride);
1416 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1417}
1418
1419void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1420 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1421 uint32_t maxDrawCount, uint32_t stride) {
1422 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer,
1423 countBufferOffset, maxDrawCount, stride);
1424 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1425}
1426
1427void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1428 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1429 uint32_t maxDrawCount, uint32_t stride) {
1430 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1431 maxDrawCount, stride);
1432 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1433}
1434
1435void GpuAssisted::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
1436 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
1437 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1438}
1439
1440void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1441 uint32_t drawCount, uint32_t stride) {
1442 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
1443 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1444}
1445
1446void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1447 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1448 uint32_t maxDrawCount, uint32_t stride) {
1449 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer,
1450 countBufferOffset, maxDrawCount, stride);
1451 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
1452}
1453
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001454void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
1455 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1456}
1457
1458void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
1459 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1460}
1461
Tony-LunarGd13f9b52020-09-08 15:45:45 -06001462void GpuAssisted::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1463 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1464 uint32_t groupCountZ) {
1465 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
1466}
1467
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001468void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1469 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1470 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1471 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1472 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1473 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1474 uint32_t width, uint32_t height, uint32_t depth) {
1475 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
1476}
1477
1478void GpuAssisted::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1479 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1480 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1481 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1482 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1483 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1484 uint32_t width, uint32_t height, uint32_t depth) {
1485 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1486 cb_state->hasTraceRaysCmd = true;
1487}
1488
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001489void GpuAssisted::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
1490 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1491 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1492 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1493 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, uint32_t width,
1494 uint32_t height, uint32_t depth) {
1495 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
1496}
1497
1498void GpuAssisted::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
1499 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1500 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1501 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1502 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, uint32_t width,
1503 uint32_t height, uint32_t depth) {
1504 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1505 cb_state->hasTraceRaysCmd = true;
1506}
1507
1508void GpuAssisted::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
1509 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1510 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1511 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1512 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, VkBuffer buffer,
1513 VkDeviceSize offset) {
1514 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
1515}
1516
1517void GpuAssisted::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
1518 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
1519 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
1520 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
1521 const VkStridedBufferRegionKHR *pCallableShaderBindingTable,
1522 VkBuffer buffer, VkDeviceSize offset) {
1523 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1524 cb_state->hasTraceRaysCmd = true;
1525}
1526
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001527void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Jason Macnak67407e72019-07-11 11:05:09 -07001528 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1529 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
andreygca287f22019-04-10 00:15:33 +03001530 return;
1531 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001532 VkResult result;
1533
Tony-LunarG99b880b2019-09-26 11:19:52 -06001534 if (aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001535
1536 std::vector<VkDescriptorSet> desc_sets;
1537 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -06001538 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001539 assert(result == VK_SUCCESS);
1540 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001541 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001542 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001543 return;
1544 }
1545
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001546 VkDescriptorBufferInfo output_desc_buffer_info = {};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001547 output_desc_buffer_info.range = output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001548
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06001549 auto cb_node = GetCBState(cmd_buffer);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001550 if (!cb_node) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001551 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001552 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001553 return;
1554 }
1555
Tony-LunarG81efe392019-03-07 15:43:27 -07001556 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001557 GpuAssistedDeviceMemoryBlock output_block = {};
Tony-LunarG0e564722019-03-19 16:09:14 -06001558 VkBufferCreateInfo bufferInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001559 bufferInfo.size = output_buffer_size;
Tony-LunarG0e564722019-03-19 16:09:14 -06001560 bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1561 VmaAllocationCreateInfo allocInfo = {};
1562 allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001563 result = vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001564 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001565 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001566 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001567 return;
1568 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001569
Tony-LunarG81efe392019-03-07 15:43:27 -07001570 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGa77cade2019-03-06 10:49:22 -07001571 uint32_t *pData;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001572 result = vmaMapMemory(vmaAllocator, output_block.allocation, (void **)&pData);
Tony-LunarG0e564722019-03-19 16:09:14 -06001573 if (result == VK_SUCCESS) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001574 memset(pData, 0, output_buffer_size);
1575 vmaUnmapMemory(vmaAllocator, output_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001576 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001577
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001578 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001579 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
1580 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
1581 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001582 uint32_t desc_count = 1;
1583 auto const &state = cb_node->lastBound[bind_point];
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001584 uint32_t number_of_sets = (uint32_t)state.per_set.size();
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001585
Tony-LunarG81efe392019-03-07 15:43:27 -07001586 // Figure out how much memory we need for the input block based on how many sets and bindings there are
1587 // and how big each of the bindings is
Tony-LunarG5c38b182020-06-10 16:15:32 -06001588 if (number_of_sets > 0 && descriptor_indexing) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001589 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
1590 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001591 for (auto s : state.per_set) {
1592 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06001593 if (desc && (desc->GetBindingCount() > 0)) {
1594 auto bindings = desc->GetLayout()->GetSortedBindingSet();
Tony-LunarGa77cade2019-03-06 10:49:22 -07001595 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
1596 for (auto binding : bindings) {
Tony-LunarG7564b382019-08-21 10:11:35 -06001597 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1598 // blocks
1599 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1600 descriptor_count++;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001601 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
1602 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
1603 "validation");
Tony-LunarG7564b382019-08-21 10:11:35 -06001604 } else if (binding == desc->GetLayout()->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001605 descriptor_count += desc->GetVariableDescriptorCount();
1606 } else {
1607 descriptor_count += desc->GetDescriptorCountFromBinding(binding);
1608 }
1609 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001610 }
1611 }
1612
Tony-LunarGa77cade2019-03-06 10:49:22 -07001613 // Note that the size of the input buffer is dependent on the maximum binding number, which
1614 // can be very large. This is because for (set = s, binding = b, index = i), the validation
1615 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
1616 // see if descriptors have been written. In gpu_validation.md, we note this and advise
1617 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
1618 uint32_t words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001619 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
1620 bufferInfo.size = words_needed * 4;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001621 result =
1622 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &di_input_block.buffer, &di_input_block.allocation, nullptr);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001623 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001624 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001625 aborted = true;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001626 return;
1627 }
1628
Tony-LunarGa77cade2019-03-06 10:49:22 -07001629 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
1630 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
1631 // outline of the input buffer format
Tony-LunarG99b880b2019-09-26 11:19:52 -06001632 result = vmaMapMemory(vmaAllocator, di_input_block.allocation, (void **)&pData);
Tony-LunarG76cdcac2019-05-22 16:13:12 -06001633 memset(pData, 0, static_cast<size_t>(bufferInfo.size));
Tony-LunarGa77cade2019-03-06 10:49:22 -07001634 // Pointer to a sets array that points into the sizes array
1635 uint32_t *sets_to_sizes = pData + 1;
1636 // Pointer to the sizes array that contains the array size of the descriptor at each binding
1637 uint32_t *sizes = sets_to_sizes + number_of_sets;
1638 // Pointer to another sets array that points into the bindings array that points into the written array
1639 uint32_t *sets_to_bindings = sizes + binding_count;
1640 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
1641 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
1642 // Index of the next entry in the written array to be updated
1643 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001644 uint32_t bindCounter = number_of_sets + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07001645 // Index of the start of the sets_to_bindings array
1646 pData[0] = number_of_sets + binding_count + 1;
1647
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001648 for (auto s : state.per_set) {
1649 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06001650 if (desc && (desc->GetBindingCount() > 0)) {
1651 auto layout = desc->GetLayout();
1652 auto bindings = layout->GetSortedBindingSet();
Tony-LunarG81efe392019-03-07 15:43:27 -07001653 // For each set, fill in index of its bindings sizes in the sizes array
Tony-LunarGa77cade2019-03-06 10:49:22 -07001654 *sets_to_sizes++ = bindCounter;
Tony-LunarG81efe392019-03-07 15:43:27 -07001655 // For each set, fill in the index of its bindings in the bindings_to_written array
Tony-LunarGa77cade2019-03-06 10:49:22 -07001656 *sets_to_bindings++ = bindCounter + number_of_sets + binding_count;
Tony-LunarG81efe392019-03-07 15:43:27 -07001657 for (auto binding : bindings) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001658 // For each binding, fill in its size in the sizes array
Tony-LunarG7564b382019-08-21 10:11:35 -06001659 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1660 // blocks
1661 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1662 sizes[binding] = 1;
1663 } else if (binding == layout->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001664 sizes[binding] = desc->GetVariableDescriptorCount();
1665 } else {
1666 sizes[binding] = desc->GetDescriptorCountFromBinding(binding);
1667 }
1668 // Fill in the starting index for this binding in the written array in the bindings_to_written array
1669 bindings_to_written[binding] = written_index;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001670
Tony-LunarG7564b382019-08-21 10:11:35 -06001671 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1672 // blocks
1673 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
1674 pData[written_index++] = 1;
1675 continue;
1676 }
1677
Tony-LunarGa77cade2019-03-06 10:49:22 -07001678 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
1679 // For each array element in the binding, update the written array with whether it has been written
1680 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
1681 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
Tony-LunarG81efe392019-03-07 15:43:27 -07001682 if (descriptor->updated) {
1683 pData[written_index] = 1;
1684 } else if (desc->IsUpdateAfterBind(binding)) {
1685 // If it hasn't been written now and it's update after bind, put it in a list to check at QueueSubmit
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001686 di_input_block.update_at_submit[written_index] = descriptor;
Tony-LunarG81efe392019-03-07 15:43:27 -07001687 }
Tony-LunarGa77cade2019-03-06 10:49:22 -07001688 written_index++;
1689 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001690 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001691 auto last = desc->GetLayout()->GetMaxBinding();
1692 bindings_to_written += last + 1;
1693 bindCounter += last + 1;
1694 sizes += last + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07001695 } else {
1696 *sets_to_sizes++ = 0;
1697 *sets_to_bindings++ = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001698 }
1699 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001700 vmaUnmapMemory(vmaAllocator, di_input_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001701
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001702 di_input_desc_buffer_info.range = (words_needed * 4);
1703 di_input_desc_buffer_info.buffer = di_input_block.buffer;
1704 di_input_desc_buffer_info.offset = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001705
1706 desc_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1707 desc_writes[1].dstBinding = 1;
1708 desc_writes[1].descriptorCount = 1;
1709 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001710 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001711 desc_writes[1].dstSet = desc_sets[0];
1712
1713 desc_count = 2;
Tony-LunarG0e564722019-03-19 16:09:14 -06001714 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001715
Tony-LunarGc111b242020-06-30 14:43:45 -06001716 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) && buffer_map.size() &&
Tony-LunarG5c38b182020-06-10 16:15:32 -06001717 shaderInt64 && enabled_features.core12.bufferDeviceAddress) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001718 // Example BDA input buffer assuming 2 buffers using BDA:
1719 // Word 0 | Index of start of buffer sizes (in this case 5)
1720 // Word 1 | 0x0000000000000000
1721 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
1722 // Word 3 | Device Address of second buffer
1723 // Word 4 | 0xffffffffffffffff
1724 // Word 5 | 0 (size of pretend buffer at word 1)
1725 // Word 6 | Size in bytes of first buffer
1726 // Word 7 | Size in bytes of second buffer
1727 // Word 8 | 0 (size of pretend buffer in word 4)
1728
Tony-LunarG99b880b2019-09-26 11:19:52 -06001729 uint32_t num_buffers = static_cast<uint32_t>(buffer_map.size());
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001730 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
1731 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
1732 bufferInfo.size = words_needed * 8; // 64 bit words
Tony-LunarG99b880b2019-09-26 11:19:52 -06001733 result =
1734 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &bda_input_block.buffer, &bda_input_block.allocation, nullptr);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001735 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001736 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001737 aborted = true;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001738 return;
1739 }
1740 uint64_t *bda_data;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001741 result = vmaMapMemory(vmaAllocator, bda_input_block.allocation, (void **)&bda_data);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001742 uint32_t address_index = 1;
1743 uint32_t size_index = 3 + num_buffers;
1744 memset(bda_data, 0, static_cast<size_t>(bufferInfo.size));
1745 bda_data[0] = size_index; // Start of buffer sizes
1746 bda_data[address_index++] = 0; // NULL address
1747 bda_data[size_index++] = 0;
1748
Tony-LunarG99b880b2019-09-26 11:19:52 -06001749 for (auto const &value : buffer_map) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001750 bda_data[address_index++] = value.first;
1751 bda_data[size_index++] = value.second;
1752 }
1753 bda_data[address_index] = UINTPTR_MAX;
1754 bda_data[size_index] = 0;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001755 vmaUnmapMemory(vmaAllocator, bda_input_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001756
1757 bda_input_desc_buffer_info.range = (words_needed * 8);
1758 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
1759 bda_input_desc_buffer_info.offset = 0;
1760
1761 desc_writes[desc_count].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1762 desc_writes[desc_count].dstBinding = 2;
1763 desc_writes[desc_count].descriptorCount = 1;
1764 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1765 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
1766 desc_writes[desc_count].dstSet = desc_sets[0];
1767 desc_count++;
1768 }
1769
Tony-LunarGb2501d22019-01-28 09:59:13 -07001770 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001771 output_desc_buffer_info.buffer = output_block.buffer;
1772 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001773
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001774 desc_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1775 desc_writes[0].descriptorCount = 1;
1776 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1777 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
1778 desc_writes[0].dstSet = desc_sets[0];
1779 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001780
andreyg25ce2622019-04-05 23:07:59 +03001781 auto iter = cb_node->lastBound.find(bind_point); // find() allows read-only access to cb_state
Tony-LunarGb2501d22019-01-28 09:59:13 -07001782 if (iter != cb_node->lastBound.end()) {
1783 auto pipeline_state = iter->second.pipeline_state;
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06001784 if (pipeline_state && (pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index) &&
1785 !pipeline_state->pipeline_layout->destroyed) {
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001786 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout, desc_set_bind_index, 1,
Tony-LunarG99b880b2019-09-26 11:19:52 -06001787 desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001788 }
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06001789 if (pipeline_state && pipeline_state->pipeline_layout->destroyed) {
1790 ReportSetupProblem(device, "Pipeline layout has been destroyed, aborting GPU-AV");
1791 aborted = true;
1792 } else {
1793 // Record buffer and memory info in CB state tracking
1794 GetBufferInfo(cmd_buffer)
1795 .emplace_back(output_block, di_input_block, bda_input_block, desc_sets[0], desc_pool, bind_point);
1796 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001797 } else {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001798 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06001799 aborted = true;
1800 }
1801 if (aborted) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001802 vmaDestroyBuffer(vmaAllocator, di_input_block.buffer, di_input_block.allocation);
1803 vmaDestroyBuffer(vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
1804 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001805 return;
1806 }
1807}