blob: 66cfa3aa7e42e7f759c9f208220cdfe845621e5c [file] [log] [blame]
Karl Schultz7b024b42018-08-30 16:18:18 -06001/* Copyright (c) 2018-2019 The Khronos Group Inc.
2 * Copyright (c) 2018-2019 Valve Corporation
3 * Copyright (c) 2018-2019 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
21// Allow use of STL min and max functions in Windows
22#define NOMINMAX
Tony-LunarG0e564722019-03-19 16:09:14 -060023// This define indicates to build the VMA routines themselves
24#define VMA_IMPLEMENTATION
25// This define indicates that we will supply Vulkan function pointers at initialization
26#define VMA_STATIC_VULKAN_FUNCTIONS 0
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -070027#include "gpu_validation.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060028#include "shader_validation.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060029#include "spirv-tools/libspirv.h"
30#include "spirv-tools/optimizer.hpp"
31#include "spirv-tools/instrument.hpp"
32#include <SPIRV/spirv.hpp>
33#include <algorithm>
34#include <regex>
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060035#include "layer_chassis_dispatch.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060036
37// This is the number of bindings in the debug descriptor set.
Tony-LunarG8eb5a002019-07-25 16:49:00 -060038static const uint32_t kNumBindingsInSet = 3;
Karl Schultz7b024b42018-08-30 16:18:18 -060039
Jason Macnak67407e72019-07-11 11:05:09 -070040static const VkShaderStageFlags kShaderStageAllRayTracing =
41 VK_SHADER_STAGE_ANY_HIT_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV | VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV |
42 VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV | VK_SHADER_STAGE_RAYGEN_BIT_NV;
43
Jason Macnak83cfd582019-07-31 10:14:24 -070044// Keep in sync with the GLSL shader below.
45struct GpuAccelerationStructureBuildValidationBuffer {
46 uint32_t instances_to_validate;
47 uint32_t replacement_handle_bits_0;
48 uint32_t replacement_handle_bits_1;
49 uint32_t invalid_handle_found;
50 uint32_t invalid_handle_bits_0;
51 uint32_t invalid_handle_bits_1;
52 uint32_t valid_handles_count;
53};
54
55// This is the GLSL source for the compute shader that is used during ray tracing acceleration structure
56// building validation which inspects instance buffers for top level acceleration structure builds and
57// reports and replaces invalid bottom level acceleration structure handles with good bottom level
58// acceleration structure handle so that applications can continue without undefined behavior long enough
59// to report errors.
60//
61// #version 450
62// layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
63// struct VkGeometryInstanceNV {
64// uint unused[14];
65// uint handle_bits_0;
66// uint handle_bits_1;
67// };
68// layout(set=0, binding=0, std430) buffer InstanceBuffer {
69// VkGeometryInstanceNV instances[];
70// };
71// layout(set=0, binding=1, std430) buffer ValidationBuffer {
72// uint instances_to_validate;
73// uint replacement_handle_bits_0;
74// uint replacement_handle_bits_1;
75// uint invalid_handle_found;
76// uint invalid_handle_bits_0;
77// uint invalid_handle_bits_1;
78// uint valid_handles_count;
79// uint valid_handles[];
80// };
81// void main() {
82// for (uint instance_index = 0; instance_index < instances_to_validate; instance_index++) {
83// uint instance_handle_bits_0 = instances[instance_index].handle_bits_0;
84// uint instance_handle_bits_1 = instances[instance_index].handle_bits_1;
85// bool valid = false;
86// for (uint valid_handle_index = 0; valid_handle_index < valid_handles_count; valid_handle_index++) {
87// if (instance_handle_bits_0 == valid_handles[2*valid_handle_index+0] &&
88// instance_handle_bits_1 == valid_handles[2*valid_handle_index+1]) {
89// valid = true;
90// break;
91// }
92// }
93// if (!valid) {
94// invalid_handle_found += 1;
95// invalid_handle_bits_0 = instance_handle_bits_0;
96// invalid_handle_bits_1 = instance_handle_bits_1;
97// instances[instance_index].handle_bits_0 = replacement_handle_bits_0;
98// instances[instance_index].handle_bits_1 = replacement_handle_bits_1;
99// }
100// }
101// }
102//
103// To regenerate the spirv below:
104// 1. Save the above GLSL source to a file called validation_shader.comp.
105// 2. Run in terminal
106//
107// glslangValidator.exe -x -V validation_shader.comp -o validation_shader.comp.spv
108//
109// 4. Copy-paste the contents of validation_shader.comp.spv here (clang-format will fix up the alignment).
110static const uint32_t kComputeShaderSpirv[] = {
111 0x07230203, 0x00010000, 0x00080007, 0x0000006d, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, 0x00000001, 0x4c534c47,
112 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0005000f, 0x00000005, 0x00000004, 0x6e69616d,
113 0x00000000, 0x00060010, 0x00000004, 0x00000011, 0x00000001, 0x00000001, 0x00000001, 0x00030003, 0x00000002, 0x000001c2,
114 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00060005, 0x00000008, 0x74736e69, 0x65636e61, 0x646e695f, 0x00007865,
115 0x00070005, 0x00000011, 0x696c6156, 0x69746164, 0x75426e6f, 0x72656666, 0x00000000, 0x00090006, 0x00000011, 0x00000000,
116 0x74736e69, 0x65636e61, 0x6f745f73, 0x6c61765f, 0x74616469, 0x00000065, 0x000a0006, 0x00000011, 0x00000001, 0x6c706572,
117 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x000a0006, 0x00000011, 0x00000002, 0x6c706572,
118 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00090006, 0x00000011, 0x00000003, 0x61766e69,
119 0x5f64696c, 0x646e6168, 0x665f656c, 0x646e756f, 0x00000000, 0x00090006, 0x00000011, 0x00000004, 0x61766e69, 0x5f64696c,
120 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00090006, 0x00000011, 0x00000005, 0x61766e69, 0x5f64696c, 0x646e6168,
121 0x625f656c, 0x5f737469, 0x00000031, 0x00080006, 0x00000011, 0x00000006, 0x696c6176, 0x61685f64, 0x656c646e, 0x6f635f73,
122 0x00746e75, 0x00070006, 0x00000011, 0x00000007, 0x696c6176, 0x61685f64, 0x656c646e, 0x00000073, 0x00030005, 0x00000013,
123 0x00000000, 0x00080005, 0x0000001b, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000305f, 0x00080005,
124 0x0000001e, 0x65476b56, 0x74656d6f, 0x6e497972, 0x6e617473, 0x564e6563, 0x00000000, 0x00050006, 0x0000001e, 0x00000000,
125 0x73756e75, 0x00006465, 0x00070006, 0x0000001e, 0x00000001, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00070006,
126 0x0000001e, 0x00000002, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00060005, 0x00000020, 0x74736e49, 0x65636e61,
127 0x66667542, 0x00007265, 0x00060006, 0x00000020, 0x00000000, 0x74736e69, 0x65636e61, 0x00000073, 0x00030005, 0x00000022,
128 0x00000000, 0x00080005, 0x00000027, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000315f, 0x00040005,
129 0x0000002d, 0x696c6176, 0x00000064, 0x00070005, 0x0000002f, 0x696c6176, 0x61685f64, 0x656c646e, 0x646e695f, 0x00007865,
130 0x00040047, 0x00000010, 0x00000006, 0x00000004, 0x00050048, 0x00000011, 0x00000000, 0x00000023, 0x00000000, 0x00050048,
131 0x00000011, 0x00000001, 0x00000023, 0x00000004, 0x00050048, 0x00000011, 0x00000002, 0x00000023, 0x00000008, 0x00050048,
132 0x00000011, 0x00000003, 0x00000023, 0x0000000c, 0x00050048, 0x00000011, 0x00000004, 0x00000023, 0x00000010, 0x00050048,
133 0x00000011, 0x00000005, 0x00000023, 0x00000014, 0x00050048, 0x00000011, 0x00000006, 0x00000023, 0x00000018, 0x00050048,
134 0x00000011, 0x00000007, 0x00000023, 0x0000001c, 0x00030047, 0x00000011, 0x00000003, 0x00040047, 0x00000013, 0x00000022,
135 0x00000000, 0x00040047, 0x00000013, 0x00000021, 0x00000001, 0x00040047, 0x0000001d, 0x00000006, 0x00000004, 0x00050048,
136 0x0000001e, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x0000001e, 0x00000001, 0x00000023, 0x00000038, 0x00050048,
137 0x0000001e, 0x00000002, 0x00000023, 0x0000003c, 0x00040047, 0x0000001f, 0x00000006, 0x00000040, 0x00050048, 0x00000020,
138 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x00000020, 0x00000003, 0x00040047, 0x00000022, 0x00000022, 0x00000000,
139 0x00040047, 0x00000022, 0x00000021, 0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00040015,
140 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, 0x00000006, 0x0004002b, 0x00000006, 0x00000009,
141 0x00000000, 0x0003001d, 0x00000010, 0x00000006, 0x000a001e, 0x00000011, 0x00000006, 0x00000006, 0x00000006, 0x00000006,
142 0x00000006, 0x00000006, 0x00000006, 0x00000010, 0x00040020, 0x00000012, 0x00000002, 0x00000011, 0x0004003b, 0x00000012,
143 0x00000013, 0x00000002, 0x00040015, 0x00000014, 0x00000020, 0x00000001, 0x0004002b, 0x00000014, 0x00000015, 0x00000000,
144 0x00040020, 0x00000016, 0x00000002, 0x00000006, 0x00020014, 0x00000019, 0x0004002b, 0x00000006, 0x0000001c, 0x0000000e,
145 0x0004001c, 0x0000001d, 0x00000006, 0x0000001c, 0x0005001e, 0x0000001e, 0x0000001d, 0x00000006, 0x00000006, 0x0003001d,
146 0x0000001f, 0x0000001e, 0x0003001e, 0x00000020, 0x0000001f, 0x00040020, 0x00000021, 0x00000002, 0x00000020, 0x0004003b,
147 0x00000021, 0x00000022, 0x00000002, 0x0004002b, 0x00000014, 0x00000024, 0x00000001, 0x0004002b, 0x00000014, 0x00000029,
148 0x00000002, 0x00040020, 0x0000002c, 0x00000007, 0x00000019, 0x0003002a, 0x00000019, 0x0000002e, 0x0004002b, 0x00000014,
149 0x00000036, 0x00000006, 0x0004002b, 0x00000014, 0x0000003b, 0x00000007, 0x0004002b, 0x00000006, 0x0000003c, 0x00000002,
150 0x0004002b, 0x00000006, 0x00000048, 0x00000001, 0x00030029, 0x00000019, 0x00000050, 0x0004002b, 0x00000014, 0x00000058,
151 0x00000003, 0x0004002b, 0x00000014, 0x0000005d, 0x00000004, 0x0004002b, 0x00000014, 0x00000060, 0x00000005, 0x00050036,
152 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007,
153 0x0004003b, 0x00000007, 0x0000001b, 0x00000007, 0x0004003b, 0x00000007, 0x00000027, 0x00000007, 0x0004003b, 0x0000002c,
154 0x0000002d, 0x00000007, 0x0004003b, 0x00000007, 0x0000002f, 0x00000007, 0x0003003e, 0x00000008, 0x00000009, 0x000200f9,
155 0x0000000a, 0x000200f8, 0x0000000a, 0x000400f6, 0x0000000c, 0x0000000d, 0x00000000, 0x000200f9, 0x0000000e, 0x000200f8,
156 0x0000000e, 0x0004003d, 0x00000006, 0x0000000f, 0x00000008, 0x00050041, 0x00000016, 0x00000017, 0x00000013, 0x00000015,
157 0x0004003d, 0x00000006, 0x00000018, 0x00000017, 0x000500b0, 0x00000019, 0x0000001a, 0x0000000f, 0x00000018, 0x000400fa,
158 0x0000001a, 0x0000000b, 0x0000000c, 0x000200f8, 0x0000000b, 0x0004003d, 0x00000006, 0x00000023, 0x00000008, 0x00070041,
159 0x00000016, 0x00000025, 0x00000022, 0x00000015, 0x00000023, 0x00000024, 0x0004003d, 0x00000006, 0x00000026, 0x00000025,
160 0x0003003e, 0x0000001b, 0x00000026, 0x0004003d, 0x00000006, 0x00000028, 0x00000008, 0x00070041, 0x00000016, 0x0000002a,
161 0x00000022, 0x00000015, 0x00000028, 0x00000029, 0x0004003d, 0x00000006, 0x0000002b, 0x0000002a, 0x0003003e, 0x00000027,
162 0x0000002b, 0x0003003e, 0x0000002d, 0x0000002e, 0x0003003e, 0x0000002f, 0x00000009, 0x000200f9, 0x00000030, 0x000200f8,
163 0x00000030, 0x000400f6, 0x00000032, 0x00000033, 0x00000000, 0x000200f9, 0x00000034, 0x000200f8, 0x00000034, 0x0004003d,
164 0x00000006, 0x00000035, 0x0000002f, 0x00050041, 0x00000016, 0x00000037, 0x00000013, 0x00000036, 0x0004003d, 0x00000006,
165 0x00000038, 0x00000037, 0x000500b0, 0x00000019, 0x00000039, 0x00000035, 0x00000038, 0x000400fa, 0x00000039, 0x00000031,
166 0x00000032, 0x000200f8, 0x00000031, 0x0004003d, 0x00000006, 0x0000003a, 0x0000001b, 0x0004003d, 0x00000006, 0x0000003d,
167 0x0000002f, 0x00050084, 0x00000006, 0x0000003e, 0x0000003c, 0x0000003d, 0x00050080, 0x00000006, 0x0000003f, 0x0000003e,
168 0x00000009, 0x00060041, 0x00000016, 0x00000040, 0x00000013, 0x0000003b, 0x0000003f, 0x0004003d, 0x00000006, 0x00000041,
169 0x00000040, 0x000500aa, 0x00000019, 0x00000042, 0x0000003a, 0x00000041, 0x000300f7, 0x00000044, 0x00000000, 0x000400fa,
170 0x00000042, 0x00000043, 0x00000044, 0x000200f8, 0x00000043, 0x0004003d, 0x00000006, 0x00000045, 0x00000027, 0x0004003d,
171 0x00000006, 0x00000046, 0x0000002f, 0x00050084, 0x00000006, 0x00000047, 0x0000003c, 0x00000046, 0x00050080, 0x00000006,
172 0x00000049, 0x00000047, 0x00000048, 0x00060041, 0x00000016, 0x0000004a, 0x00000013, 0x0000003b, 0x00000049, 0x0004003d,
173 0x00000006, 0x0000004b, 0x0000004a, 0x000500aa, 0x00000019, 0x0000004c, 0x00000045, 0x0000004b, 0x000200f9, 0x00000044,
174 0x000200f8, 0x00000044, 0x000700f5, 0x00000019, 0x0000004d, 0x00000042, 0x00000031, 0x0000004c, 0x00000043, 0x000300f7,
175 0x0000004f, 0x00000000, 0x000400fa, 0x0000004d, 0x0000004e, 0x0000004f, 0x000200f8, 0x0000004e, 0x0003003e, 0x0000002d,
176 0x00000050, 0x000200f9, 0x00000032, 0x000200f8, 0x0000004f, 0x000200f9, 0x00000033, 0x000200f8, 0x00000033, 0x0004003d,
177 0x00000006, 0x00000052, 0x0000002f, 0x00050080, 0x00000006, 0x00000053, 0x00000052, 0x00000024, 0x0003003e, 0x0000002f,
178 0x00000053, 0x000200f9, 0x00000030, 0x000200f8, 0x00000032, 0x0004003d, 0x00000019, 0x00000054, 0x0000002d, 0x000400a8,
179 0x00000019, 0x00000055, 0x00000054, 0x000300f7, 0x00000057, 0x00000000, 0x000400fa, 0x00000055, 0x00000056, 0x00000057,
180 0x000200f8, 0x00000056, 0x00050041, 0x00000016, 0x00000059, 0x00000013, 0x00000058, 0x0004003d, 0x00000006, 0x0000005a,
181 0x00000059, 0x00050080, 0x00000006, 0x0000005b, 0x0000005a, 0x00000048, 0x00050041, 0x00000016, 0x0000005c, 0x00000013,
182 0x00000058, 0x0003003e, 0x0000005c, 0x0000005b, 0x0004003d, 0x00000006, 0x0000005e, 0x0000001b, 0x00050041, 0x00000016,
183 0x0000005f, 0x00000013, 0x0000005d, 0x0003003e, 0x0000005f, 0x0000005e, 0x0004003d, 0x00000006, 0x00000061, 0x00000027,
184 0x00050041, 0x00000016, 0x00000062, 0x00000013, 0x00000060, 0x0003003e, 0x00000062, 0x00000061, 0x0004003d, 0x00000006,
185 0x00000063, 0x00000008, 0x00050041, 0x00000016, 0x00000064, 0x00000013, 0x00000024, 0x0004003d, 0x00000006, 0x00000065,
186 0x00000064, 0x00070041, 0x00000016, 0x00000066, 0x00000022, 0x00000015, 0x00000063, 0x00000024, 0x0003003e, 0x00000066,
187 0x00000065, 0x0004003d, 0x00000006, 0x00000067, 0x00000008, 0x00050041, 0x00000016, 0x00000068, 0x00000013, 0x00000029,
188 0x0004003d, 0x00000006, 0x00000069, 0x00000068, 0x00070041, 0x00000016, 0x0000006a, 0x00000022, 0x00000015, 0x00000067,
189 0x00000029, 0x0003003e, 0x0000006a, 0x00000069, 0x000200f9, 0x00000057, 0x000200f8, 0x00000057, 0x000200f9, 0x0000000d,
190 0x000200f8, 0x0000000d, 0x0004003d, 0x00000006, 0x0000006b, 0x00000008, 0x00050080, 0x00000006, 0x0000006c, 0x0000006b,
191 0x00000024, 0x0003003e, 0x00000008, 0x0000006c, 0x000200f9, 0x0000000a, 0x000200f8, 0x0000000c, 0x000100fd, 0x00010038};
192
Karl Schultz7b024b42018-08-30 16:18:18 -0600193// Implementation for Descriptor Set Manager class
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600194GpuAssistedDescriptorSetManager::GpuAssistedDescriptorSetManager(GpuAssisted *dev_data) { dev_data_ = dev_data; }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700195
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600196GpuAssistedDescriptorSetManager::~GpuAssistedDescriptorSetManager() {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700197 for (auto &pool : desc_pool_map_) {
Tony-LunarG152a88b2019-03-20 15:42:24 -0600198 DispatchDestroyDescriptorPool(dev_data_->device, pool.first, NULL);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700199 }
200 desc_pool_map_.clear();
201}
202
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600203VkResult GpuAssistedDescriptorSetManager::GetDescriptorSet(VkDescriptorPool *desc_pool, VkDescriptorSet *desc_set) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700204 std::vector<VkDescriptorSet> desc_sets;
205 VkResult result = GetDescriptorSets(1, desc_pool, &desc_sets);
206 if (result == VK_SUCCESS) {
207 *desc_set = desc_sets[0];
208 }
209 return result;
210}
211
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600212VkResult GpuAssistedDescriptorSetManager::GetDescriptorSets(uint32_t count, VkDescriptorPool *pool,
213 std::vector<VkDescriptorSet> *desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600214 const uint32_t default_pool_size = kItemsPerChunk;
215 VkResult result = VK_SUCCESS;
216 VkDescriptorPool pool_to_use = VK_NULL_HANDLE;
217
218 if (0 == count) {
219 return result;
220 }
221 desc_sets->clear();
222 desc_sets->resize(count);
223
224 for (auto &pool : desc_pool_map_) {
225 if (pool.second.used + count < pool.second.size) {
226 pool_to_use = pool.first;
227 break;
228 }
229 }
230 if (VK_NULL_HANDLE == pool_to_use) {
231 uint32_t pool_count = default_pool_size;
232 if (count > default_pool_size) {
233 pool_count = count;
234 }
235 const VkDescriptorPoolSize size_counts = {
236 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
237 pool_count * kNumBindingsInSet,
238 };
239 VkDescriptorPoolCreateInfo desc_pool_info = {};
240 desc_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
241 desc_pool_info.pNext = NULL;
242 desc_pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
243 desc_pool_info.maxSets = pool_count;
244 desc_pool_info.poolSizeCount = 1;
245 desc_pool_info.pPoolSizes = &size_counts;
Tony-LunarG152a88b2019-03-20 15:42:24 -0600246 result = DispatchCreateDescriptorPool(dev_data_->device, &desc_pool_info, NULL, &pool_to_use);
Karl Schultz7b024b42018-08-30 16:18:18 -0600247 assert(result == VK_SUCCESS);
248 if (result != VK_SUCCESS) {
249 return result;
250 }
251 desc_pool_map_[pool_to_use].size = desc_pool_info.maxSets;
252 desc_pool_map_[pool_to_use].used = 0;
253 }
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600254 std::vector<VkDescriptorSetLayout> desc_layouts(count, dev_data_->gpu_validation_state->debug_desc_layout);
Karl Schultz7b024b42018-08-30 16:18:18 -0600255
256 VkDescriptorSetAllocateInfo alloc_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, NULL, pool_to_use, count,
257 desc_layouts.data()};
258
Tony-LunarG152a88b2019-03-20 15:42:24 -0600259 result = DispatchAllocateDescriptorSets(dev_data_->device, &alloc_info, desc_sets->data());
Karl Schultz7b024b42018-08-30 16:18:18 -0600260 assert(result == VK_SUCCESS);
261 if (result != VK_SUCCESS) {
262 return result;
263 }
264 *pool = pool_to_use;
265 desc_pool_map_[pool_to_use].used += count;
266 return result;
267}
268
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600269void GpuAssistedDescriptorSetManager::PutBackDescriptorSet(VkDescriptorPool desc_pool, VkDescriptorSet desc_set) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600270 auto iter = desc_pool_map_.find(desc_pool);
271 if (iter != desc_pool_map_.end()) {
Tony-LunarG152a88b2019-03-20 15:42:24 -0600272 VkResult result = DispatchFreeDescriptorSets(dev_data_->device, desc_pool, 1, &desc_set);
Karl Schultz7b024b42018-08-30 16:18:18 -0600273 assert(result == VK_SUCCESS);
274 if (result != VK_SUCCESS) {
275 return;
276 }
277 desc_pool_map_[desc_pool].used--;
278 if (0 == desc_pool_map_[desc_pool].used) {
Tony-LunarG152a88b2019-03-20 15:42:24 -0600279 DispatchDestroyDescriptorPool(dev_data_->device, desc_pool, NULL);
Karl Schultz7b024b42018-08-30 16:18:18 -0600280 desc_pool_map_.erase(desc_pool);
281 }
282 }
283 return;
284}
285
Tony-LunarG0e564722019-03-19 16:09:14 -0600286// Trampolines to make VMA call Dispatch for Vulkan calls
287static VKAPI_ATTR void VKAPI_CALL gpuVkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
288 VkPhysicalDeviceProperties *pProperties) {
289 DispatchGetPhysicalDeviceProperties(physicalDevice, pProperties);
290}
291static VKAPI_ATTR void VKAPI_CALL gpuVkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
292 VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
293 DispatchGetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
294}
295static VKAPI_ATTR VkResult VKAPI_CALL gpuVkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
296 const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
297 return DispatchAllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
298}
299static VKAPI_ATTR void VKAPI_CALL gpuVkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks *pAllocator) {
300 DispatchFreeMemory(device, memory, pAllocator);
301}
302static VKAPI_ATTR VkResult VKAPI_CALL gpuVkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size,
303 VkMemoryMapFlags flags, void **ppData) {
304 return DispatchMapMemory(device, memory, offset, size, flags, ppData);
305}
306static VKAPI_ATTR void VKAPI_CALL gpuVkUnmapMemory(VkDevice device, VkDeviceMemory memory) { DispatchUnmapMemory(device, memory); }
307static VKAPI_ATTR VkResult VKAPI_CALL gpuVkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
308 const VkMappedMemoryRange *pMemoryRanges) {
309 return DispatchFlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
310}
311static VKAPI_ATTR VkResult VKAPI_CALL gpuVkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
312 const VkMappedMemoryRange *pMemoryRanges) {
313 return DispatchInvalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
314}
315static VKAPI_ATTR VkResult VKAPI_CALL gpuVkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory,
316 VkDeviceSize memoryOffset) {
317 return DispatchBindBufferMemory(device, buffer, memory, memoryOffset);
318}
319static VKAPI_ATTR VkResult VKAPI_CALL gpuVkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory,
320 VkDeviceSize memoryOffset) {
321 return DispatchBindImageMemory(device, image, memory, memoryOffset);
322}
323static VKAPI_ATTR void VKAPI_CALL gpuVkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer,
324 VkMemoryRequirements *pMemoryRequirements) {
325 DispatchGetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
326}
327static VKAPI_ATTR void VKAPI_CALL gpuVkGetImageMemoryRequirements(VkDevice device, VkImage image,
328 VkMemoryRequirements *pMemoryRequirements) {
329 DispatchGetImageMemoryRequirements(device, image, pMemoryRequirements);
330}
331static VKAPI_ATTR VkResult VKAPI_CALL gpuVkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
332 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
333 return DispatchCreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
334}
335static VKAPI_ATTR void VKAPI_CALL gpuVkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
336 return DispatchDestroyBuffer(device, buffer, pAllocator);
337}
338static VKAPI_ATTR VkResult VKAPI_CALL gpuVkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
339 const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
340 return DispatchCreateImage(device, pCreateInfo, pAllocator, pImage);
341}
342static VKAPI_ATTR void VKAPI_CALL gpuVkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
343 DispatchDestroyImage(device, image, pAllocator);
344}
345static VKAPI_ATTR void VKAPI_CALL gpuVkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
346 uint32_t regionCount, const VkBufferCopy *pRegions) {
347 DispatchCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
348}
349
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600350VkResult GpuAssisted::InitializeVma(VkPhysicalDevice physical_device, VkDevice device, VmaAllocator *pAllocator) {
Tony-LunarG0e564722019-03-19 16:09:14 -0600351 VmaVulkanFunctions functions;
352 VmaAllocatorCreateInfo allocatorInfo = {};
353 allocatorInfo.device = device;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600354 allocatorInfo.physicalDevice = physical_device;
Tony-LunarG0e564722019-03-19 16:09:14 -0600355
356 functions.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)gpuVkGetPhysicalDeviceProperties;
357 functions.vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)gpuVkGetPhysicalDeviceMemoryProperties;
358 functions.vkAllocateMemory = (PFN_vkAllocateMemory)gpuVkAllocateMemory;
359 functions.vkFreeMemory = (PFN_vkFreeMemory)gpuVkFreeMemory;
360 functions.vkMapMemory = (PFN_vkMapMemory)gpuVkMapMemory;
361 functions.vkUnmapMemory = (PFN_vkUnmapMemory)gpuVkUnmapMemory;
362 functions.vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)gpuVkFlushMappedMemoryRanges;
363 functions.vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)gpuVkInvalidateMappedMemoryRanges;
364 functions.vkBindBufferMemory = (PFN_vkBindBufferMemory)gpuVkBindBufferMemory;
365 functions.vkBindImageMemory = (PFN_vkBindImageMemory)gpuVkBindImageMemory;
366 functions.vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)gpuVkGetBufferMemoryRequirements;
367 functions.vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)gpuVkGetImageMemoryRequirements;
368 functions.vkCreateBuffer = (PFN_vkCreateBuffer)gpuVkCreateBuffer;
369 functions.vkDestroyBuffer = (PFN_vkDestroyBuffer)gpuVkDestroyBuffer;
370 functions.vkCreateImage = (PFN_vkCreateImage)gpuVkCreateImage;
371 functions.vkDestroyImage = (PFN_vkDestroyImage)gpuVkDestroyImage;
372 functions.vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)gpuVkCmdCopyBuffer;
373 allocatorInfo.pVulkanFunctions = &functions;
374
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600375 return vmaCreateAllocator(&allocatorInfo, pAllocator);
Tony-LunarG0e564722019-03-19 16:09:14 -0600376}
377
Karl Schultz7b024b42018-08-30 16:18:18 -0600378// Convenience function for reporting problems with setting up GPU Validation.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600379void GpuAssisted::ReportSetupProblem(VkDebugReportObjectTypeEXT object_type, uint64_t object_handle,
380 const char *const specific_message) {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700381 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle, "UNASSIGNED-GPU-Assisted Validation Error. ",
382 "Detail: (%s)", specific_message);
Karl Schultz7b024b42018-08-30 16:18:18 -0600383}
384
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600385void GpuAssisted::PreCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
386 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer, void *cb_state_data) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700387 // Ray tracing acceleration structure instance buffers also need the storage buffer usage as
388 // acceleration structure build validation will find and replace invalid acceleration structure
389 // handles inside of a compute shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600390 create_buffer_api_state *cb_state = reinterpret_cast<create_buffer_api_state *>(cb_state_data);
391 if (cb_state && cb_state->modified_create_info.usage & VK_BUFFER_USAGE_RAY_TRACING_BIT_NV) {
392 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
Jason Macnak83cfd582019-07-31 10:14:24 -0700393 }
394}
395
Karl Schultz7b024b42018-08-30 16:18:18 -0600396// Turn on necessary device features.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600397void GpuAssisted::PreCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info,
398 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
399 safe_VkDeviceCreateInfo *modified_create_info) {
400 VkPhysicalDeviceFeatures supported_features;
401 DispatchGetPhysicalDeviceFeatures(gpu, &supported_features);
402 if (supported_features.fragmentStoresAndAtomics || supported_features.vertexPipelineStoresAndAtomics ||
403 supported_features.shaderInt64) {
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600404 VkPhysicalDeviceFeatures *features = nullptr;
Petr Kraus08d51062019-08-21 00:14:16 +0200405 if (modified_create_info->pEnabledFeatures) {
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600406 // If pEnabledFeatures, VkPhysicalDeviceFeatures2 in pNext chain is not allowed
Petr Kraus08d51062019-08-21 00:14:16 +0200407 features = const_cast<VkPhysicalDeviceFeatures *>(modified_create_info->pEnabledFeatures);
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600408 } else {
409 VkPhysicalDeviceFeatures2 *features2 = nullptr;
Petr Kraus08d51062019-08-21 00:14:16 +0200410 features2 =
411 const_cast<VkPhysicalDeviceFeatures2 *>(lvl_find_in_chain<VkPhysicalDeviceFeatures2>(modified_create_info->pNext));
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600412 if (features2) features = &features2->features;
Tony-LunarG48b478a2019-01-15 16:35:22 -0700413 }
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600414 if (features) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600415 features->fragmentStoresAndAtomics = supported_features.fragmentStoresAndAtomics;
416 features->vertexPipelineStoresAndAtomics = supported_features.vertexPipelineStoresAndAtomics;
417 features->shaderInt64 = supported_features.shaderInt64;
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600418 } else {
419 VkPhysicalDeviceFeatures new_features = {};
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600420 new_features.fragmentStoresAndAtomics = supported_features.fragmentStoresAndAtomics;
421 new_features.vertexPipelineStoresAndAtomics = supported_features.vertexPipelineStoresAndAtomics;
422 new_features.shaderInt64 = supported_features.shaderInt64;
Petr Krausbd5b7b22019-08-21 00:12:33 +0200423 delete modified_create_info->pEnabledFeatures;
Petr Kraus08d51062019-08-21 00:14:16 +0200424 modified_create_info->pEnabledFeatures = new VkPhysicalDeviceFeatures(new_features);
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600425 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600426 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600427}
Karl Schultz7b024b42018-08-30 16:18:18 -0600428// Perform initializations that can be done at Create Device time.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600429void GpuAssisted::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
430 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result) {
431 // The state tracker sets up the device state
432 StateTracker::PostCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski5dc3dcd2019-04-23 14:26:28 -0600433
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600434 ValidationObject *device_object = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
435 ValidationObject *validation_data = GetValidationObject(device_object->object_dispatch, this->container_type);
436 GpuAssisted *device_gpu_assisted = static_cast<GpuAssisted *>(validation_data);
437 device_gpu_assisted->gpu_validation_state = std::unique_ptr<GpuAssistedValidationState>(new GpuAssistedValidationState);
Tony-LunarG65f9c492019-01-17 14:24:42 -0700438
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600439 if (device_gpu_assisted->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600440 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz7b024b42018-08-30 16:18:18 -0600441 "GPU-Assisted validation requires Vulkan 1.1 or later. GPU-Assisted Validation disabled.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600442 device_gpu_assisted->gpu_validation_state->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600443 return;
444 }
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600445
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600446 if (!device_gpu_assisted->enabled_features.core.fragmentStoresAndAtomics ||
447 !device_gpu_assisted->enabled_features.core.vertexPipelineStoresAndAtomics) {
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600448 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
449 "GPU-Assisted validation requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
450 "GPU-Assisted Validation disabled.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600451 device_gpu_assisted->gpu_validation_state->aborted = true;
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600452 return;
453 }
454
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600455 if (device_extensions.vk_ext_buffer_device_address && !device_gpu_assisted->enabled_features.core.shaderInt64) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600456 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
457 "UNASSIGNED-GPU-Assisted Validation Warning",
458 "shaderInt64 feature is not available. No buffer device address checking will be attempted");
459 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600460 device_gpu_assisted->gpu_validation_state->shaderInt64 = device_gpu_assisted->enabled_features.core.shaderInt64;
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600461
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600462 // If api version 1.1 or later, SetDeviceLoaderData will be in the loader
463 auto chain_info = get_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK);
464 assert(chain_info->u.pfnSetDeviceLoaderData);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600465 device_gpu_assisted->gpu_validation_state->vkSetDeviceLoaderData = chain_info->u.pfnSetDeviceLoaderData;
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600466
Karl Schultz7b024b42018-08-30 16:18:18 -0600467 // Some devices have extremely high limits here, so set a reasonable max because we have to pad
468 // the pipeline layout with dummy descriptor set layouts.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600469 device_gpu_assisted->gpu_validation_state->adjusted_max_desc_sets =
470 device_gpu_assisted->phys_dev_props.limits.maxBoundDescriptorSets;
471 device_gpu_assisted->gpu_validation_state->adjusted_max_desc_sets =
472 std::min(33U, device_gpu_assisted->gpu_validation_state->adjusted_max_desc_sets);
Karl Schultz7b024b42018-08-30 16:18:18 -0600473
474 // We can't do anything if there is only one.
475 // Device probably not a legit Vulkan device, since there should be at least 4. Protect ourselves.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600476 if (device_gpu_assisted->gpu_validation_state->adjusted_max_desc_sets == 1) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600477 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz7b024b42018-08-30 16:18:18 -0600478 "Device can bind only a single descriptor set. GPU-Assisted Validation disabled.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600479 device_gpu_assisted->gpu_validation_state->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600480 return;
481 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600482 device_gpu_assisted->gpu_validation_state->desc_set_bind_index =
483 device_gpu_assisted->gpu_validation_state->adjusted_max_desc_sets - 1;
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600484 log_msg(report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
485 "UNASSIGNED-GPU-Assisted Validation. ", "Shaders using descriptor set at index %d. ",
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600486 device_gpu_assisted->gpu_validation_state->desc_set_bind_index);
Karl Schultz7b024b42018-08-30 16:18:18 -0600487
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600488 device_gpu_assisted->gpu_validation_state->output_buffer_size = sizeof(uint32_t) * (spvtools::kInst2MaxOutCnt + 1);
489 VkResult result1 = InitializeVma(physicalDevice, *pDevice, &device_gpu_assisted->gpu_validation_state->vmaAllocator);
490 assert(result1 == VK_SUCCESS);
491 std::unique_ptr<GpuAssistedDescriptorSetManager> desc_set_manager(new GpuAssistedDescriptorSetManager(device_gpu_assisted));
Karl Schultz7b024b42018-08-30 16:18:18 -0600492
493 // The descriptor indexing checks require only the first "output" binding.
494 const VkDescriptorSetLayoutBinding debug_desc_layout_bindings[kNumBindingsInSet] = {
495 {
496 0, // output
497 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
498 1,
Jason Macnak67407e72019-07-11 11:05:09 -0700499 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT | kShaderStageAllRayTracing,
Karl Schultz7b024b42018-08-30 16:18:18 -0600500 NULL,
501 },
Tony-LunarG1b2e0c32019-02-07 17:13:27 -0700502 {
503 1, // input
504 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
505 1,
Jason Macnak67407e72019-07-11 11:05:09 -0700506 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT | kShaderStageAllRayTracing,
Tony-LunarG1b2e0c32019-02-07 17:13:27 -0700507 NULL,
508 },
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600509 {
510 2, // input
511 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
512 1,
513 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT | kShaderStageAllRayTracing,
514 NULL,
515 },
Karl Schultz7b024b42018-08-30 16:18:18 -0600516 };
Karl Schultz7b024b42018-08-30 16:18:18 -0600517 const VkDescriptorSetLayoutCreateInfo debug_desc_layout_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, 0,
518 kNumBindingsInSet, debug_desc_layout_bindings};
519
520 const VkDescriptorSetLayoutCreateInfo dummy_desc_layout_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, 0, 0,
521 NULL};
522
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600523 result1 = DispatchCreateDescriptorSetLayout(*pDevice, &debug_desc_layout_info, NULL,
524 &device_gpu_assisted->gpu_validation_state->debug_desc_layout);
Karl Schultz7b024b42018-08-30 16:18:18 -0600525
526 // This is a layout used to "pad" a pipeline layout to fill in any gaps to the selected bind index.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600527 VkResult result2 = DispatchCreateDescriptorSetLayout(*pDevice, &dummy_desc_layout_info, NULL,
528 &device_gpu_assisted->gpu_validation_state->dummy_desc_layout);
529 assert((result1 == VK_SUCCESS) && (result2 == VK_SUCCESS));
530 if ((result1 != VK_SUCCESS) || (result2 != VK_SUCCESS)) {
531 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(*pDevice),
Karl Schultz7b024b42018-08-30 16:18:18 -0600532 "Unable to create descriptor set layout. GPU-Assisted Validation disabled.");
533 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600534 DispatchDestroyDescriptorSetLayout(*pDevice, device_gpu_assisted->gpu_validation_state->debug_desc_layout, NULL);
Karl Schultz7b024b42018-08-30 16:18:18 -0600535 }
536 if (result2 == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600537 DispatchDestroyDescriptorSetLayout(*pDevice, device_gpu_assisted->gpu_validation_state->dummy_desc_layout, NULL);
Karl Schultz7b024b42018-08-30 16:18:18 -0600538 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600539 device_gpu_assisted->gpu_validation_state->debug_desc_layout = VK_NULL_HANDLE;
540 device_gpu_assisted->gpu_validation_state->dummy_desc_layout = VK_NULL_HANDLE;
541 device_gpu_assisted->gpu_validation_state->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600542 return;
543 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600544 device_gpu_assisted->gpu_validation_state->desc_set_manager = std::move(desc_set_manager);
Jason Macnak83cfd582019-07-31 10:14:24 -0700545
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600546 // Register callback to be called at any ResetCommandBuffer time
547 device_gpu_assisted->SetCommandBufferResetCallback(
548 [device_gpu_assisted](VkCommandBuffer command_buffer) -> void { device_gpu_assisted->ResetCommandBuffer(command_buffer); });
549
550 CreateAccelerationStructureBuildValidationState(device_gpu_assisted);
Karl Schultz7b024b42018-08-30 16:18:18 -0600551}
552
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600553void GpuAssisted::PostCallRecordGetBufferDeviceAddressEXT(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
554 VkDeviceAddress address) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600555 BUFFER_STATE *buffer_state = GetBufferState(pInfo->buffer);
556 // Validate against the size requested when the buffer was created
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600557 if (buffer_state) {
558 gpu_validation_state->buffer_map[address] = buffer_state->createInfo.size;
559 buffer_state->deviceAddress = address;
560 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600561}
562
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600563void GpuAssisted::PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600564 BUFFER_STATE *buffer_state = GetBufferState(buffer);
565 if (buffer_state) gpu_validation_state->buffer_map.erase(buffer_state->deviceAddress);
566}
Karl Schultz7b024b42018-08-30 16:18:18 -0600567// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600568void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Jason Macnak8eae5722019-07-17 15:17:45 -0700569 for (auto &queue_barrier_command_info_kv : gpu_validation_state->queue_barrier_command_infos) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600570 GpuAssistedQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_kv.second;
Jason Macnak8eae5722019-07-17 15:17:45 -0700571
572 DispatchFreeCommandBuffers(device, queue_barrier_command_info.barrier_command_pool, 1,
573 &queue_barrier_command_info.barrier_command_buffer);
574 queue_barrier_command_info.barrier_command_buffer = VK_NULL_HANDLE;
575
576 DispatchDestroyCommandPool(device, queue_barrier_command_info.barrier_command_pool, NULL);
577 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
Karl Schultz58674242019-01-22 15:35:02 -0700578 }
Jason Macnak8eae5722019-07-17 15:17:45 -0700579 gpu_validation_state->queue_barrier_command_infos.clear();
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600580 if (gpu_validation_state->debug_desc_layout) {
Tony-LunarG152a88b2019-03-20 15:42:24 -0600581 DispatchDestroyDescriptorSetLayout(device, gpu_validation_state->debug_desc_layout, NULL);
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600582 gpu_validation_state->debug_desc_layout = VK_NULL_HANDLE;
Karl Schultz7b024b42018-08-30 16:18:18 -0600583 }
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600584 if (gpu_validation_state->dummy_desc_layout) {
Tony-LunarG152a88b2019-03-20 15:42:24 -0600585 DispatchDestroyDescriptorSetLayout(device, gpu_validation_state->dummy_desc_layout, NULL);
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600586 gpu_validation_state->dummy_desc_layout = VK_NULL_HANDLE;
Karl Schultz7b024b42018-08-30 16:18:18 -0600587 }
Tony-LunarG29f48a72019-04-16 11:53:37 -0600588 gpu_validation_state->desc_set_manager.reset();
Jason Macnak83cfd582019-07-31 10:14:24 -0700589
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600590 DestroyAccelerationStructureBuildValidationState();
Jason Macnak83cfd582019-07-31 10:14:24 -0700591
Tony-LunarG29f48a72019-04-16 11:53:37 -0600592 if (gpu_validation_state->vmaAllocator) {
593 vmaDestroyAllocator(gpu_validation_state->vmaAllocator);
594 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600595}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600596void GpuAssisted::CreateAccelerationStructureBuildValidationState(GpuAssisted *device_gpuav) {
597 if (device_gpuav->gpu_validation_state->aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700598 return;
599 }
600
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600601 auto &as_validation_state = device_gpuav->gpu_validation_state->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700602 if (as_validation_state.initialized) {
603 return;
604 }
605
606 if (!device_extensions.vk_nv_ray_tracing) {
607 return;
608 }
609
610 // Outline:
611 // - Create valid bottom level acceleration structure which acts as replacement
612 // - Create and load vertex buffer
613 // - Create and load index buffer
614 // - Create, allocate memory for, and bind memory for acceleration structure
615 // - Query acceleration structure handle
616 // - Create command pool and command buffer
617 // - Record build acceleration structure command
618 // - Submit command buffer and wait for completion
619 // - Cleanup
620 // - Create compute pipeline for validating instance buffers
621 // - Create descriptor set layout
622 // - Create pipeline layout
623 // - Create pipeline
624 // - Cleanup
625
626 VkResult result = VK_SUCCESS;
627
628 VkBuffer vbo = VK_NULL_HANDLE;
629 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
630 if (result == VK_SUCCESS) {
631 VkBufferCreateInfo vbo_ci = {};
632 vbo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
633 vbo_ci.size = sizeof(float) * 9;
634 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
635
636 VmaAllocationCreateInfo vbo_ai = {};
637 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
638 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
639
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600640 result =
641 vmaCreateBuffer(device_gpuav->gpu_validation_state->vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700642 if (result != VK_SUCCESS) {
643 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
644 "Failed to create vertex buffer for acceleration structure build validation.");
645 }
646 }
647
648 if (result == VK_SUCCESS) {
649 uint8_t *mapped_vbo_buffer = nullptr;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600650 result = vmaMapMemory(device_gpuav->gpu_validation_state->vmaAllocator, vbo_allocation, (void **)&mapped_vbo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700651 if (result != VK_SUCCESS) {
652 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
653 "Failed to map vertex buffer for acceleration structure build validation.");
654 } else {
655 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
656 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600657 vmaUnmapMemory(device_gpuav->gpu_validation_state->vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700658 }
659 }
660
661 VkBuffer ibo = VK_NULL_HANDLE;
662 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
663 if (result == VK_SUCCESS) {
664 VkBufferCreateInfo ibo_ci = {};
665 ibo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
666 ibo_ci.size = sizeof(uint32_t) * 3;
667 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
668
669 VmaAllocationCreateInfo ibo_ai = {};
670 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
671 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
672
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600673 result =
674 vmaCreateBuffer(device_gpuav->gpu_validation_state->vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700675 if (result != VK_SUCCESS) {
676 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
677 "Failed to create index buffer for acceleration structure build validation.");
678 }
679 }
680
681 if (result == VK_SUCCESS) {
682 uint8_t *mapped_ibo_buffer = nullptr;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600683 result = vmaMapMemory(device_gpuav->gpu_validation_state->vmaAllocator, ibo_allocation, (void **)&mapped_ibo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700684 if (result != VK_SUCCESS) {
685 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
686 "Failed to map index buffer for acceleration structure build validation.");
687 } else {
688 const std::vector<uint32_t> indicies = {0, 1, 2};
689 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600690 vmaUnmapMemory(device_gpuav->gpu_validation_state->vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700691 }
692 }
693
694 VkGeometryNV geometry = {};
695 geometry.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
696 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
697 geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
698 geometry.geometry.triangles.vertexData = vbo;
699 geometry.geometry.triangles.vertexOffset = 0;
700 geometry.geometry.triangles.vertexCount = 3;
701 geometry.geometry.triangles.vertexStride = 12;
702 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
703 geometry.geometry.triangles.indexData = ibo;
704 geometry.geometry.triangles.indexOffset = 0;
705 geometry.geometry.triangles.indexCount = 3;
706 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
707 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
708 geometry.geometry.triangles.transformOffset = 0;
709 geometry.geometry.aabbs = {};
710 geometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
711
712 VkAccelerationStructureCreateInfoNV as_ci = {};
713 as_ci.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
714 as_ci.info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
715 as_ci.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV;
716 as_ci.info.instanceCount = 0;
717 as_ci.info.geometryCount = 1;
718 as_ci.info.pGeometries = &geometry;
719 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600720 result = DispatchCreateAccelerationStructureNV(device_gpuav->device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700721 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600722 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700723 "Failed to create acceleration structure for acceleration structure build validation.");
724 }
725 }
726
727 VkMemoryRequirements2 as_mem_requirements = {};
728 if (result == VK_SUCCESS) {
729 VkAccelerationStructureMemoryRequirementsInfoNV as_mem_requirements_info = {};
730 as_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
731 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
732 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
733
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600734 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700735 }
736
737 VmaAllocationInfo as_memory_ai = {};
738 if (result == VK_SUCCESS) {
739 VmaAllocationCreateInfo as_memory_aci = {};
740 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
741
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600742 result = vmaAllocateMemory(device_gpuav->gpu_validation_state->vmaAllocator, &as_mem_requirements.memoryRequirements,
743 &as_memory_aci, &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700744 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600745 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700746 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
747 }
748 }
749
750 if (result == VK_SUCCESS) {
751 VkBindAccelerationStructureMemoryInfoNV as_bind_info = {};
752 as_bind_info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
753 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
754 as_bind_info.memory = as_memory_ai.deviceMemory;
755 as_bind_info.memoryOffset = as_memory_ai.offset;
756
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600757 result = DispatchBindAccelerationStructureMemoryNV(device_gpuav->device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700758 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600759 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700760 "Failed to bind acceleration structure memory for acceleration structure build validation.");
761 }
762 }
763
764 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600765 result = DispatchGetAccelerationStructureHandleNV(device_gpuav->device, as_validation_state.replacement_as,
766 sizeof(uint64_t), &as_validation_state.replacement_as_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700767 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600768 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700769 "Failed to get acceleration structure handle for acceleration structure build validation.");
770 }
771 }
772
773 VkMemoryRequirements2 scratch_mem_requirements = {};
774 if (result == VK_SUCCESS) {
775 VkAccelerationStructureMemoryRequirementsInfoNV scratch_mem_requirements_info = {};
776 scratch_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
777 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
778 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
779
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600780 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &scratch_mem_requirements_info,
781 &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700782 }
783
784 VkBuffer scratch = VK_NULL_HANDLE;
785 if (result == VK_SUCCESS) {
786 VkBufferCreateInfo scratch_ci = {};
787 scratch_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
788 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
789 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
790
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600791 result = DispatchCreateBuffer(device_gpuav->device, &scratch_ci, nullptr, &scratch);
Jason Macnak83cfd582019-07-31 10:14:24 -0700792 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600793 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700794 "Failed to create scratch buffer for acceleration structure build validation.");
795 }
796 }
797
798 VmaAllocation scratch_allocation = VK_NULL_HANDLE;
799 VmaAllocationInfo scratch_allocation_info = {};
800 if (result == VK_SUCCESS) {
801 VmaAllocationCreateInfo scratch_aci = {};
802 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
803
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600804 result = vmaAllocateMemory(device_gpuav->gpu_validation_state->vmaAllocator, &scratch_mem_requirements.memoryRequirements,
805 &scratch_aci, &scratch_allocation, &scratch_allocation_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700806 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600807 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700808 "Failed to alloc scratch memory for acceleration structure build validation.");
809 }
810 }
811
812 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600813 result = DispatchBindBufferMemory(device_gpuav->device, scratch, scratch_allocation_info.deviceMemory,
814 scratch_allocation_info.offset);
Jason Macnak83cfd582019-07-31 10:14:24 -0700815 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600816 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700817 "Failed to bind scratch memory for acceleration structure build validation.");
818 }
819 }
820
821 VkCommandPool command_pool = VK_NULL_HANDLE;
822 if (result == VK_SUCCESS) {
823 VkCommandPoolCreateInfo command_pool_ci = {};
824 command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
825 command_pool_ci.queueFamilyIndex = 0;
826
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600827 result = DispatchCreateCommandPool(device_gpuav->device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700828 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600829 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700830 "Failed to create command pool for acceleration structure build validation.");
831 }
832 }
833
834 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
835
836 if (result == VK_SUCCESS) {
837 VkCommandBufferAllocateInfo command_buffer_ai = {};
838 command_buffer_ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
839 command_buffer_ai.commandPool = command_pool;
840 command_buffer_ai.commandBufferCount = 1;
841 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
842
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600843 result = DispatchAllocateCommandBuffers(device_gpuav->device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700844 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600845 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700846 "Failed to create command buffer for acceleration structure build validation.");
847 }
848
849 // Hook up command buffer dispatch
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600850 device_gpuav->gpu_validation_state->vkSetDeviceLoaderData(device_gpuav->device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700851 }
852
853 if (result == VK_SUCCESS) {
854 VkCommandBufferBeginInfo command_buffer_bi = {};
855 command_buffer_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
856
857 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
858 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600859 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700860 "Failed to begin command buffer for acceleration structure build validation.");
861 }
862 }
863
864 if (result == VK_SUCCESS) {
865 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
866 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
867 DispatchEndCommandBuffer(command_buffer);
868 }
869
870 VkQueue queue = VK_NULL_HANDLE;
871 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600872 DispatchGetDeviceQueue(device_gpuav->device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700873
874 // Hook up queue dispatch
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600875 device_gpuav->gpu_validation_state->vkSetDeviceLoaderData(device_gpuav->device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700876
877 VkSubmitInfo submit_info = {};
878 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
879 submit_info.commandBufferCount = 1;
880 submit_info.pCommandBuffers = &command_buffer;
881 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
882 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600883 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700884 "Failed to submit command buffer for acceleration structure build validation.");
885 }
886 }
887
888 if (result == VK_SUCCESS) {
889 result = DispatchQueueWaitIdle(queue);
890 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600891 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700892 "Failed to wait for queue idle for acceleration structure build validation.");
893 }
894 }
895
896 if (vbo != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600897 vmaDestroyBuffer(device_gpuav->gpu_validation_state->vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700898 }
899 if (ibo != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600900 vmaDestroyBuffer(device_gpuav->gpu_validation_state->vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700901 }
902 if (scratch != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600903 DispatchDestroyBuffer(device_gpuav->device, scratch, nullptr);
904 vmaFreeMemory(device_gpuav->gpu_validation_state->vmaAllocator, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700905 }
906 if (command_pool != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600907 DispatchDestroyCommandPool(device_gpuav->device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700908 }
909
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600910 if (device_gpuav->gpu_validation_state->debug_desc_layout == VK_NULL_HANDLE) {
911 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700912 "Failed to find descriptor set layout for acceleration structure build validation.");
913 result = VK_INCOMPLETE;
914 }
915
916 if (result == VK_SUCCESS) {
917 VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
918 pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
919 pipeline_layout_ci.setLayoutCount = 1;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600920 pipeline_layout_ci.pSetLayouts = &device_gpuav->gpu_validation_state->debug_desc_layout;
921 result = DispatchCreatePipelineLayout(device_gpuav->device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700922 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600923 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700924 "Failed to create pipeline layout for acceleration structure build validation.");
925 }
926 }
927
928 VkShaderModule shader_module = VK_NULL_HANDLE;
929 if (result == VK_SUCCESS) {
930 VkShaderModuleCreateInfo shader_module_ci = {};
931 shader_module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
932 shader_module_ci.codeSize = sizeof(kComputeShaderSpirv);
933 shader_module_ci.pCode = (uint32_t *)kComputeShaderSpirv;
934
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600935 result = DispatchCreateShaderModule(device_gpuav->device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700936 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600937 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700938 "Failed to create compute shader module for acceleration structure build validation.");
939 }
940 }
941
942 if (result == VK_SUCCESS) {
943 VkPipelineShaderStageCreateInfo pipeline_stage_ci = {};
944 pipeline_stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
945 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
946 pipeline_stage_ci.module = shader_module;
947 pipeline_stage_ci.pName = "main";
948
949 VkComputePipelineCreateInfo pipeline_ci = {};
950 pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
951 pipeline_ci.stage = pipeline_stage_ci;
952 pipeline_ci.layout = as_validation_state.pipeline_layout;
953
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600954 result = DispatchCreateComputePipelines(device_gpuav->device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr,
955 &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700956 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600957 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700958 "Failed to create compute pipeline for acceleration structure build validation.");
959 }
960 }
961
962 if (shader_module != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600963 DispatchDestroyShaderModule(device_gpuav->device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700964 }
965
966 if (result == VK_SUCCESS) {
967 as_validation_state.initialized = true;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600968 log_msg(report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
969 HandleToUint64(device_gpuav->device), "UNASSIGNED-GPU-Assisted Validation.",
970 "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700971 } else {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600972 device_gpuav->gpu_validation_state->aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700973 }
974}
975
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600976void GpuAssisted::DestroyAccelerationStructureBuildValidationState() {
977 auto &as_validation_state = gpu_validation_state->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700978 if (as_validation_state.pipeline != VK_NULL_HANDLE) {
979 DispatchDestroyPipeline(device, as_validation_state.pipeline, nullptr);
980 }
981 if (as_validation_state.pipeline_layout != VK_NULL_HANDLE) {
982 DispatchDestroyPipelineLayout(device, as_validation_state.pipeline_layout, nullptr);
983 }
984 if (as_validation_state.replacement_as != VK_NULL_HANDLE) {
985 DispatchDestroyAccelerationStructureNV(device, as_validation_state.replacement_as, nullptr);
986 }
987 if (as_validation_state.replacement_as_allocation != VK_NULL_HANDLE) {
988 vmaFreeMemory(gpu_validation_state->vmaAllocator, as_validation_state.replacement_as_allocation);
989 }
990}
991
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600992struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700993 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
994 VkPipeline pipeline = VK_NULL_HANDLE;
995 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
996 std::vector<VkDescriptorSet> descriptor_sets;
997 std::vector<std::vector<uint32_t>> dynamic_offsets;
998 uint32_t push_descriptor_set_index = 0;
999 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
1000 std::vector<uint8_t> push_constants_data;
1001 PushConstantRangesId push_constants_ranges;
1002
1003 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
1004 pipeline_bind_point = bind_point;
1005
1006 LAST_BOUND_STATE &last_bound = cb_state->lastBound[bind_point];
1007 if (last_bound.pipeline_state) {
1008 pipeline = last_bound.pipeline_state->pipeline;
1009 pipeline_layout = last_bound.pipeline_layout;
1010 descriptor_sets.reserve(last_bound.per_set.size());
1011 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
1012 const auto *bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
1013
1014 descriptor_sets.push_back(bound_descriptor_set->GetSet());
1015 if (bound_descriptor_set->IsPushDescriptor()) {
1016 push_descriptor_set_index = static_cast<uint32_t>(i);
1017 }
1018 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
1019 }
1020
1021 if (last_bound.push_descriptor_set) {
1022 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
1023 }
1024 if (last_bound.pipeline_state->pipeline_layout.push_constant_ranges == cb_state->push_constant_data_ranges) {
1025 push_constants_data = cb_state->push_constant_data;
1026 push_constants_ranges = last_bound.pipeline_state->pipeline_layout.push_constant_ranges;
1027 }
1028 }
1029 }
1030
1031 void Restore(VkCommandBuffer command_buffer) const {
1032 if (pipeline != VK_NULL_HANDLE) {
1033 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
1034 if (!descriptor_sets.empty()) {
1035 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
1036 VkDescriptorSet descriptor_set = descriptor_sets[i];
1037 if (descriptor_set != VK_NULL_HANDLE) {
1038 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
1039 static_cast<uint32_t>(i), 1, &descriptor_set,
1040 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
1041 }
1042 }
1043 }
1044 if (!push_descriptor_set_writes.empty()) {
1045 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
1046 static_cast<uint32_t>(push_descriptor_set_writes.size()),
1047 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
1048 }
1049 for (const auto &push_constant_range : *push_constants_ranges) {
1050 if (push_constant_range.size == 0) continue;
1051 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
1052 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
1053 }
1054 }
1055 }
1056};
1057
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001058void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
1059 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
1060 VkDeviceSize instanceOffset, VkBool32 update,
1061 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
1062 VkBuffer scratch, VkDeviceSize scratchOffset) {
Jason Macnak83cfd582019-07-31 10:14:24 -07001063 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
1064 return;
1065 }
1066
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001067 auto &as_validation_state = gpu_validation_state->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001068 if (!as_validation_state.initialized) {
1069 return;
1070 }
1071
1072 // Empty acceleration structure is valid according to the spec.
1073 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
1074 return;
1075 }
1076
1077 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1078 assert(cb_state != nullptr);
1079
1080 std::vector<uint64_t> current_valid_handles;
1081 for (const auto &as_state_kv : accelerationStructureMap) {
1082 const ACCELERATION_STRUCTURE_STATE &as_state = *as_state_kv.second;
1083 if (as_state.built && as_state.create_info.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
1084 current_valid_handles.push_back(as_state.opaque_handle);
1085 }
1086 }
1087
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001088 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -07001089 as_validation_buffer_info.acceleration_structure = dst;
1090
1091 const VkDeviceSize validation_buffer_size =
1092 // One uint for number of instances to validate
1093 4 +
1094 // Two uint for the replacement acceleration structure handle
1095 8 +
1096 // One uint for number of invalid handles found
1097 4 +
1098 // Two uint for the first invalid handle found
1099 8 +
1100 // One uint for the number of current valid handles
1101 4 +
1102 // Two uint for each current valid handle
1103 (8 * current_valid_handles.size());
1104
1105 VkBufferCreateInfo validation_buffer_create_info = {};
1106 validation_buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1107 validation_buffer_create_info.size = validation_buffer_size;
1108 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1109
1110 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
1111 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
1112
1113 VkResult result = vmaCreateBuffer(gpu_validation_state->vmaAllocator, &validation_buffer_create_info,
1114 &validation_buffer_alloc_info, &as_validation_buffer_info.validation_buffer,
1115 &as_validation_buffer_info.validation_buffer_allocation, nullptr);
1116 if (result != VK_SUCCESS) {
1117 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
1118 "Unable to allocate device memory. Device could become unstable.");
1119 gpu_validation_state->aborted = true;
1120 return;
1121 }
1122
1123 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
1124 result = vmaMapMemory(gpu_validation_state->vmaAllocator, as_validation_buffer_info.validation_buffer_allocation,
1125 (void **)&mapped_validation_buffer);
1126 if (result != VK_SUCCESS) {
1127 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
1128 "Unable to allocate device memory for acceleration structure build val buffer.");
1129 gpu_validation_state->aborted = true;
1130 return;
1131 }
1132
1133 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
1134 mapped_validation_buffer->replacement_handle_bits_0 =
1135 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
1136 mapped_validation_buffer->replacement_handle_bits_1 =
1137 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
1138 mapped_validation_buffer->invalid_handle_found = 0;
1139 mapped_validation_buffer->invalid_handle_bits_0 = 0;
1140 mapped_validation_buffer->invalid_handle_bits_1 = 0;
1141 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
1142
1143 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
1144 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
1145 const uint64_t current_valid_handle = current_valid_handles[i];
1146
1147 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
1148 ++mapped_valid_handles;
1149 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
1150 ++mapped_valid_handles;
1151 }
1152
1153 vmaUnmapMemory(gpu_validation_state->vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
1154
1155 static constexpr const VkDeviceSize kInstanceSize = 64;
1156 const VkDeviceSize instance_buffer_size = kInstanceSize * pInfo->instanceCount;
1157
1158 result = gpu_validation_state->desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool,
1159 &as_validation_buffer_info.descriptor_set);
1160 if (result != VK_SUCCESS) {
1161 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
1162 "Unable to get descriptor set for acceleration structure build.");
1163 gpu_validation_state->aborted = true;
1164 return;
1165 }
1166
1167 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
1168 descriptor_buffer_infos[0].buffer = instanceData;
1169 descriptor_buffer_infos[0].offset = instanceOffset;
1170 descriptor_buffer_infos[0].range = instance_buffer_size;
1171 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.validation_buffer;
1172 descriptor_buffer_infos[1].offset = 0;
1173 descriptor_buffer_infos[1].range = validation_buffer_size;
1174
1175 VkWriteDescriptorSet descriptor_set_writes[2] = {};
1176 descriptor_set_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1177 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
1178 descriptor_set_writes[0].dstBinding = 0;
1179 descriptor_set_writes[0].descriptorCount = 1;
1180 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1181 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
1182 descriptor_set_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1183 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
1184 descriptor_set_writes[1].dstBinding = 1;
1185 descriptor_set_writes[1].descriptorCount = 1;
1186 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1187 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
1188
1189 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
1190
1191 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
1192 VkMemoryBarrier memory_barrier = {};
1193 memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
1194 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
1195 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
1196 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
1197 &memory_barrier, 0, nullptr, 0, nullptr);
1198
1199 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001200 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001201 restorable_state.Create(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
1202
1203 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
1204 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
1205 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
1206 &as_validation_buffer_info.descriptor_set, 0, nullptr);
1207 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
1208
1209 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
1210 // have been replaced by the validation compute shader before any builds take place.
1211 VkBufferMemoryBarrier instance_buffer_barrier = {};
1212 instance_buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1213 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1214 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
1215 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1216 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1217 instance_buffer_barrier.buffer = instanceData;
1218 instance_buffer_barrier.offset = instanceOffset;
1219 instance_buffer_barrier.size = instance_buffer_size;
1220 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1221 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
1222 nullptr);
1223
1224 // Restore the previous compute pipeline state.
1225 restorable_state.Restore(commandBuffer);
1226
1227 as_validation_state.validation_buffers[commandBuffer].push_back(std::move(as_validation_buffer_info));
1228}
1229
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001230void GpuAssisted::ProcessAccelerationStructureBuildValidationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Jason Macnak83cfd582019-07-31 10:14:24 -07001231 if (cb_node == nullptr || !cb_node->hasBuildAccelerationStructureCmd) {
1232 return;
1233 }
1234
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001235 auto &as_validation_info = gpu_validation_state->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001236 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[cb_node->commandBuffer];
1237 for (const auto &as_validation_buffer_info : as_validation_buffer_infos) {
1238 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
1239
1240 VkResult result = vmaMapMemory(gpu_validation_state->vmaAllocator, as_validation_buffer_info.validation_buffer_allocation,
1241 (void **)&mapped_validation_buffer);
1242 if (result == VK_SUCCESS) {
1243 if (mapped_validation_buffer->invalid_handle_found > 0) {
1244 uint64_t invalid_handle = 0;
1245 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
1246 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
1247
1248 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT,
1249 HandleToUint64(as_validation_buffer_info.acceleration_structure), "UNASSIGNED-AccelerationStructure",
1250 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
1251 "handle (%" PRIu64 ")",
1252 invalid_handle);
1253 }
1254 vmaUnmapMemory(gpu_validation_state->vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
1255 }
1256 }
1257}
1258
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001259void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
1260 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
1261 VkResult result) {
1262 if (VK_SUCCESS != result) return;
1263 StateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
1264 for (uint32_t i = 0; i < bindInfoCount; i++) {
1265 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
1266 ACCELERATION_STRUCTURE_STATE *as_state = GetAccelerationStructureState(info.accelerationStructure);
1267 if (as_state) {
1268 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
1269 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001270 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001271}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -07001272
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001273// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
1274void GpuAssisted::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
1275 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
1276 void *cpl_state_data) {
1277 if (gpu_validation_state->aborted) {
1278 return;
1279 }
1280 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
1281
1282 if (cpl_state->modified_create_info.setLayoutCount >= gpu_validation_state->adjusted_max_desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001283 std::ostringstream strm;
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001284 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << gpu_validation_state->desc_set_bind_index
1285 << ". "
Karl Schultz7b024b42018-08-30 16:18:18 -06001286 << "Application has too many descriptor sets in the pipeline layout to continue with gpu validation. "
1287 << "Validation is not modifying the pipeline layout. "
1288 << "Instrumented shaders are replaced with non-instrumented shaders.";
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001289 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device), strm.str().c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -06001290 } else {
1291 // Modify the pipeline layout by:
1292 // 1. Copying the caller's descriptor set desc_layouts
1293 // 2. Fill in dummy descriptor layouts up to the max binding
1294 // 3. Fill in with the debug descriptor layout at the max binding slot
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001295 cpl_state->new_layouts.reserve(gpu_validation_state->adjusted_max_desc_sets);
1296 cpl_state->new_layouts.insert(cpl_state->new_layouts.end(), &pCreateInfo->pSetLayouts[0],
1297 &pCreateInfo->pSetLayouts[pCreateInfo->setLayoutCount]);
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001298 for (uint32_t i = pCreateInfo->setLayoutCount; i < gpu_validation_state->adjusted_max_desc_sets - 1; ++i) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001299 cpl_state->new_layouts.push_back(gpu_validation_state->dummy_desc_layout);
Karl Schultz7b024b42018-08-30 16:18:18 -06001300 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001301 cpl_state->new_layouts.push_back(gpu_validation_state->debug_desc_layout);
1302 cpl_state->modified_create_info.pSetLayouts = cpl_state->new_layouts.data();
1303 cpl_state->modified_create_info.setLayoutCount = gpu_validation_state->adjusted_max_desc_sets;
Karl Schultz7b024b42018-08-30 16:18:18 -06001304 }
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -07001305}
1306
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001307void GpuAssisted::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
1308 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
1309 VkResult result) {
1310 StateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
Karl Schultz7b024b42018-08-30 16:18:18 -06001311 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001312 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz7b024b42018-08-30 16:18:18 -06001313 "Unable to create pipeline layout. Device could become unstable.");
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001314 gpu_validation_state->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -06001315 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001316}
1317
Karl Schultz7b024b42018-08-30 16:18:18 -06001318// Free the device memory and descriptor set associated with a command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001319void GpuAssisted::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001320 if (gpu_validation_state->aborted) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001321 return;
1322 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001323 auto gpuav_buffer_list = gpu_validation_state->GetGpuAssistedBufferInfo(commandBuffer);
1324 for (auto buffer_info : gpuav_buffer_list) {
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001325 vmaDestroyBuffer(gpu_validation_state->vmaAllocator, buffer_info.output_mem_block.buffer,
1326 buffer_info.output_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001327 if (buffer_info.di_input_mem_block.buffer) {
1328 vmaDestroyBuffer(gpu_validation_state->vmaAllocator, buffer_info.di_input_mem_block.buffer,
1329 buffer_info.di_input_mem_block.allocation);
1330 }
1331 if (buffer_info.bda_input_mem_block.buffer) {
1332 vmaDestroyBuffer(gpu_validation_state->vmaAllocator, buffer_info.bda_input_mem_block.buffer,
1333 buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -06001334 }
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001335 if (buffer_info.desc_set != VK_NULL_HANDLE) {
1336 gpu_validation_state->desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
1337 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001338 }
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001339 gpu_validation_state->command_buffer_map.erase(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001340
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001341 auto &as_validation_info = gpu_validation_state->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001342 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[commandBuffer];
1343 for (auto &as_validation_buffer_info : as_validation_buffer_infos) {
1344 vmaDestroyBuffer(gpu_validation_state->vmaAllocator, as_validation_buffer_info.validation_buffer,
1345 as_validation_buffer_info.validation_buffer_allocation);
1346
1347 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
1348 gpu_validation_state->desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool,
1349 as_validation_buffer_info.descriptor_set);
1350 }
1351 }
1352 as_validation_info.validation_buffers.erase(commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -06001353}
Karl Schultz7b024b42018-08-30 16:18:18 -06001354// Just gives a warning about a possible deadlock.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001355bool GpuAssisted::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
1356 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
1357 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1358 uint32_t bufferMemoryBarrierCount,
1359 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
1360 const VkImageMemoryBarrier *pImageMemoryBarriers) {
1361 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
1362 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer),
Karl Schultz7b024b42018-08-30 16:18:18 -06001363 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1364 "GPU_Assisted validation waits on queue completion. "
1365 "This wait could block the host's signaling of this event, resulting in deadlock.");
1366 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001367 return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001368}
1369
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001370void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1371 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
1372 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
1373 if (enabled.gpu_validation_reserve_binding_slot && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
1374 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
1375 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
1376 } else {
1377 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1378 HandleToUint64(physicalDevice), "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1379 "Unable to reserve descriptor binding slot on a device with only one slot.");
1380 }
1381 }
1382}
1383
1384void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1385 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
1386 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
1387 if (enabled.gpu_validation_reserve_binding_slot && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
1388 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
1389 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
1390 } else {
1391 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1392 HandleToUint64(physicalDevice), "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1393 "Unable to reserve descriptor binding slot on a device with only one slot.");
1394 }
1395 }
1396}
1397
1398void GpuAssisted::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1399 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1400 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1401 void *cgpl_state_data) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001402 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001403 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
1404 PreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state, &new_pipeline_create_infos,
1405 VK_PIPELINE_BIND_POINT_GRAPHICS);
1406 cgpl_state->gpu_create_infos = new_pipeline_create_infos;
1407 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001408}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001409
1410void GpuAssisted::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1411 const VkComputePipelineCreateInfo *pCreateInfos,
1412 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1413 void *ccpl_state_data) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001414 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001415 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
1416 PreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state, &new_pipeline_create_infos,
1417 VK_PIPELINE_BIND_POINT_COMPUTE);
1418 ccpl_state->gpu_create_infos = new_pipeline_create_infos;
1419 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
Jason Macnak67407e72019-07-11 11:05:09 -07001420}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001421
1422void GpuAssisted::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1423 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1424 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1425 void *crtpl_state_data) {
Jason Macnak67407e72019-07-11 11:05:09 -07001426 std::vector<safe_VkRayTracingPipelineCreateInfoNV> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001427 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
1428 PreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state, &new_pipeline_create_infos,
1429 VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
1430 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1431 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001432}
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001433template <typename CreateInfo>
1434struct CreatePipelineTraits {};
1435template <>
1436struct CreatePipelineTraits<VkGraphicsPipelineCreateInfo> {
1437 using SafeType = safe_VkGraphicsPipelineCreateInfo;
1438 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->graphicsPipelineCI; }
1439 static uint32_t GetStageCount(const VkGraphicsPipelineCreateInfo &createInfo) { return createInfo.stageCount; }
1440 static VkShaderModule GetShaderModule(const VkGraphicsPipelineCreateInfo &createInfo, uint32_t stage) {
1441 return createInfo.pStages[stage].module;
1442 }
1443 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
1444 createInfo->pStages[stage].module = shader_module;
1445 }
1446};
1447
1448template <>
1449struct CreatePipelineTraits<VkComputePipelineCreateInfo> {
1450 using SafeType = safe_VkComputePipelineCreateInfo;
1451 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->computePipelineCI; }
1452 static uint32_t GetStageCount(const VkComputePipelineCreateInfo &createInfo) { return 1; }
1453 static VkShaderModule GetShaderModule(const VkComputePipelineCreateInfo &createInfo, uint32_t stage) {
1454 return createInfo.stage.module;
1455 }
1456 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
1457 assert(stage == 0);
1458 createInfo->stage.module = shader_module;
1459 }
1460};
1461template <>
1462struct CreatePipelineTraits<VkRayTracingPipelineCreateInfoNV> {
1463 using SafeType = safe_VkRayTracingPipelineCreateInfoNV;
1464 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->raytracingPipelineCI; }
1465 static uint32_t GetStageCount(const VkRayTracingPipelineCreateInfoNV &createInfo) { return createInfo.stageCount; }
1466 static VkShaderModule GetShaderModule(const VkRayTracingPipelineCreateInfoNV &createInfo, uint32_t stage) {
1467 return createInfo.pStages[stage].module;
1468 }
1469 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
1470 createInfo->pStages[stage].module = shader_module;
1471 }
1472};
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001473
1474// Examine the pipelines to see if they use the debug descriptor set binding index.
1475// If any do, create new non-instrumented shader modules and use them to replace the instrumented
1476// shaders in the pipeline. Return the (possibly) modified create infos to the caller.
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001477template <typename CreateInfo, typename SafeCreateInfo>
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001478void GpuAssisted::PreCallRecordPipelineCreations(uint32_t count, const CreateInfo *pCreateInfos,
1479 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1480 std::vector<std::unique_ptr<PIPELINE_STATE>> &pipe_state,
1481 std::vector<SafeCreateInfo> *new_pipeline_create_infos,
1482 const VkPipelineBindPoint bind_point) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001483 using Accessor = CreatePipelineTraits<CreateInfo>;
Jason Macnak67407e72019-07-11 11:05:09 -07001484 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1485 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001486 return;
1487 }
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001488
Karl Schultz7b024b42018-08-30 16:18:18 -06001489 // Walk through all the pipelines, make a copy of each and flag each pipeline that contains a shader that uses the debug
1490 // descriptor set index.
1491 for (uint32_t pipeline = 0; pipeline < count; ++pipeline) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001492 uint32_t stageCount = Accessor::GetStageCount(pCreateInfos[pipeline]);
1493 new_pipeline_create_infos->push_back(Accessor::GetPipelineCI(pipe_state[pipeline].get()));
Jason Macnak67407e72019-07-11 11:05:09 -07001494
1495 bool replace_shaders = false;
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001496 if (pipe_state[pipeline]->active_slots.find(gpu_validation_state->desc_set_bind_index) !=
1497 pipe_state[pipeline]->active_slots.end()) {
Tony-LunarGd4da33b2019-04-16 16:28:22 -06001498 replace_shaders = true;
Karl Schultz7b024b42018-08-30 16:18:18 -06001499 }
Tony-LunarGd4da33b2019-04-16 16:28:22 -06001500 // If the app requests all available sets, the pipeline layout was not modified at pipeline layout creation and the already
1501 // instrumented shaders need to be replaced with uninstrumented shaders
1502 if (pipe_state[pipeline]->pipeline_layout.set_layouts.size() >= gpu_validation_state->adjusted_max_desc_sets) {
1503 replace_shaders = true;
1504 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001505
Tony-LunarGd4da33b2019-04-16 16:28:22 -06001506 if (replace_shaders) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001507 for (uint32_t stage = 0; stage < stageCount; ++stage) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001508 const SHADER_MODULE_STATE *shader = GetShaderModuleState(Accessor::GetShaderModule(pCreateInfos[pipeline], stage));
Jason Macnak67407e72019-07-11 11:05:09 -07001509
Karl Schultz7b024b42018-08-30 16:18:18 -06001510 VkShaderModuleCreateInfo create_info = {};
1511 VkShaderModule shader_module;
1512 create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
1513 create_info.pCode = shader->words.data();
1514 create_info.codeSize = shader->words.size() * sizeof(uint32_t);
Tony-LunarG152a88b2019-03-20 15:42:24 -06001515 VkResult result = DispatchCreateShaderModule(device, &create_info, pAllocator, &shader_module);
Karl Schultz7b024b42018-08-30 16:18:18 -06001516 if (result == VK_SUCCESS) {
Petr Kraus6c4bdce2019-08-27 17:35:01 +02001517 Accessor::SetShaderModule(&(*new_pipeline_create_infos)[pipeline], shader_module, stage);
Karl Schultz7b024b42018-08-30 16:18:18 -06001518 } else {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001519 uint64_t moduleHandle = HandleToUint64(Accessor::GetShaderModule(pCreateInfos[pipeline], stage));
Jason Macnak67407e72019-07-11 11:05:09 -07001520 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, moduleHandle,
Karl Schultz7b024b42018-08-30 16:18:18 -06001521 "Unable to replace instrumented shader with non-instrumented one. "
1522 "Device could become unstable.");
1523 }
1524 }
1525 }
1526 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001527}
1528
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001529void GpuAssisted::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1530 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1531 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1532 VkResult result, void *cgpl_state_data) {
1533 StateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines, result,
1534 cgpl_state_data);
1535 PostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001536}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001537void GpuAssisted::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1538 const VkComputePipelineCreateInfo *pCreateInfos,
1539 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1540 VkResult result, void *ccpl_state_data) {
1541 StateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines, result,
1542 ccpl_state_data);
1543 PostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001544}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001545void GpuAssisted::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1546 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1547 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1548 VkResult result, void *crtpl_state_data) {
1549 StateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1550 result, crtpl_state_data);
1551 PostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
Jason Macnak67407e72019-07-11 11:05:09 -07001552}
1553
Karl Schultz7b024b42018-08-30 16:18:18 -06001554// For every pipeline:
1555// - For every shader in a pipeline:
1556// - If the shader had to be replaced in PreCallRecord (because the pipeline is using the debug desc set index):
1557// - Destroy it since it has been bound into the pipeline by now. This is our only chance to delete it.
1558// - Track the shader in the shader_map
1559// - Save the shader binary if it contains debug code
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001560template <typename CreateInfo>
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001561void GpuAssisted::PostCallRecordPipelineCreations(const uint32_t count, const CreateInfo *pCreateInfos,
1562 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1563 const VkPipelineBindPoint bind_point) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001564 using Accessor = CreatePipelineTraits<CreateInfo>;
Jason Macnak67407e72019-07-11 11:05:09 -07001565 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1566 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001567 return;
1568 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001569 for (uint32_t pipeline = 0; pipeline < count; ++pipeline) {
Tobin Ehlisfd68ba12019-08-22 08:16:18 -06001570 auto pipeline_state = ValidationStateTracker::GetPipelineState(pPipelines[pipeline]);
Karl Schultz7b024b42018-08-30 16:18:18 -06001571 if (nullptr == pipeline_state) continue;
Jason Macnak67407e72019-07-11 11:05:09 -07001572
1573 uint32_t stageCount = 0;
1574 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1575 stageCount = pipeline_state->graphicsPipelineCI.stageCount;
1576 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1577 stageCount = 1;
1578 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1579 stageCount = pipeline_state->raytracingPipelineCI.stageCount;
1580 } else {
1581 assert(false);
1582 }
1583
1584 for (uint32_t stage = 0; stage < stageCount; ++stage) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001585 if (pipeline_state->active_slots.find(gpu_validation_state->desc_set_bind_index) !=
1586 pipeline_state->active_slots.end()) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001587 DispatchDestroyShaderModule(device, Accessor::GetShaderModule(pCreateInfos[pipeline], stage), pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001588 }
Jason Macnak67407e72019-07-11 11:05:09 -07001589
1590 const SHADER_MODULE_STATE *shader_state = nullptr;
1591 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1592 shader_state = GetShaderModuleState(pipeline_state->graphicsPipelineCI.pStages[stage].module);
1593 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1594 assert(stage == 0);
1595 shader_state = GetShaderModuleState(pipeline_state->computePipelineCI.stage.module);
1596 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1597 shader_state = GetShaderModuleState(pipeline_state->raytracingPipelineCI.pStages[stage].module);
1598 } else {
1599 assert(false);
1600 }
1601
Karl Schultz7b024b42018-08-30 16:18:18 -06001602 std::vector<unsigned int> code;
1603 // Save the shader binary if debug info is present.
1604 // The core_validation ShaderModule tracker saves the binary too, but discards it when the ShaderModule
1605 // is destroyed. Applications may destroy ShaderModules after they are placed in a pipeline and before
1606 // the pipeline is used, so we have to keep another copy.
1607 if (shader_state && shader_state->has_valid_spirv) { // really checking for presense of SPIR-V code.
1608 for (auto insn : *shader_state) {
1609 if (insn.opcode() == spv::OpLine) {
1610 code = shader_state->words;
1611 break;
1612 }
1613 }
1614 }
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001615 gpu_validation_state->shader_map[shader_state->gpu_validation_shader_id].pipeline = pipeline_state->pipeline;
Karl Schultz7b024b42018-08-30 16:18:18 -06001616 // Be careful to use the originally bound (instrumented) shader here, even if PreCallRecord had to back it
1617 // out with a non-instrumented shader. The non-instrumented shader (found in pCreateInfo) was destroyed above.
Jason Macnak67407e72019-07-11 11:05:09 -07001618 VkShaderModule shader_module = VK_NULL_HANDLE;
1619 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1620 shader_module = pipeline_state->graphicsPipelineCI.pStages[stage].module;
1621 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1622 assert(stage == 0);
1623 shader_module = pipeline_state->computePipelineCI.stage.module;
1624 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1625 shader_module = pipeline_state->raytracingPipelineCI.pStages[stage].module;
1626 } else {
1627 assert(false);
1628 }
1629 gpu_validation_state->shader_map[shader_state->gpu_validation_shader_id].shader_module = shader_module;
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001630 gpu_validation_state->shader_map[shader_state->gpu_validation_shader_id].pgm = std::move(code);
Karl Schultz7b024b42018-08-30 16:18:18 -06001631 }
1632 }
1633}
1634
1635// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001636void GpuAssisted::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001637 for (auto it = gpu_validation_state->shader_map.begin(); it != gpu_validation_state->shader_map.end();) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001638 if (it->second.pipeline == pipeline) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001639 it = gpu_validation_state->shader_map.erase(it);
Karl Schultz7b024b42018-08-30 16:18:18 -06001640 } else {
1641 ++it;
1642 }
1643 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001644 StateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001645}
1646
1647// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001648bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
1649 uint32_t *unique_shader_id) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001650 if (gpu_validation_state->aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001651 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
1652
1653 // Load original shader SPIR-V
1654 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
1655 new_pgm.clear();
1656 new_pgm.reserve(num_words);
1657 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
1658
1659 // Call the optimizer to instrument the shader.
1660 // 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 -07001661 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Mark Lobodzinskif45e45f2019-04-19 14:15:39 -06001662 const bool descriptor_indexing = device_extensions.vk_ext_descriptor_indexing;
Karl Schultz7b024b42018-08-30 16:18:18 -06001663 using namespace spvtools;
1664 spv_target_env target_env = SPV_ENV_VULKAN_1_1;
1665 Optimizer optimizer(target_env);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001666 optimizer.RegisterPass(CreateInstBindlessCheckPass(gpu_validation_state->desc_set_bind_index,
Tony-LunarGa77cade2019-03-06 10:49:22 -07001667 gpu_validation_state->unique_shader_module_id, descriptor_indexing,
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001668 descriptor_indexing, 2));
Karl Schultz7b024b42018-08-30 16:18:18 -06001669 optimizer.RegisterPass(CreateAggressiveDCEPass());
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001670 if (device_extensions.vk_ext_buffer_device_address && gpu_validation_state->shaderInt64)
1671 optimizer.RegisterPass(
1672 CreateInstBuffAddrCheckPass(gpu_validation_state->desc_set_bind_index, gpu_validation_state->unique_shader_module_id));
Karl Schultz7b024b42018-08-30 16:18:18 -06001673 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm);
1674 if (!pass) {
Mark Lobodzinski586d10e2019-03-08 18:19:48 -07001675 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, VK_NULL_HANDLE,
Karl Schultz7b024b42018-08-30 16:18:18 -06001676 "Failure to instrument shader. Proceeding with non-instrumented shader.");
1677 }
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001678 *unique_shader_id = gpu_validation_state->unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -06001679 return pass;
1680}
Mark Lobodzinski01734072019-02-13 17:39:15 -07001681// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001682void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
1683 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
1684 void *csm_state_data) {
1685 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
1686 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -06001687 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001688 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
1689 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
Karl Schultz7b024b42018-08-30 16:18:18 -06001690 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001691}
1692
1693// Generate the stage-specific part of the message.
1694static void GenerateStageMessage(const uint32_t *debug_record, std::string &msg) {
1695 using namespace spvtools;
1696 std::ostringstream strm;
1697 switch (debug_record[kInstCommonOutStageIdx]) {
Jason Macnak67407e72019-07-11 11:05:09 -07001698 case spv::ExecutionModelVertex: {
Tony-LunarG6ff87582019-02-08 10:29:07 -07001699 strm << "Stage = Vertex. Vertex Index = " << debug_record[kInstVertOutVertexIndex]
1700 << " Instance Index = " << debug_record[kInstVertOutInstanceIndex] << ". ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001701 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001702 case spv::ExecutionModelTessellationControl: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001703 strm << "Stage = Tessellation Control. Invocation ID = " << debug_record[kInstTessCtlOutInvocationId]
1704 << ", Primitive ID = " << debug_record[kInstTessCtlOutPrimitiveId];
Karl Schultz7b024b42018-08-30 16:18:18 -06001705 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001706 case spv::ExecutionModelTessellationEvaluation: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001707 strm << "Stage = Tessellation Eval. Primitive ID = " << debug_record[kInstTessEvalOutPrimitiveId]
1708 << ", TessCoord (u, v) = (" << debug_record[kInstTessEvalOutTessCoordU] << ", "
1709 << debug_record[kInstTessEvalOutTessCoordV] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001710 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001711 case spv::ExecutionModelGeometry: {
Karl Schultz7b024b42018-08-30 16:18:18 -06001712 strm << "Stage = Geometry. Primitive ID = " << debug_record[kInstGeomOutPrimitiveId]
1713 << " Invocation ID = " << debug_record[kInstGeomOutInvocationId] << ". ";
1714 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001715 case spv::ExecutionModelFragment: {
Karl Schultz7b024b42018-08-30 16:18:18 -06001716 strm << "Stage = Fragment. Fragment coord (x,y) = ("
1717 << *reinterpret_cast<const float *>(&debug_record[kInstFragOutFragCoordX]) << ", "
1718 << *reinterpret_cast<const float *>(&debug_record[kInstFragOutFragCoordY]) << "). ";
1719 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001720 case spv::ExecutionModelGLCompute: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001721 strm << "Stage = Compute. Global invocation ID (x, y, z) = (" << debug_record[kInstCompOutGlobalInvocationIdX] << ", "
1722 << debug_record[kInstCompOutGlobalInvocationIdY] << ", " << debug_record[kInstCompOutGlobalInvocationIdZ] << " )";
Karl Schultz7b024b42018-08-30 16:18:18 -06001723 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001724 case spv::ExecutionModelRayGenerationNV: {
1725 strm << "Stage = Ray Generation. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1726 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1727 } break;
1728 case spv::ExecutionModelIntersectionNV: {
1729 strm << "Stage = Intersection. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1730 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1731 } break;
1732 case spv::ExecutionModelAnyHitNV: {
1733 strm << "Stage = Any Hit. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1734 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1735 } break;
1736 case spv::ExecutionModelClosestHitNV: {
1737 strm << "Stage = Closest Hit. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1738 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1739 } break;
1740 case spv::ExecutionModelMissNV: {
1741 strm << "Stage = Miss. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1742 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1743 } break;
1744 case spv::ExecutionModelCallableNV: {
1745 strm << "Stage = Callable. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1746 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1747 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001748 default: {
1749 strm << "Internal Error (unexpected stage = " << debug_record[kInstCommonOutStageIdx] << "). ";
1750 assert(false);
1751 } break;
1752 }
1753 msg = strm.str();
1754}
1755
1756// Generate the part of the message describing the violation.
1757static void GenerateValidationMessage(const uint32_t *debug_record, std::string &msg, std::string &vuid_msg) {
1758 using namespace spvtools;
1759 std::ostringstream strm;
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001760 switch (debug_record[kInst2ValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001761 case kInstErrorBindlessBounds: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001762 strm << "Index of " << debug_record[kInst2BindlessBoundsOutDescIndex] << " used to index descriptor array of length "
1763 << debug_record[kInst2BindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001764 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -06001765 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001766 case kInstErrorBindlessUninit: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001767 strm << "Descriptor index " << debug_record[kInst2BindlessUninitOutDescIndex] << " is uninitialized. ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001768 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -06001769 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001770 case kInstErrorBuffAddrUnallocRef: {
1771 uint64_t *ptr = (uint64_t *)&debug_record[kInst2BuffAddrUnallocOutDescPtrLo];
1772 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
1773 vuid_msg = "UNASSIGNED-Device address out of bounds";
1774 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001775 default: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001776 strm << "Internal Error (unexpected error type = " << debug_record[kInst2ValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001777 vuid_msg = "UNASSIGNED-Internal Error";
1778 assert(false);
1779 } break;
1780 }
1781 msg = strm.str();
1782}
1783
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001784static std::string LookupDebugUtilsName(const debug_report_data *report_data, const uint64_t object) {
Mark Lobodzinski1d7313a2019-02-07 11:04:42 -07001785 auto object_label = report_data->DebugReportGetUtilsObjectName(object);
1786 if (object_label != "") {
1787 object_label = "(" + object_label + ")";
Karl Schultz7b024b42018-08-30 16:18:18 -06001788 }
Mark Lobodzinski1d7313a2019-02-07 11:04:42 -07001789 return object_label;
Karl Schultz7b024b42018-08-30 16:18:18 -06001790}
1791
1792// Generate message from the common portion of the debug report record.
Mark Lobodzinski33a34b82019-04-25 11:38:36 -06001793static void GenerateCommonMessage(const debug_report_data *report_data, const CMD_BUFFER_STATE *cb_node,
1794 const uint32_t *debug_record, const VkShaderModule shader_module_handle,
Jason Macnak67407e72019-07-11 11:05:09 -07001795 const VkPipeline pipeline_handle, const VkPipelineBindPoint pipeline_bind_point,
1796 const uint32_t operation_index, std::string &msg) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001797 using namespace spvtools;
1798 std::ostringstream strm;
1799 if (shader_module_handle == VK_NULL_HANDLE) {
1800 strm << std::hex << std::showbase << "Internal Error: Unable to locate information for shader used in command buffer "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001801 << LookupDebugUtilsName(report_data, HandleToUint64(cb_node->commandBuffer)) << "("
Karl Schultz7b024b42018-08-30 16:18:18 -06001802 << HandleToUint64(cb_node->commandBuffer) << "). ";
1803 assert(true);
1804 } else {
1805 strm << std::hex << std::showbase << "Command buffer "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001806 << LookupDebugUtilsName(report_data, HandleToUint64(cb_node->commandBuffer)) << "("
Jason Macnak67407e72019-07-11 11:05:09 -07001807 << HandleToUint64(cb_node->commandBuffer) << "). ";
1808 if (pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1809 strm << "Draw ";
1810 } else if (pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1811 strm << "Compute ";
1812 } else if (pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1813 strm << "Ray Trace ";
1814 } else {
1815 assert(false);
1816 strm << "Unknown Pipeline Operation ";
1817 }
1818 strm << "Index " << operation_index << ". "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001819 << "Pipeline " << LookupDebugUtilsName(report_data, HandleToUint64(pipeline_handle)) << "("
Karl Schultz7b024b42018-08-30 16:18:18 -06001820 << HandleToUint64(pipeline_handle) << "). "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001821 << "Shader Module " << LookupDebugUtilsName(report_data, HandleToUint64(shader_module_handle)) << "("
Karl Schultz7b024b42018-08-30 16:18:18 -06001822 << HandleToUint64(shader_module_handle) << "). ";
1823 }
1824 strm << std::dec << std::noshowbase;
1825 strm << "Shader Instruction Index = " << debug_record[kInstCommonOutInstructionIdx] << ". ";
1826 msg = strm.str();
1827}
1828
1829// Read the contents of the SPIR-V OpSource instruction and any following continuation instructions.
1830// Split the single string into a vector of strings, one for each line, for easier processing.
Mark Lobodzinski3c59d972019-04-25 11:28:14 -06001831static void ReadOpSource(const SHADER_MODULE_STATE &shader, const uint32_t reported_file_id,
1832 std::vector<std::string> &opsource_lines) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001833 for (auto insn : shader) {
1834 if ((insn.opcode() == spv::OpSource) && (insn.len() >= 5) && (insn.word(3) == reported_file_id)) {
1835 std::istringstream in_stream;
1836 std::string cur_line;
1837 in_stream.str((char *)&insn.word(4));
1838 while (std::getline(in_stream, cur_line)) {
1839 opsource_lines.push_back(cur_line);
1840 }
1841 while ((++insn).opcode() == spv::OpSourceContinued) {
1842 in_stream.str((char *)&insn.word(1));
1843 while (std::getline(in_stream, cur_line)) {
1844 opsource_lines.push_back(cur_line);
1845 }
1846 }
1847 break;
1848 }
1849 }
1850}
Tony-LunarG03059b72019-02-19 13:57:41 -07001851
1852// The task here is to search the OpSource content to find the #line directive with the
1853// line number that is closest to, but still prior to the reported error line number and
1854// still within the reported filename.
1855// From this known position in the OpSource content we can add the difference between
1856// the #line line number and the reported error line number to determine the location
1857// in the OpSource content of the reported error line.
1858//
1859// Considerations:
1860// - Look only at #line directives that specify the reported_filename since
1861// the reported error line number refers to its location in the reported filename.
1862// - If a #line directive does not have a filename, the file is the reported filename, or
1863// the filename found in a prior #line directive. (This is C-preprocessor behavior)
1864// - It is possible (e.g., inlining) for blocks of code to get shuffled out of their
1865// original order and the #line directives are used to keep the numbering correct. This
1866// is why we need to examine the entire contents of the source, instead of leaving early
1867// when finding a #line line number larger than the reported error line number.
1868//
1869
1870// GCC 4.8 has a problem with std::regex that is fixed in GCC 4.9. Provide fallback code for 4.8
1871#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
1872
1873#if defined(__GNUC__) && GCC_VERSION < 40900
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001874static bool GetLineAndFilename(const std::string string, uint32_t *linenumber, std::string &filename) {
Tony-LunarG03059b72019-02-19 13:57:41 -07001875 // # line <linenumber> "<filename>" or
1876 // #line <linenumber> "<filename>"
1877 std::vector<std::string> tokens;
1878 std::stringstream stream(string);
1879 std::string temp;
1880 uint32_t line_index = 0;
1881
1882 while (stream >> temp) tokens.push_back(temp);
1883 auto size = tokens.size();
1884 if (size > 1) {
1885 if (tokens[0] == "#" && tokens[1] == "line") {
1886 line_index = 2;
1887 } else if (tokens[0] == "#line") {
1888 line_index = 1;
1889 }
1890 }
1891 if (0 == line_index) return false;
1892 *linenumber = std::stoul(tokens[line_index]);
1893 uint32_t filename_index = line_index + 1;
1894 // Remove enclosing double quotes around filename
1895 if (size > filename_index) filename = tokens[filename_index].substr(1, tokens[filename_index].size() - 2);
1896 return true;
1897}
1898#else
1899static bool GetLineAndFilename(const std::string string, uint32_t *linenumber, std::string &filename) {
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001900 static const std::regex line_regex( // matches #line directives
1901 "^" // beginning of line
1902 "\\s*" // optional whitespace
1903 "#" // required text
1904 "\\s*" // optional whitespace
1905 "line" // required text
1906 "\\s+" // required whitespace
1907 "([0-9]+)" // required first capture - line number
1908 "(\\s+)?" // optional second capture - whitespace
1909 "(\".+\")?" // optional third capture - quoted filename with at least one char inside
1910 ".*"); // rest of line (needed when using std::regex_match since the entire line is tested)
Karl Schultz7b024b42018-08-30 16:18:18 -06001911
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001912 std::smatch captures;
1913
1914 bool found_line = std::regex_match(string, captures, line_regex);
1915 if (!found_line) return false;
1916
1917 // filename is optional and considered found only if the whitespace and the filename are captured
1918 if (captures[2].matched && captures[3].matched) {
1919 // Remove enclosing double quotes. The regex guarantees the quotes and at least one char.
1920 filename = captures[3].str().substr(1, captures[3].str().size() - 2);
1921 }
1922 *linenumber = std::stoul(captures[1]);
1923 return true;
1924}
Tony-LunarG03059b72019-02-19 13:57:41 -07001925#endif // GCC_VERSION
1926
Karl Schultz7b024b42018-08-30 16:18:18 -06001927// Extract the filename, line number, and column number from the correct OpLine and build a message string from it.
1928// Scan the source (from OpSource) to find the line of source at the reported line number and place it in another message string.
1929static void GenerateSourceMessages(const std::vector<unsigned int> &pgm, const uint32_t *debug_record, std::string &filename_msg,
1930 std::string &source_msg) {
1931 using namespace spvtools;
1932 std::ostringstream filename_stream;
1933 std::ostringstream source_stream;
Mark Lobodzinski3c59d972019-04-25 11:28:14 -06001934 SHADER_MODULE_STATE shader;
Karl Schultz7b024b42018-08-30 16:18:18 -06001935 shader.words = pgm;
1936 // Find the OpLine just before the failing instruction indicated by the debug info.
1937 // SPIR-V can only be iterated in the forward direction due to its opcode/length encoding.
1938 uint32_t instruction_index = 0;
1939 uint32_t reported_file_id = 0;
1940 uint32_t reported_line_number = 0;
1941 uint32_t reported_column_number = 0;
1942 if (shader.words.size() > 0) {
1943 for (auto insn : shader) {
1944 if (insn.opcode() == spv::OpLine) {
1945 reported_file_id = insn.word(1);
1946 reported_line_number = insn.word(2);
1947 reported_column_number = insn.word(3);
1948 }
1949 if (instruction_index == debug_record[kInstCommonOutInstructionIdx]) {
1950 break;
1951 }
1952 instruction_index++;
1953 }
1954 }
1955 // Create message with file information obtained from the OpString pointed to by the discovered OpLine.
1956 std::string reported_filename;
1957 if (reported_file_id == 0) {
1958 filename_stream
1959 << "Unable to find SPIR-V OpLine for source information. Build shader with debug info to get source information.";
1960 } else {
1961 bool found_opstring = false;
1962 for (auto insn : shader) {
1963 if ((insn.opcode() == spv::OpString) && (insn.len() >= 3) && (insn.word(1) == reported_file_id)) {
1964 found_opstring = true;
1965 reported_filename = (char *)&insn.word(2);
1966 if (reported_filename.empty()) {
1967 filename_stream << "Shader validation error occurred at line " << reported_line_number;
1968 } else {
1969 filename_stream << "Shader validation error occurred in file: " << reported_filename << " at line "
1970 << reported_line_number;
1971 }
1972 if (reported_column_number > 0) {
1973 filename_stream << ", column " << reported_column_number;
1974 }
1975 filename_stream << ".";
1976 break;
1977 }
1978 }
1979 if (!found_opstring) {
1980 filename_stream << "Unable to find SPIR-V OpString for file id " << reported_file_id << " from OpLine instruction.";
1981 }
1982 }
1983 filename_msg = filename_stream.str();
1984
1985 // Create message to display source code line containing error.
1986 if ((reported_file_id != 0)) {
1987 // Read the source code and split it up into separate lines.
1988 std::vector<std::string> opsource_lines;
1989 ReadOpSource(shader, reported_file_id, opsource_lines);
1990 // Find the line in the OpSource content that corresponds to the reported error file and line.
1991 if (!opsource_lines.empty()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001992 uint32_t saved_line_number = 0;
1993 std::string current_filename = reported_filename; // current "preprocessor" filename state.
1994 std::vector<std::string>::size_type saved_opsource_offset = 0;
1995 bool found_best_line = false;
1996 for (auto it = opsource_lines.begin(); it != opsource_lines.end(); ++it) {
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001997 uint32_t parsed_line_number;
1998 std::string parsed_filename;
1999 bool found_line = GetLineAndFilename(*it, &parsed_line_number, parsed_filename);
Karl Schultz7b024b42018-08-30 16:18:18 -06002000 if (!found_line) continue;
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07002001
2002 bool found_filename = parsed_filename.size() > 0;
Karl Schultz7b024b42018-08-30 16:18:18 -06002003 if (found_filename) {
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07002004 current_filename = parsed_filename;
Karl Schultz7b024b42018-08-30 16:18:18 -06002005 }
2006 if ((!found_filename) || (current_filename == reported_filename)) {
Karl Schultz7b024b42018-08-30 16:18:18 -06002007 // Update the candidate best line directive, if the current one is prior and closer to the reported line
2008 if (reported_line_number >= parsed_line_number) {
2009 if (!found_best_line ||
2010 (reported_line_number - parsed_line_number <= reported_line_number - saved_line_number)) {
2011 saved_line_number = parsed_line_number;
2012 saved_opsource_offset = std::distance(opsource_lines.begin(), it);
2013 found_best_line = true;
2014 }
2015 }
2016 }
2017 }
2018 if (found_best_line) {
2019 assert(reported_line_number >= saved_line_number);
2020 std::vector<std::string>::size_type opsource_index =
2021 (reported_line_number - saved_line_number) + 1 + saved_opsource_offset;
2022 if (opsource_index < opsource_lines.size()) {
2023 source_stream << "\n" << reported_line_number << ": " << opsource_lines[opsource_index].c_str();
2024 } else {
2025 source_stream << "Internal error: calculated source line of " << opsource_index << " for source size of "
2026 << opsource_lines.size() << " lines.";
2027 }
2028 } else {
2029 source_stream << "Unable to find suitable #line directive in SPIR-V OpSource.";
2030 }
2031 } else {
2032 source_stream << "Unable to find SPIR-V OpSource.";
2033 }
2034 }
2035 source_msg = source_stream.str();
2036}
2037
2038// Pull together all the information from the debug record to build the error message strings,
2039// and then assemble them into a single message string.
2040// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
2041// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
2042// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
2043// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
2044//
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002045void GpuAssisted::AnalyzeAndReportError(CMD_BUFFER_STATE *cb_node, VkQueue queue, VkPipelineBindPoint pipeline_bind_point,
2046 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06002047 using namespace spvtools;
2048 const uint32_t total_words = debug_output_buffer[0];
2049 // A zero here means that the shader instrumentation didn't write anything.
2050 // If you have nothing to say, don't say it here.
2051 if (0 == total_words) {
2052 return;
2053 }
2054 // The first word in the debug output buffer is the number of words that would have
2055 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
2056 // The number of words actually written by the shaders is determined by the size of the buffer
2057 // we provide via the descriptor. So, we process only the number of words that can fit in the
2058 // buffer.
2059 // Each "report" written by the shader instrumentation is considered a "record". This function
2060 // is hard-coded to process only one record because it expects the buffer to be large enough to
2061 // hold only one record. If there is a desire to process more than one record, this function needs
2062 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06002063 std::string validation_message;
2064 std::string stage_message;
2065 std::string common_message;
2066 std::string filename_message;
2067 std::string source_message;
2068 std::string vuid_msg;
2069 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
2070 VkPipeline pipeline_handle = VK_NULL_HANDLE;
2071 std::vector<unsigned int> pgm;
2072 // The first record starts at this offset after the total_words.
2073 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
2074 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
2075 // by the instrumented shader.
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002076 auto it = gpu_validation_state->shader_map.find(debug_record[kInstCommonOutShaderId]);
2077 if (it != gpu_validation_state->shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06002078 shader_module_handle = it->second.shader_module;
2079 pipeline_handle = it->second.pipeline;
2080 pgm = it->second.pgm;
2081 }
2082 GenerateValidationMessage(debug_record, validation_message, vuid_msg);
2083 GenerateStageMessage(debug_record, stage_message);
Jason Macnak67407e72019-07-11 11:05:09 -07002084 GenerateCommonMessage(report_data, cb_node, debug_record, shader_module_handle, pipeline_handle, pipeline_bind_point,
2085 operation_index, common_message);
Karl Schultz7b024b42018-08-30 16:18:18 -06002086 GenerateSourceMessages(pgm, debug_record, filename_message, source_message);
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002087 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, HandleToUint64(queue),
Karl Schultz7b024b42018-08-30 16:18:18 -06002088 vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
2089 filename_message.c_str(), source_message.c_str());
2090 // The debug record at word kInstCommonOutSize is the number of words in the record
2091 // written by the shader. Clear the entire record plus the total_words word at the start.
Tony-LunarG751ebbe2019-07-24 16:41:36 -06002092 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], (uint32_t)kInst2MaxOutCnt);
Karl Schultz7b024b42018-08-30 16:18:18 -06002093 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
2094}
2095
Tony-LunarG5ad17272019-03-05 12:48:24 -07002096// For the given command buffer, map its debug data buffers and read their contents for analysis.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002097void GpuAssisted::ProcessInstrumentationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Petr Kraus6c4bdce2019-08-27 17:35:01 +02002098 if (cb_node && (cb_node->hasDrawCmd || cb_node->hasTraceRaysCmd || cb_node->hasDispatchCmd)) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002099 auto gpu_buffer_list = gpu_validation_state->GetGpuAssistedBufferInfo(cb_node->commandBuffer);
Tony-LunarG5ad17272019-03-05 12:48:24 -07002100 uint32_t draw_index = 0;
Jason Macnak67407e72019-07-11 11:05:09 -07002101 uint32_t compute_index = 0;
2102 uint32_t ray_trace_index = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002103
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002104 for (auto &buffer_info : gpu_buffer_list) {
Petr Kraus6c4bdce2019-08-27 17:35:01 +02002105 char *pData;
2106 VkResult result =
2107 vmaMapMemory(gpu_validation_state->vmaAllocator, buffer_info.output_mem_block.allocation, (void **)&pData);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002108 // Analyze debug output buffer
2109 if (result == VK_SUCCESS) {
Jason Macnak67407e72019-07-11 11:05:09 -07002110 uint32_t operation_index = 0;
2111 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
2112 operation_index = draw_index;
2113 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
2114 operation_index = compute_index;
2115 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
2116 operation_index = ray_trace_index;
2117 } else {
2118 assert(false);
2119 }
2120
2121 AnalyzeAndReportError(cb_node, queue, buffer_info.pipeline_bind_point, operation_index, (uint32_t *)pData);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002122 vmaUnmapMemory(gpu_validation_state->vmaAllocator, buffer_info.output_mem_block.allocation);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002123 }
Jason Macnak67407e72019-07-11 11:05:09 -07002124
2125 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
2126 draw_index++;
2127 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
2128 compute_index++;
2129 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
2130 ray_trace_index++;
2131 } else {
2132 assert(false);
2133 }
Karl Schultz7b024b42018-08-30 16:18:18 -06002134 }
2135 }
2136}
2137
Tony-LunarG81efe392019-03-07 15:43:27 -07002138// 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 -06002139void GpuAssisted::UpdateInstrumentationBuffer(CMD_BUFFER_STATE *cb_node) {
2140 auto gpu_buffer_list = gpu_validation_state->GetGpuAssistedBufferInfo(cb_node->commandBuffer);
Tony-LunarG81efe392019-03-07 15:43:27 -07002141 uint32_t *pData;
2142 for (auto &buffer_info : gpu_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002143 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002144 VkResult result =
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002145 vmaMapMemory(gpu_validation_state->vmaAllocator, buffer_info.di_input_mem_block.allocation, (void **)&pData);
Tony-LunarG81efe392019-03-07 15:43:27 -07002146 if (result == VK_SUCCESS) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002147 for (auto update : buffer_info.di_input_mem_block.update_at_submit) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002148 if (update.second->updated) pData[update.first] = 1;
2149 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002150 vmaUnmapMemory(gpu_validation_state->vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07002151 }
2152 }
2153 }
2154}
2155
Karl Schultz58674242019-01-22 15:35:02 -07002156// Submit a memory barrier on graphics queues.
2157// Lazy-create and record the needed command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002158void GpuAssisted::SubmitBarrier(VkQueue queue) {
Jason Macnak8eae5722019-07-17 15:17:45 -07002159 auto queue_barrier_command_info_it =
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002160 gpu_validation_state->queue_barrier_command_infos.emplace(queue, GpuAssistedQueueBarrierCommandInfo{});
Jason Macnak8eae5722019-07-17 15:17:45 -07002161 if (queue_barrier_command_info_it.second) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002162 GpuAssistedQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_it.first->second;
Karl Schultz58674242019-01-22 15:35:02 -07002163
Jason Macnak8eae5722019-07-17 15:17:45 -07002164 uint32_t queue_family_index = 0;
Karl Schultz58674242019-01-22 15:35:02 -07002165
Jason Macnak8eae5722019-07-17 15:17:45 -07002166 auto queue_state_it = queueMap.find(queue);
2167 if (queue_state_it != queueMap.end()) {
2168 queue_family_index = queue_state_it->second.queueFamilyIndex;
2169 }
Karl Schultz58674242019-01-22 15:35:02 -07002170
Jason Macnak8eae5722019-07-17 15:17:45 -07002171 VkResult result = VK_SUCCESS;
2172
Karl Schultz58674242019-01-22 15:35:02 -07002173 VkCommandPoolCreateInfo pool_create_info = {};
2174 pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
2175 pool_create_info.queueFamilyIndex = queue_family_index;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002176 result = DispatchCreateCommandPool(device, &pool_create_info, nullptr, &queue_barrier_command_info.barrier_command_pool);
Karl Schultz58674242019-01-22 15:35:02 -07002177 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002178 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz58674242019-01-22 15:35:02 -07002179 "Unable to create command pool for barrier CB.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002180 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
Karl Schultz58674242019-01-22 15:35:02 -07002181 return;
2182 }
2183
Jason Macnak8eae5722019-07-17 15:17:45 -07002184 VkCommandBufferAllocateInfo buffer_alloc_info = {};
2185 buffer_alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002186 buffer_alloc_info.commandPool = queue_barrier_command_info.barrier_command_pool;
Jason Macnak8eae5722019-07-17 15:17:45 -07002187 buffer_alloc_info.commandBufferCount = 1;
2188 buffer_alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002189 result = DispatchAllocateCommandBuffers(device, &buffer_alloc_info, &queue_barrier_command_info.barrier_command_buffer);
Karl Schultz58674242019-01-22 15:35:02 -07002190 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002191 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz58674242019-01-22 15:35:02 -07002192 "Unable to create barrier command buffer.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002193 DispatchDestroyCommandPool(device, queue_barrier_command_info.barrier_command_pool, nullptr);
2194 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
2195 queue_barrier_command_info.barrier_command_buffer = VK_NULL_HANDLE;
Karl Schultz58674242019-01-22 15:35:02 -07002196 return;
2197 }
2198
2199 // Hook up command buffer dispatch
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002200 gpu_validation_state->vkSetDeviceLoaderData(device, queue_barrier_command_info.barrier_command_buffer);
Karl Schultz58674242019-01-22 15:35:02 -07002201
2202 // Record a global memory barrier to force availability of device memory operations to the host domain.
2203 VkCommandBufferBeginInfo command_buffer_begin_info = {};
2204 command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002205 result = DispatchBeginCommandBuffer(queue_barrier_command_info.barrier_command_buffer, &command_buffer_begin_info);
Karl Schultz58674242019-01-22 15:35:02 -07002206 if (result == VK_SUCCESS) {
2207 VkMemoryBarrier memory_barrier = {};
2208 memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2209 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
2210 memory_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
2211
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002212 DispatchCmdPipelineBarrier(queue_barrier_command_info.barrier_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
Mark Lobodzinskie514d1a2019-03-12 08:47:45 -06002213 VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &memory_barrier, 0, nullptr, 0, nullptr);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002214 DispatchEndCommandBuffer(queue_barrier_command_info.barrier_command_buffer);
Karl Schultz58674242019-01-22 15:35:02 -07002215 }
2216 }
2217
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002218 GpuAssistedQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_it.first->second;
2219 if (queue_barrier_command_info.barrier_command_buffer != VK_NULL_HANDLE) {
Karl Schultz58674242019-01-22 15:35:02 -07002220 VkSubmitInfo submit_info = {};
2221 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2222 submit_info.commandBufferCount = 1;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002223 submit_info.pCommandBuffers = &queue_barrier_command_info.barrier_command_buffer;
Tony-LunarG152a88b2019-03-20 15:42:24 -06002224 DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
Karl Schultz58674242019-01-22 15:35:02 -07002225 }
2226}
2227
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002228void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002229 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
2230 const VkSubmitInfo *submit = &pSubmits[submit_idx];
2231 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06002232 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07002233 UpdateInstrumentationBuffer(cb_node);
2234 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
2235 UpdateInstrumentationBuffer(secondaryCmdBuffer);
2236 }
2237 }
2238 }
2239}
2240
Karl Schultz58674242019-01-22 15:35:02 -07002241// Issue a memory barrier to make GPU-written data available to host.
2242// Wait for the queue to complete execution.
2243// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002244void GpuAssisted::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
2245 VkResult result) {
2246 StateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
2247
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002248 if (gpu_validation_state->aborted) return;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06002249 bool buffers_present = false;
2250 // Don't QueueWaitIdle if there's nothing to process
2251 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
2252 const VkSubmitInfo *submit = &pSubmits[submit_idx];
2253 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
2254 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002255 if (gpu_validation_state->GetGpuAssistedBufferInfo(cb_node->commandBuffer).size() ||
2256 cb_node->hasBuildAccelerationStructureCmd)
Jason Macnak83cfd582019-07-31 10:14:24 -07002257 buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06002258 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002259 if (gpu_validation_state->GetGpuAssistedBufferInfo(secondaryCmdBuffer->commandBuffer).size() ||
Jason Macnak83cfd582019-07-31 10:14:24 -07002260 cb_node->hasBuildAccelerationStructureCmd)
2261 buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06002262 }
2263 }
2264 }
2265 if (!buffers_present) return;
Karl Schultz58674242019-01-22 15:35:02 -07002266
Mark Lobodzinskie377ac32019-03-07 16:12:46 -07002267 SubmitBarrier(queue);
Karl Schultz58674242019-01-22 15:35:02 -07002268
Tony-LunarG152a88b2019-03-20 15:42:24 -06002269 DispatchQueueWaitIdle(queue);
Karl Schultz58674242019-01-22 15:35:02 -07002270
Karl Schultz7b024b42018-08-30 16:18:18 -06002271 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
2272 const VkSubmitInfo *submit = &pSubmits[submit_idx];
2273 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06002274 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Mark Lobodzinskie377ac32019-03-07 16:12:46 -07002275 ProcessInstrumentationBuffer(queue, cb_node);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002276 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06002277 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Mark Lobodzinskie377ac32019-03-07 16:12:46 -07002278 ProcessInstrumentationBuffer(queue, secondaryCmdBuffer);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002279 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06002280 }
2281 }
2282 }
2283}
Tony-LunarGb2501d22019-01-28 09:59:13 -07002284
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002285void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
2286 uint32_t firstVertex, uint32_t firstInstance) {
2287 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2288}
2289
2290void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
2291 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
2292 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2293}
2294
2295void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
2296 uint32_t stride) {
2297 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2298}
2299
2300void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
2301 uint32_t count, uint32_t stride) {
2302 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2303}
2304
2305void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
2306 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
2307}
2308
2309void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
2310 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
2311}
2312
2313void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
2314 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
2315 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
2316 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
2317 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
2318 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
2319 uint32_t width, uint32_t height, uint32_t depth) {
2320 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
2321}
2322
2323void GpuAssisted::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
2324 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
2325 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
2326 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
2327 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
2328 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
2329 uint32_t width, uint32_t height, uint32_t depth) {
2330 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
2331 cb_state->hasTraceRaysCmd = true;
2332}
2333
2334void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Jason Macnak67407e72019-07-11 11:05:09 -07002335 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
2336 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
andreygca287f22019-04-10 00:15:33 +03002337 return;
2338 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002339 VkResult result;
2340
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002341 if (gpu_validation_state->aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002342
2343 std::vector<VkDescriptorSet> desc_sets;
2344 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002345 result = gpu_validation_state->desc_set_manager->GetDescriptorSets(1, &desc_pool, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002346 assert(result == VK_SUCCESS);
2347 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002348 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Tony-LunarGb2501d22019-01-28 09:59:13 -07002349 "Unable to allocate descriptor sets. Device could become unstable.");
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002350 gpu_validation_state->aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002351 return;
2352 }
2353
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002354 VkDescriptorBufferInfo output_desc_buffer_info = {};
2355 output_desc_buffer_info.range = gpu_validation_state->output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002356
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06002357 auto cb_node = GetCBState(cmd_buffer);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002358 if (!cb_node) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002359 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device), "Unrecognized command buffer");
2360 gpu_validation_state->aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002361 return;
2362 }
2363
Tony-LunarG81efe392019-03-07 15:43:27 -07002364 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002365 GpuAssistedDeviceMemoryBlock output_block = {};
Tony-LunarG0e564722019-03-19 16:09:14 -06002366 VkBufferCreateInfo bufferInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
2367 bufferInfo.size = gpu_validation_state->output_buffer_size;
2368 bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
2369 VmaAllocationCreateInfo allocInfo = {};
2370 allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002371 result = vmaCreateBuffer(gpu_validation_state->vmaAllocator, &bufferInfo, &allocInfo, &output_block.buffer,
2372 &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002373 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002374 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Tony-LunarGb2501d22019-01-28 09:59:13 -07002375 "Unable to allocate device memory. Device could become unstable.");
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002376 gpu_validation_state->aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002377 return;
2378 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002379
Tony-LunarG81efe392019-03-07 15:43:27 -07002380 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGa77cade2019-03-06 10:49:22 -07002381 uint32_t *pData;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002382 result = vmaMapMemory(gpu_validation_state->vmaAllocator, output_block.allocation, (void **)&pData);
Tony-LunarG0e564722019-03-19 16:09:14 -06002383 if (result == VK_SUCCESS) {
2384 memset(pData, 0, gpu_validation_state->output_buffer_size);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002385 vmaUnmapMemory(gpu_validation_state->vmaAllocator, output_block.allocation);
2386 }
Tony-LunarG81efe392019-03-07 15:43:27 -07002387
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002388 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002389 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
2390 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
2391 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002392 uint32_t desc_count = 1;
2393 auto const &state = cb_node->lastBound[bind_point];
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002394 uint32_t number_of_sets = (uint32_t)state.per_set.size();
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002395
Tony-LunarG81efe392019-03-07 15:43:27 -07002396 // Figure out how much memory we need for the input block based on how many sets and bindings there are
2397 // and how big each of the bindings is
Mark Lobodzinskif45e45f2019-04-19 14:15:39 -06002398 if (number_of_sets > 0 && device_extensions.vk_ext_descriptor_indexing) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002399 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
2400 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002401 for (auto s : state.per_set) {
2402 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06002403 if (desc && (desc->GetBindingCount() > 0)) {
2404 auto bindings = desc->GetLayout()->GetSortedBindingSet();
Tony-LunarGa77cade2019-03-06 10:49:22 -07002405 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
2406 for (auto binding : bindings) {
Tony-LunarG7564b382019-08-21 10:11:35 -06002407 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2408 // blocks
2409 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2410 descriptor_count++;
2411 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
2412 VK_NULL_HANDLE, "UNASSIGNED-GPU-Assisted Validation Warning",
2413 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
2414 "validation");
2415 } else if (binding == desc->GetLayout()->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002416 descriptor_count += desc->GetVariableDescriptorCount();
2417 } else {
2418 descriptor_count += desc->GetDescriptorCountFromBinding(binding);
2419 }
2420 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002421 }
2422 }
2423
Tony-LunarGa77cade2019-03-06 10:49:22 -07002424 // Note that the size of the input buffer is dependent on the maximum binding number, which
2425 // can be very large. This is because for (set = s, binding = b, index = i), the validation
2426 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
2427 // see if descriptors have been written. In gpu_validation.md, we note this and advise
2428 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
2429 uint32_t words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002430 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2431 bufferInfo.size = words_needed * 4;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002432 result = vmaCreateBuffer(gpu_validation_state->vmaAllocator, &bufferInfo, &allocInfo, &di_input_block.buffer,
2433 &di_input_block.allocation, nullptr);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002434 if (result != VK_SUCCESS) {
2435 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
2436 "Unable to allocate device memory. Device could become unstable.");
2437 gpu_validation_state->aborted = true;
2438 return;
2439 }
2440
Tony-LunarGa77cade2019-03-06 10:49:22 -07002441 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
2442 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
2443 // outline of the input buffer format
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002444 result = vmaMapMemory(gpu_validation_state->vmaAllocator, di_input_block.allocation, (void **)&pData);
Tony-LunarG76cdcac2019-05-22 16:13:12 -06002445 memset(pData, 0, static_cast<size_t>(bufferInfo.size));
Tony-LunarGa77cade2019-03-06 10:49:22 -07002446 // Pointer to a sets array that points into the sizes array
2447 uint32_t *sets_to_sizes = pData + 1;
2448 // Pointer to the sizes array that contains the array size of the descriptor at each binding
2449 uint32_t *sizes = sets_to_sizes + number_of_sets;
2450 // Pointer to another sets array that points into the bindings array that points into the written array
2451 uint32_t *sets_to_bindings = sizes + binding_count;
2452 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
2453 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
2454 // Index of the next entry in the written array to be updated
2455 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002456 uint32_t bindCounter = number_of_sets + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07002457 // Index of the start of the sets_to_bindings array
2458 pData[0] = number_of_sets + binding_count + 1;
2459
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002460 for (auto s : state.per_set) {
2461 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06002462 if (desc && (desc->GetBindingCount() > 0)) {
2463 auto layout = desc->GetLayout();
2464 auto bindings = layout->GetSortedBindingSet();
Tony-LunarG81efe392019-03-07 15:43:27 -07002465 // For each set, fill in index of its bindings sizes in the sizes array
Tony-LunarGa77cade2019-03-06 10:49:22 -07002466 *sets_to_sizes++ = bindCounter;
Tony-LunarG81efe392019-03-07 15:43:27 -07002467 // For each set, fill in the index of its bindings in the bindings_to_written array
Tony-LunarGa77cade2019-03-06 10:49:22 -07002468 *sets_to_bindings++ = bindCounter + number_of_sets + binding_count;
Tony-LunarG81efe392019-03-07 15:43:27 -07002469 for (auto binding : bindings) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002470 // For each binding, fill in its size in the sizes array
Tony-LunarG7564b382019-08-21 10:11:35 -06002471 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2472 // blocks
2473 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2474 sizes[binding] = 1;
2475 } else if (binding == layout->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002476 sizes[binding] = desc->GetVariableDescriptorCount();
2477 } else {
2478 sizes[binding] = desc->GetDescriptorCountFromBinding(binding);
2479 }
2480 // Fill in the starting index for this binding in the written array in the bindings_to_written array
2481 bindings_to_written[binding] = written_index;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002482
Tony-LunarG7564b382019-08-21 10:11:35 -06002483 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2484 // blocks
2485 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2486 pData[written_index++] = 1;
2487 continue;
2488 }
2489
Tony-LunarGa77cade2019-03-06 10:49:22 -07002490 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
2491 // For each array element in the binding, update the written array with whether it has been written
2492 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
2493 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
Tony-LunarG81efe392019-03-07 15:43:27 -07002494 if (descriptor->updated) {
2495 pData[written_index] = 1;
2496 } else if (desc->IsUpdateAfterBind(binding)) {
2497 // 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 -06002498 di_input_block.update_at_submit[written_index] = descriptor;
Tony-LunarG81efe392019-03-07 15:43:27 -07002499 }
Tony-LunarGa77cade2019-03-06 10:49:22 -07002500 written_index++;
2501 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002502 }
Tony-LunarG81efe392019-03-07 15:43:27 -07002503 auto last = desc->GetLayout()->GetMaxBinding();
2504 bindings_to_written += last + 1;
2505 bindCounter += last + 1;
2506 sizes += last + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07002507 } else {
2508 *sets_to_sizes++ = 0;
2509 *sets_to_bindings++ = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002510 }
2511 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002512 vmaUnmapMemory(gpu_validation_state->vmaAllocator, di_input_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002513
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002514 di_input_desc_buffer_info.range = (words_needed * 4);
2515 di_input_desc_buffer_info.buffer = di_input_block.buffer;
2516 di_input_desc_buffer_info.offset = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002517
2518 desc_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2519 desc_writes[1].dstBinding = 1;
2520 desc_writes[1].descriptorCount = 1;
2521 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002522 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002523 desc_writes[1].dstSet = desc_sets[0];
2524
2525 desc_count = 2;
Tony-LunarG0e564722019-03-19 16:09:14 -06002526 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002527
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002528 if (number_of_sets > 0 && device_extensions.vk_ext_buffer_device_address && gpu_validation_state->buffer_map.size() &&
2529 gpu_validation_state->shaderInt64) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002530 // Example BDA input buffer assuming 2 buffers using BDA:
2531 // Word 0 | Index of start of buffer sizes (in this case 5)
2532 // Word 1 | 0x0000000000000000
2533 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
2534 // Word 3 | Device Address of second buffer
2535 // Word 4 | 0xffffffffffffffff
2536 // Word 5 | 0 (size of pretend buffer at word 1)
2537 // Word 6 | Size in bytes of first buffer
2538 // Word 7 | Size in bytes of second buffer
2539 // Word 8 | 0 (size of pretend buffer in word 4)
2540
2541 uint32_t num_buffers = static_cast<uint32_t>(gpu_validation_state->buffer_map.size());
2542 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
2543 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2544 bufferInfo.size = words_needed * 8; // 64 bit words
2545 result = vmaCreateBuffer(gpu_validation_state->vmaAllocator, &bufferInfo, &allocInfo, &bda_input_block.buffer,
2546 &bda_input_block.allocation, nullptr);
2547 if (result != VK_SUCCESS) {
2548 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
2549 "Unable to allocate device memory. Device could become unstable.");
2550 gpu_validation_state->aborted = true;
2551 return;
2552 }
2553 uint64_t *bda_data;
2554 result = vmaMapMemory(gpu_validation_state->vmaAllocator, bda_input_block.allocation, (void **)&bda_data);
2555 uint32_t address_index = 1;
2556 uint32_t size_index = 3 + num_buffers;
2557 memset(bda_data, 0, static_cast<size_t>(bufferInfo.size));
2558 bda_data[0] = size_index; // Start of buffer sizes
2559 bda_data[address_index++] = 0; // NULL address
2560 bda_data[size_index++] = 0;
2561
2562 for (auto const &value : gpu_validation_state->buffer_map) {
2563 bda_data[address_index++] = value.first;
2564 bda_data[size_index++] = value.second;
2565 }
2566 bda_data[address_index] = UINTPTR_MAX;
2567 bda_data[size_index] = 0;
2568 vmaUnmapMemory(gpu_validation_state->vmaAllocator, bda_input_block.allocation);
2569
2570 bda_input_desc_buffer_info.range = (words_needed * 8);
2571 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
2572 bda_input_desc_buffer_info.offset = 0;
2573
2574 desc_writes[desc_count].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2575 desc_writes[desc_count].dstBinding = 2;
2576 desc_writes[desc_count].descriptorCount = 1;
2577 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2578 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
2579 desc_writes[desc_count].dstSet = desc_sets[0];
2580 desc_count++;
2581 }
2582
Tony-LunarGb2501d22019-01-28 09:59:13 -07002583 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002584 output_desc_buffer_info.buffer = output_block.buffer;
2585 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002586
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002587 desc_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2588 desc_writes[0].descriptorCount = 1;
2589 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2590 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
2591 desc_writes[0].dstSet = desc_sets[0];
2592 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002593
andreyg25ce2622019-04-05 23:07:59 +03002594 auto iter = cb_node->lastBound.find(bind_point); // find() allows read-only access to cb_state
Tony-LunarGb2501d22019-01-28 09:59:13 -07002595 if (iter != cb_node->lastBound.end()) {
2596 auto pipeline_state = iter->second.pipeline_state;
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002597 if (pipeline_state && (pipeline_state->pipeline_layout.set_layouts.size() <= gpu_validation_state->desc_set_bind_index)) {
Jason Macnak67407e72019-07-11 11:05:09 -07002598 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout.layout,
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002599 gpu_validation_state->desc_set_bind_index, 1, desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002600 }
Tony-LunarG0e564722019-03-19 16:09:14 -06002601 // Record buffer and memory info in CB state tracking
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002602 gpu_validation_state->GetGpuAssistedBufferInfo(cmd_buffer)
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002603 .emplace_back(output_block, di_input_block, bda_input_block, desc_sets[0], desc_pool, bind_point);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002604 } else {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002605 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device), "Unable to find pipeline state");
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002606 vmaDestroyBuffer(gpu_validation_state->vmaAllocator, di_input_block.buffer, di_input_block.allocation);
2607 vmaDestroyBuffer(gpu_validation_state->vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002608 vmaDestroyBuffer(gpu_validation_state->vmaAllocator, output_block.buffer, output_block.allocation);
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002609 gpu_validation_state->aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002610 return;
2611 }
2612}