blob: cfb2f06a03bb41a7aef37a8be21f9ba7fe4f8df9 [file] [log] [blame]
Mark Lobodzinski103c58a2020-01-29 13:20:00 -07001/* Copyright (c) 2018-2020 The Khronos Group Inc.
2 * Copyright (c) 2018-2020 Valve Corporation
3 * Copyright (c) 2018-2020 LunarG, Inc.
Karl Schultz7b024b42018-08-30 16:18:18 -06004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060017 * Author: Karl Schultz <karl@lunarg.com>
18 * Author: Tony Barbour <tony@lunarg.com>
Karl Schultz7b024b42018-08-30 16:18:18 -060019 */
20
Tony-LunarG0e564722019-03-19 16:09:14 -060021// This define indicates to build the VMA routines themselves
22#define VMA_IMPLEMENTATION
23// This define indicates that we will supply Vulkan function pointers at initialization
24#define VMA_STATIC_VULKAN_FUNCTIONS 0
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -070025#include "gpu_validation.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060026#include "shader_validation.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060027#include "spirv-tools/libspirv.h"
28#include "spirv-tools/optimizer.hpp"
29#include "spirv-tools/instrument.hpp"
30#include <SPIRV/spirv.hpp>
31#include <algorithm>
32#include <regex>
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060033#include "layer_chassis_dispatch.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060034
35// This is the number of bindings in the debug descriptor set.
Tony-LunarG8eb5a002019-07-25 16:49:00 -060036static const uint32_t kNumBindingsInSet = 3;
Karl Schultz7b024b42018-08-30 16:18:18 -060037
Jason Macnak67407e72019-07-11 11:05:09 -070038static const VkShaderStageFlags kShaderStageAllRayTracing =
39 VK_SHADER_STAGE_ANY_HIT_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV | VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV |
40 VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV | VK_SHADER_STAGE_RAYGEN_BIT_NV;
41
Jason Macnak83cfd582019-07-31 10:14:24 -070042// Keep in sync with the GLSL shader below.
43struct GpuAccelerationStructureBuildValidationBuffer {
44 uint32_t instances_to_validate;
45 uint32_t replacement_handle_bits_0;
46 uint32_t replacement_handle_bits_1;
47 uint32_t invalid_handle_found;
48 uint32_t invalid_handle_bits_0;
49 uint32_t invalid_handle_bits_1;
50 uint32_t valid_handles_count;
51};
52
53// This is the GLSL source for the compute shader that is used during ray tracing acceleration structure
54// building validation which inspects instance buffers for top level acceleration structure builds and
55// reports and replaces invalid bottom level acceleration structure handles with good bottom level
56// acceleration structure handle so that applications can continue without undefined behavior long enough
57// to report errors.
58//
59// #version 450
60// layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
61// struct VkGeometryInstanceNV {
62// uint unused[14];
63// uint handle_bits_0;
64// uint handle_bits_1;
65// };
66// layout(set=0, binding=0, std430) buffer InstanceBuffer {
67// VkGeometryInstanceNV instances[];
68// };
69// layout(set=0, binding=1, std430) buffer ValidationBuffer {
70// uint instances_to_validate;
71// uint replacement_handle_bits_0;
72// uint replacement_handle_bits_1;
73// uint invalid_handle_found;
74// uint invalid_handle_bits_0;
75// uint invalid_handle_bits_1;
76// uint valid_handles_count;
77// uint valid_handles[];
78// };
79// void main() {
80// for (uint instance_index = 0; instance_index < instances_to_validate; instance_index++) {
81// uint instance_handle_bits_0 = instances[instance_index].handle_bits_0;
82// uint instance_handle_bits_1 = instances[instance_index].handle_bits_1;
83// bool valid = false;
84// for (uint valid_handle_index = 0; valid_handle_index < valid_handles_count; valid_handle_index++) {
85// if (instance_handle_bits_0 == valid_handles[2*valid_handle_index+0] &&
86// instance_handle_bits_1 == valid_handles[2*valid_handle_index+1]) {
87// valid = true;
88// break;
89// }
90// }
91// if (!valid) {
92// invalid_handle_found += 1;
93// invalid_handle_bits_0 = instance_handle_bits_0;
94// invalid_handle_bits_1 = instance_handle_bits_1;
95// instances[instance_index].handle_bits_0 = replacement_handle_bits_0;
96// instances[instance_index].handle_bits_1 = replacement_handle_bits_1;
97// }
98// }
99// }
100//
101// To regenerate the spirv below:
102// 1. Save the above GLSL source to a file called validation_shader.comp.
103// 2. Run in terminal
104//
105// glslangValidator.exe -x -V validation_shader.comp -o validation_shader.comp.spv
106//
107// 4. Copy-paste the contents of validation_shader.comp.spv here (clang-format will fix up the alignment).
108static const uint32_t kComputeShaderSpirv[] = {
109 0x07230203, 0x00010000, 0x00080007, 0x0000006d, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, 0x00000001, 0x4c534c47,
110 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0005000f, 0x00000005, 0x00000004, 0x6e69616d,
111 0x00000000, 0x00060010, 0x00000004, 0x00000011, 0x00000001, 0x00000001, 0x00000001, 0x00030003, 0x00000002, 0x000001c2,
112 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00060005, 0x00000008, 0x74736e69, 0x65636e61, 0x646e695f, 0x00007865,
113 0x00070005, 0x00000011, 0x696c6156, 0x69746164, 0x75426e6f, 0x72656666, 0x00000000, 0x00090006, 0x00000011, 0x00000000,
114 0x74736e69, 0x65636e61, 0x6f745f73, 0x6c61765f, 0x74616469, 0x00000065, 0x000a0006, 0x00000011, 0x00000001, 0x6c706572,
115 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x000a0006, 0x00000011, 0x00000002, 0x6c706572,
116 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00090006, 0x00000011, 0x00000003, 0x61766e69,
117 0x5f64696c, 0x646e6168, 0x665f656c, 0x646e756f, 0x00000000, 0x00090006, 0x00000011, 0x00000004, 0x61766e69, 0x5f64696c,
118 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00090006, 0x00000011, 0x00000005, 0x61766e69, 0x5f64696c, 0x646e6168,
119 0x625f656c, 0x5f737469, 0x00000031, 0x00080006, 0x00000011, 0x00000006, 0x696c6176, 0x61685f64, 0x656c646e, 0x6f635f73,
120 0x00746e75, 0x00070006, 0x00000011, 0x00000007, 0x696c6176, 0x61685f64, 0x656c646e, 0x00000073, 0x00030005, 0x00000013,
121 0x00000000, 0x00080005, 0x0000001b, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000305f, 0x00080005,
122 0x0000001e, 0x65476b56, 0x74656d6f, 0x6e497972, 0x6e617473, 0x564e6563, 0x00000000, 0x00050006, 0x0000001e, 0x00000000,
123 0x73756e75, 0x00006465, 0x00070006, 0x0000001e, 0x00000001, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00070006,
124 0x0000001e, 0x00000002, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00060005, 0x00000020, 0x74736e49, 0x65636e61,
125 0x66667542, 0x00007265, 0x00060006, 0x00000020, 0x00000000, 0x74736e69, 0x65636e61, 0x00000073, 0x00030005, 0x00000022,
126 0x00000000, 0x00080005, 0x00000027, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000315f, 0x00040005,
127 0x0000002d, 0x696c6176, 0x00000064, 0x00070005, 0x0000002f, 0x696c6176, 0x61685f64, 0x656c646e, 0x646e695f, 0x00007865,
128 0x00040047, 0x00000010, 0x00000006, 0x00000004, 0x00050048, 0x00000011, 0x00000000, 0x00000023, 0x00000000, 0x00050048,
129 0x00000011, 0x00000001, 0x00000023, 0x00000004, 0x00050048, 0x00000011, 0x00000002, 0x00000023, 0x00000008, 0x00050048,
130 0x00000011, 0x00000003, 0x00000023, 0x0000000c, 0x00050048, 0x00000011, 0x00000004, 0x00000023, 0x00000010, 0x00050048,
131 0x00000011, 0x00000005, 0x00000023, 0x00000014, 0x00050048, 0x00000011, 0x00000006, 0x00000023, 0x00000018, 0x00050048,
132 0x00000011, 0x00000007, 0x00000023, 0x0000001c, 0x00030047, 0x00000011, 0x00000003, 0x00040047, 0x00000013, 0x00000022,
133 0x00000000, 0x00040047, 0x00000013, 0x00000021, 0x00000001, 0x00040047, 0x0000001d, 0x00000006, 0x00000004, 0x00050048,
134 0x0000001e, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x0000001e, 0x00000001, 0x00000023, 0x00000038, 0x00050048,
135 0x0000001e, 0x00000002, 0x00000023, 0x0000003c, 0x00040047, 0x0000001f, 0x00000006, 0x00000040, 0x00050048, 0x00000020,
136 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x00000020, 0x00000003, 0x00040047, 0x00000022, 0x00000022, 0x00000000,
137 0x00040047, 0x00000022, 0x00000021, 0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00040015,
138 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, 0x00000006, 0x0004002b, 0x00000006, 0x00000009,
139 0x00000000, 0x0003001d, 0x00000010, 0x00000006, 0x000a001e, 0x00000011, 0x00000006, 0x00000006, 0x00000006, 0x00000006,
140 0x00000006, 0x00000006, 0x00000006, 0x00000010, 0x00040020, 0x00000012, 0x00000002, 0x00000011, 0x0004003b, 0x00000012,
141 0x00000013, 0x00000002, 0x00040015, 0x00000014, 0x00000020, 0x00000001, 0x0004002b, 0x00000014, 0x00000015, 0x00000000,
142 0x00040020, 0x00000016, 0x00000002, 0x00000006, 0x00020014, 0x00000019, 0x0004002b, 0x00000006, 0x0000001c, 0x0000000e,
143 0x0004001c, 0x0000001d, 0x00000006, 0x0000001c, 0x0005001e, 0x0000001e, 0x0000001d, 0x00000006, 0x00000006, 0x0003001d,
144 0x0000001f, 0x0000001e, 0x0003001e, 0x00000020, 0x0000001f, 0x00040020, 0x00000021, 0x00000002, 0x00000020, 0x0004003b,
145 0x00000021, 0x00000022, 0x00000002, 0x0004002b, 0x00000014, 0x00000024, 0x00000001, 0x0004002b, 0x00000014, 0x00000029,
146 0x00000002, 0x00040020, 0x0000002c, 0x00000007, 0x00000019, 0x0003002a, 0x00000019, 0x0000002e, 0x0004002b, 0x00000014,
147 0x00000036, 0x00000006, 0x0004002b, 0x00000014, 0x0000003b, 0x00000007, 0x0004002b, 0x00000006, 0x0000003c, 0x00000002,
148 0x0004002b, 0x00000006, 0x00000048, 0x00000001, 0x00030029, 0x00000019, 0x00000050, 0x0004002b, 0x00000014, 0x00000058,
149 0x00000003, 0x0004002b, 0x00000014, 0x0000005d, 0x00000004, 0x0004002b, 0x00000014, 0x00000060, 0x00000005, 0x00050036,
150 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007,
151 0x0004003b, 0x00000007, 0x0000001b, 0x00000007, 0x0004003b, 0x00000007, 0x00000027, 0x00000007, 0x0004003b, 0x0000002c,
152 0x0000002d, 0x00000007, 0x0004003b, 0x00000007, 0x0000002f, 0x00000007, 0x0003003e, 0x00000008, 0x00000009, 0x000200f9,
153 0x0000000a, 0x000200f8, 0x0000000a, 0x000400f6, 0x0000000c, 0x0000000d, 0x00000000, 0x000200f9, 0x0000000e, 0x000200f8,
154 0x0000000e, 0x0004003d, 0x00000006, 0x0000000f, 0x00000008, 0x00050041, 0x00000016, 0x00000017, 0x00000013, 0x00000015,
155 0x0004003d, 0x00000006, 0x00000018, 0x00000017, 0x000500b0, 0x00000019, 0x0000001a, 0x0000000f, 0x00000018, 0x000400fa,
156 0x0000001a, 0x0000000b, 0x0000000c, 0x000200f8, 0x0000000b, 0x0004003d, 0x00000006, 0x00000023, 0x00000008, 0x00070041,
157 0x00000016, 0x00000025, 0x00000022, 0x00000015, 0x00000023, 0x00000024, 0x0004003d, 0x00000006, 0x00000026, 0x00000025,
158 0x0003003e, 0x0000001b, 0x00000026, 0x0004003d, 0x00000006, 0x00000028, 0x00000008, 0x00070041, 0x00000016, 0x0000002a,
159 0x00000022, 0x00000015, 0x00000028, 0x00000029, 0x0004003d, 0x00000006, 0x0000002b, 0x0000002a, 0x0003003e, 0x00000027,
160 0x0000002b, 0x0003003e, 0x0000002d, 0x0000002e, 0x0003003e, 0x0000002f, 0x00000009, 0x000200f9, 0x00000030, 0x000200f8,
161 0x00000030, 0x000400f6, 0x00000032, 0x00000033, 0x00000000, 0x000200f9, 0x00000034, 0x000200f8, 0x00000034, 0x0004003d,
162 0x00000006, 0x00000035, 0x0000002f, 0x00050041, 0x00000016, 0x00000037, 0x00000013, 0x00000036, 0x0004003d, 0x00000006,
163 0x00000038, 0x00000037, 0x000500b0, 0x00000019, 0x00000039, 0x00000035, 0x00000038, 0x000400fa, 0x00000039, 0x00000031,
164 0x00000032, 0x000200f8, 0x00000031, 0x0004003d, 0x00000006, 0x0000003a, 0x0000001b, 0x0004003d, 0x00000006, 0x0000003d,
165 0x0000002f, 0x00050084, 0x00000006, 0x0000003e, 0x0000003c, 0x0000003d, 0x00050080, 0x00000006, 0x0000003f, 0x0000003e,
166 0x00000009, 0x00060041, 0x00000016, 0x00000040, 0x00000013, 0x0000003b, 0x0000003f, 0x0004003d, 0x00000006, 0x00000041,
167 0x00000040, 0x000500aa, 0x00000019, 0x00000042, 0x0000003a, 0x00000041, 0x000300f7, 0x00000044, 0x00000000, 0x000400fa,
168 0x00000042, 0x00000043, 0x00000044, 0x000200f8, 0x00000043, 0x0004003d, 0x00000006, 0x00000045, 0x00000027, 0x0004003d,
169 0x00000006, 0x00000046, 0x0000002f, 0x00050084, 0x00000006, 0x00000047, 0x0000003c, 0x00000046, 0x00050080, 0x00000006,
170 0x00000049, 0x00000047, 0x00000048, 0x00060041, 0x00000016, 0x0000004a, 0x00000013, 0x0000003b, 0x00000049, 0x0004003d,
171 0x00000006, 0x0000004b, 0x0000004a, 0x000500aa, 0x00000019, 0x0000004c, 0x00000045, 0x0000004b, 0x000200f9, 0x00000044,
172 0x000200f8, 0x00000044, 0x000700f5, 0x00000019, 0x0000004d, 0x00000042, 0x00000031, 0x0000004c, 0x00000043, 0x000300f7,
173 0x0000004f, 0x00000000, 0x000400fa, 0x0000004d, 0x0000004e, 0x0000004f, 0x000200f8, 0x0000004e, 0x0003003e, 0x0000002d,
174 0x00000050, 0x000200f9, 0x00000032, 0x000200f8, 0x0000004f, 0x000200f9, 0x00000033, 0x000200f8, 0x00000033, 0x0004003d,
175 0x00000006, 0x00000052, 0x0000002f, 0x00050080, 0x00000006, 0x00000053, 0x00000052, 0x00000024, 0x0003003e, 0x0000002f,
176 0x00000053, 0x000200f9, 0x00000030, 0x000200f8, 0x00000032, 0x0004003d, 0x00000019, 0x00000054, 0x0000002d, 0x000400a8,
177 0x00000019, 0x00000055, 0x00000054, 0x000300f7, 0x00000057, 0x00000000, 0x000400fa, 0x00000055, 0x00000056, 0x00000057,
178 0x000200f8, 0x00000056, 0x00050041, 0x00000016, 0x00000059, 0x00000013, 0x00000058, 0x0004003d, 0x00000006, 0x0000005a,
179 0x00000059, 0x00050080, 0x00000006, 0x0000005b, 0x0000005a, 0x00000048, 0x00050041, 0x00000016, 0x0000005c, 0x00000013,
180 0x00000058, 0x0003003e, 0x0000005c, 0x0000005b, 0x0004003d, 0x00000006, 0x0000005e, 0x0000001b, 0x00050041, 0x00000016,
181 0x0000005f, 0x00000013, 0x0000005d, 0x0003003e, 0x0000005f, 0x0000005e, 0x0004003d, 0x00000006, 0x00000061, 0x00000027,
182 0x00050041, 0x00000016, 0x00000062, 0x00000013, 0x00000060, 0x0003003e, 0x00000062, 0x00000061, 0x0004003d, 0x00000006,
183 0x00000063, 0x00000008, 0x00050041, 0x00000016, 0x00000064, 0x00000013, 0x00000024, 0x0004003d, 0x00000006, 0x00000065,
184 0x00000064, 0x00070041, 0x00000016, 0x00000066, 0x00000022, 0x00000015, 0x00000063, 0x00000024, 0x0003003e, 0x00000066,
185 0x00000065, 0x0004003d, 0x00000006, 0x00000067, 0x00000008, 0x00050041, 0x00000016, 0x00000068, 0x00000013, 0x00000029,
186 0x0004003d, 0x00000006, 0x00000069, 0x00000068, 0x00070041, 0x00000016, 0x0000006a, 0x00000022, 0x00000015, 0x00000067,
187 0x00000029, 0x0003003e, 0x0000006a, 0x00000069, 0x000200f9, 0x00000057, 0x000200f8, 0x00000057, 0x000200f9, 0x0000000d,
188 0x000200f8, 0x0000000d, 0x0004003d, 0x00000006, 0x0000006b, 0x00000008, 0x00050080, 0x00000006, 0x0000006c, 0x0000006b,
189 0x00000024, 0x0003003e, 0x00000008, 0x0000006c, 0x000200f9, 0x0000000a, 0x000200f8, 0x0000000c, 0x000100fd, 0x00010038};
190
Karl Schultz7b024b42018-08-30 16:18:18 -0600191// Implementation for Descriptor Set Manager class
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600192GpuAssistedDescriptorSetManager::GpuAssistedDescriptorSetManager(GpuAssisted *dev_data) { dev_data_ = dev_data; }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700193
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600194GpuAssistedDescriptorSetManager::~GpuAssistedDescriptorSetManager() {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700195 for (auto &pool : desc_pool_map_) {
Tony-LunarG152a88b2019-03-20 15:42:24 -0600196 DispatchDestroyDescriptorPool(dev_data_->device, pool.first, NULL);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700197 }
198 desc_pool_map_.clear();
199}
200
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600201VkResult GpuAssistedDescriptorSetManager::GetDescriptorSet(VkDescriptorPool *desc_pool, VkDescriptorSet *desc_set) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700202 std::vector<VkDescriptorSet> desc_sets;
203 VkResult result = GetDescriptorSets(1, desc_pool, &desc_sets);
204 if (result == VK_SUCCESS) {
205 *desc_set = desc_sets[0];
206 }
207 return result;
208}
209
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600210VkResult GpuAssistedDescriptorSetManager::GetDescriptorSets(uint32_t count, VkDescriptorPool *pool,
211 std::vector<VkDescriptorSet> *desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600212 const uint32_t default_pool_size = kItemsPerChunk;
213 VkResult result = VK_SUCCESS;
214 VkDescriptorPool pool_to_use = VK_NULL_HANDLE;
215
216 if (0 == count) {
217 return result;
218 }
219 desc_sets->clear();
220 desc_sets->resize(count);
221
222 for (auto &pool : desc_pool_map_) {
223 if (pool.second.used + count < pool.second.size) {
224 pool_to_use = pool.first;
225 break;
226 }
227 }
228 if (VK_NULL_HANDLE == pool_to_use) {
229 uint32_t pool_count = default_pool_size;
230 if (count > default_pool_size) {
231 pool_count = count;
232 }
233 const VkDescriptorPoolSize size_counts = {
234 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
235 pool_count * kNumBindingsInSet,
236 };
237 VkDescriptorPoolCreateInfo desc_pool_info = {};
238 desc_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
239 desc_pool_info.pNext = NULL;
240 desc_pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
241 desc_pool_info.maxSets = pool_count;
242 desc_pool_info.poolSizeCount = 1;
243 desc_pool_info.pPoolSizes = &size_counts;
Tony-LunarG152a88b2019-03-20 15:42:24 -0600244 result = DispatchCreateDescriptorPool(dev_data_->device, &desc_pool_info, NULL, &pool_to_use);
Karl Schultz7b024b42018-08-30 16:18:18 -0600245 assert(result == VK_SUCCESS);
246 if (result != VK_SUCCESS) {
247 return result;
248 }
249 desc_pool_map_[pool_to_use].size = desc_pool_info.maxSets;
250 desc_pool_map_[pool_to_use].used = 0;
251 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600252 std::vector<VkDescriptorSetLayout> desc_layouts(count, dev_data_->debug_desc_layout);
Karl Schultz7b024b42018-08-30 16:18:18 -0600253
254 VkDescriptorSetAllocateInfo alloc_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, NULL, pool_to_use, count,
255 desc_layouts.data()};
256
Tony-LunarG152a88b2019-03-20 15:42:24 -0600257 result = DispatchAllocateDescriptorSets(dev_data_->device, &alloc_info, desc_sets->data());
Karl Schultz7b024b42018-08-30 16:18:18 -0600258 assert(result == VK_SUCCESS);
259 if (result != VK_SUCCESS) {
260 return result;
261 }
262 *pool = pool_to_use;
263 desc_pool_map_[pool_to_use].used += count;
264 return result;
265}
266
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600267void GpuAssistedDescriptorSetManager::PutBackDescriptorSet(VkDescriptorPool desc_pool, VkDescriptorSet desc_set) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600268 auto iter = desc_pool_map_.find(desc_pool);
269 if (iter != desc_pool_map_.end()) {
Tony-LunarG152a88b2019-03-20 15:42:24 -0600270 VkResult result = DispatchFreeDescriptorSets(dev_data_->device, desc_pool, 1, &desc_set);
Karl Schultz7b024b42018-08-30 16:18:18 -0600271 assert(result == VK_SUCCESS);
272 if (result != VK_SUCCESS) {
273 return;
274 }
275 desc_pool_map_[desc_pool].used--;
276 if (0 == desc_pool_map_[desc_pool].used) {
Tony-LunarG152a88b2019-03-20 15:42:24 -0600277 DispatchDestroyDescriptorPool(dev_data_->device, desc_pool, NULL);
Karl Schultz7b024b42018-08-30 16:18:18 -0600278 desc_pool_map_.erase(desc_pool);
279 }
280 }
281 return;
282}
283
Tony-LunarG0e564722019-03-19 16:09:14 -0600284// Trampolines to make VMA call Dispatch for Vulkan calls
285static VKAPI_ATTR void VKAPI_CALL gpuVkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
286 VkPhysicalDeviceProperties *pProperties) {
287 DispatchGetPhysicalDeviceProperties(physicalDevice, pProperties);
288}
289static VKAPI_ATTR void VKAPI_CALL gpuVkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
290 VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
291 DispatchGetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
292}
293static VKAPI_ATTR VkResult VKAPI_CALL gpuVkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
294 const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
295 return DispatchAllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
296}
297static VKAPI_ATTR void VKAPI_CALL gpuVkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks *pAllocator) {
298 DispatchFreeMemory(device, memory, pAllocator);
299}
300static VKAPI_ATTR VkResult VKAPI_CALL gpuVkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size,
301 VkMemoryMapFlags flags, void **ppData) {
302 return DispatchMapMemory(device, memory, offset, size, flags, ppData);
303}
304static VKAPI_ATTR void VKAPI_CALL gpuVkUnmapMemory(VkDevice device, VkDeviceMemory memory) { DispatchUnmapMemory(device, memory); }
305static VKAPI_ATTR VkResult VKAPI_CALL gpuVkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
306 const VkMappedMemoryRange *pMemoryRanges) {
307 return DispatchFlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
308}
309static VKAPI_ATTR VkResult VKAPI_CALL gpuVkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
310 const VkMappedMemoryRange *pMemoryRanges) {
311 return DispatchInvalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
312}
313static VKAPI_ATTR VkResult VKAPI_CALL gpuVkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory,
314 VkDeviceSize memoryOffset) {
315 return DispatchBindBufferMemory(device, buffer, memory, memoryOffset);
316}
317static VKAPI_ATTR VkResult VKAPI_CALL gpuVkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory,
318 VkDeviceSize memoryOffset) {
319 return DispatchBindImageMemory(device, image, memory, memoryOffset);
320}
321static VKAPI_ATTR void VKAPI_CALL gpuVkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer,
322 VkMemoryRequirements *pMemoryRequirements) {
323 DispatchGetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
324}
325static VKAPI_ATTR void VKAPI_CALL gpuVkGetImageMemoryRequirements(VkDevice device, VkImage image,
326 VkMemoryRequirements *pMemoryRequirements) {
327 DispatchGetImageMemoryRequirements(device, image, pMemoryRequirements);
328}
329static VKAPI_ATTR VkResult VKAPI_CALL gpuVkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
330 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
331 return DispatchCreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
332}
333static VKAPI_ATTR void VKAPI_CALL gpuVkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
334 return DispatchDestroyBuffer(device, buffer, pAllocator);
335}
336static VKAPI_ATTR VkResult VKAPI_CALL gpuVkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
337 const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
338 return DispatchCreateImage(device, pCreateInfo, pAllocator, pImage);
339}
340static VKAPI_ATTR void VKAPI_CALL gpuVkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
341 DispatchDestroyImage(device, image, pAllocator);
342}
343static VKAPI_ATTR void VKAPI_CALL gpuVkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
344 uint32_t regionCount, const VkBufferCopy *pRegions) {
345 DispatchCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
346}
347
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600348VkResult GpuAssisted::InitializeVma(VkPhysicalDevice physical_device, VkDevice device, VmaAllocator *pAllocator) {
Tony-LunarG0e564722019-03-19 16:09:14 -0600349 VmaVulkanFunctions functions;
350 VmaAllocatorCreateInfo allocatorInfo = {};
351 allocatorInfo.device = device;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600352 allocatorInfo.physicalDevice = physical_device;
Tony-LunarG0e564722019-03-19 16:09:14 -0600353
354 functions.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)gpuVkGetPhysicalDeviceProperties;
355 functions.vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)gpuVkGetPhysicalDeviceMemoryProperties;
356 functions.vkAllocateMemory = (PFN_vkAllocateMemory)gpuVkAllocateMemory;
357 functions.vkFreeMemory = (PFN_vkFreeMemory)gpuVkFreeMemory;
358 functions.vkMapMemory = (PFN_vkMapMemory)gpuVkMapMemory;
359 functions.vkUnmapMemory = (PFN_vkUnmapMemory)gpuVkUnmapMemory;
360 functions.vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)gpuVkFlushMappedMemoryRanges;
361 functions.vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)gpuVkInvalidateMappedMemoryRanges;
362 functions.vkBindBufferMemory = (PFN_vkBindBufferMemory)gpuVkBindBufferMemory;
363 functions.vkBindImageMemory = (PFN_vkBindImageMemory)gpuVkBindImageMemory;
364 functions.vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)gpuVkGetBufferMemoryRequirements;
365 functions.vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)gpuVkGetImageMemoryRequirements;
366 functions.vkCreateBuffer = (PFN_vkCreateBuffer)gpuVkCreateBuffer;
367 functions.vkDestroyBuffer = (PFN_vkDestroyBuffer)gpuVkDestroyBuffer;
368 functions.vkCreateImage = (PFN_vkCreateImage)gpuVkCreateImage;
369 functions.vkDestroyImage = (PFN_vkDestroyImage)gpuVkDestroyImage;
370 functions.vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)gpuVkCmdCopyBuffer;
371 allocatorInfo.pVulkanFunctions = &functions;
372
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600373 return vmaCreateAllocator(&allocatorInfo, pAllocator);
Tony-LunarG0e564722019-03-19 16:09:14 -0600374}
375
Karl Schultz7b024b42018-08-30 16:18:18 -0600376// Convenience function for reporting problems with setting up GPU Validation.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600377void GpuAssisted::ReportSetupProblem(VkDebugReportObjectTypeEXT object_type, uint64_t object_handle,
Jeff Bolz46c0ea02019-10-09 13:06:29 -0500378 const char *const specific_message) const {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700379 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle, "UNASSIGNED-GPU-Assisted Validation Error. ",
380 "Detail: (%s)", specific_message);
Karl Schultz7b024b42018-08-30 16:18:18 -0600381}
382
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600383void GpuAssisted::PreCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
384 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer, void *cb_state_data) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700385 // Ray tracing acceleration structure instance buffers also need the storage buffer usage as
386 // acceleration structure build validation will find and replace invalid acceleration structure
387 // handles inside of a compute shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600388 create_buffer_api_state *cb_state = reinterpret_cast<create_buffer_api_state *>(cb_state_data);
389 if (cb_state && cb_state->modified_create_info.usage & VK_BUFFER_USAGE_RAY_TRACING_BIT_NV) {
390 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
Jason Macnak83cfd582019-07-31 10:14:24 -0700391 }
392}
393
Karl Schultz7b024b42018-08-30 16:18:18 -0600394// Turn on necessary device features.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600395void GpuAssisted::PreCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info,
396 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
397 safe_VkDeviceCreateInfo *modified_create_info) {
398 VkPhysicalDeviceFeatures supported_features;
399 DispatchGetPhysicalDeviceFeatures(gpu, &supported_features);
400 if (supported_features.fragmentStoresAndAtomics || supported_features.vertexPipelineStoresAndAtomics ||
401 supported_features.shaderInt64) {
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600402 VkPhysicalDeviceFeatures *features = nullptr;
Petr Kraus08d51062019-08-21 00:14:16 +0200403 if (modified_create_info->pEnabledFeatures) {
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600404 // If pEnabledFeatures, VkPhysicalDeviceFeatures2 in pNext chain is not allowed
Petr Kraus08d51062019-08-21 00:14:16 +0200405 features = const_cast<VkPhysicalDeviceFeatures *>(modified_create_info->pEnabledFeatures);
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600406 } else {
407 VkPhysicalDeviceFeatures2 *features2 = nullptr;
Petr Kraus08d51062019-08-21 00:14:16 +0200408 features2 =
409 const_cast<VkPhysicalDeviceFeatures2 *>(lvl_find_in_chain<VkPhysicalDeviceFeatures2>(modified_create_info->pNext));
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600410 if (features2) features = &features2->features;
Tony-LunarG48b478a2019-01-15 16:35:22 -0700411 }
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600412 if (features) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600413 features->fragmentStoresAndAtomics = supported_features.fragmentStoresAndAtomics;
414 features->vertexPipelineStoresAndAtomics = supported_features.vertexPipelineStoresAndAtomics;
415 features->shaderInt64 = supported_features.shaderInt64;
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600416 } else {
417 VkPhysicalDeviceFeatures new_features = {};
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600418 new_features.fragmentStoresAndAtomics = supported_features.fragmentStoresAndAtomics;
419 new_features.vertexPipelineStoresAndAtomics = supported_features.vertexPipelineStoresAndAtomics;
420 new_features.shaderInt64 = supported_features.shaderInt64;
Petr Krausbd5b7b22019-08-21 00:12:33 +0200421 delete modified_create_info->pEnabledFeatures;
Petr Kraus08d51062019-08-21 00:14:16 +0200422 modified_create_info->pEnabledFeatures = new VkPhysicalDeviceFeatures(new_features);
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600423 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600424 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600425}
Karl Schultz7b024b42018-08-30 16:18:18 -0600426// Perform initializations that can be done at Create Device time.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600427void GpuAssisted::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
428 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result) {
429 // The state tracker sets up the device state
Tony-LunarG99b880b2019-09-26 11:19:52 -0600430 ValidationStateTracker::PostCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski5dc3dcd2019-04-23 14:26:28 -0600431
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600432 ValidationObject *device_object = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
433 ValidationObject *validation_data = GetValidationObject(device_object->object_dispatch, this->container_type);
434 GpuAssisted *device_gpu_assisted = static_cast<GpuAssisted *>(validation_data);
Tony-LunarG65f9c492019-01-17 14:24:42 -0700435
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600436 if (device_gpu_assisted->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600437 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz7b024b42018-08-30 16:18:18 -0600438 "GPU-Assisted validation requires Vulkan 1.1 or later. GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600439 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600440 return;
441 }
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600442
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600443 if (!device_gpu_assisted->enabled_features.core.fragmentStoresAndAtomics ||
444 !device_gpu_assisted->enabled_features.core.vertexPipelineStoresAndAtomics) {
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600445 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
446 "GPU-Assisted validation requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
447 "GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600448 device_gpu_assisted->aborted = true;
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600449 return;
450 }
451
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700452 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) &&
453 !device_gpu_assisted->enabled_features.core.shaderInt64) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600454 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
455 "UNASSIGNED-GPU-Assisted Validation Warning",
456 "shaderInt64 feature is not available. No buffer device address checking will be attempted");
457 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600458 device_gpu_assisted->shaderInt64 = device_gpu_assisted->enabled_features.core.shaderInt64;
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600459
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600460 // If api version 1.1 or later, SetDeviceLoaderData will be in the loader
461 auto chain_info = get_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK);
462 assert(chain_info->u.pfnSetDeviceLoaderData);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600463 device_gpu_assisted->vkSetDeviceLoaderData = chain_info->u.pfnSetDeviceLoaderData;
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600464
Karl Schultz7b024b42018-08-30 16:18:18 -0600465 // Some devices have extremely high limits here, so set a reasonable max because we have to pad
466 // the pipeline layout with dummy descriptor set layouts.
Tony-LunarG99b880b2019-09-26 11:19:52 -0600467 device_gpu_assisted->adjusted_max_desc_sets = device_gpu_assisted->phys_dev_props.limits.maxBoundDescriptorSets;
468 device_gpu_assisted->adjusted_max_desc_sets = std::min(33U, device_gpu_assisted->adjusted_max_desc_sets);
Karl Schultz7b024b42018-08-30 16:18:18 -0600469
470 // We can't do anything if there is only one.
471 // Device probably not a legit Vulkan device, since there should be at least 4. Protect ourselves.
Tony-LunarG99b880b2019-09-26 11:19:52 -0600472 if (device_gpu_assisted->adjusted_max_desc_sets == 1) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600473 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz7b024b42018-08-30 16:18:18 -0600474 "Device can bind only a single descriptor set. GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600475 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600476 return;
477 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600478 device_gpu_assisted->desc_set_bind_index = device_gpu_assisted->adjusted_max_desc_sets - 1;
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600479 log_msg(report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
480 "UNASSIGNED-GPU-Assisted Validation. ", "Shaders using descriptor set at index %d. ",
Tony-LunarG99b880b2019-09-26 11:19:52 -0600481 device_gpu_assisted->desc_set_bind_index);
Karl Schultz7b024b42018-08-30 16:18:18 -0600482
Tony-LunarG99b880b2019-09-26 11:19:52 -0600483 device_gpu_assisted->output_buffer_size = sizeof(uint32_t) * (spvtools::kInst2MaxOutCnt + 1);
484 VkResult result1 = InitializeVma(physicalDevice, *pDevice, &device_gpu_assisted->vmaAllocator);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600485 assert(result1 == VK_SUCCESS);
486 std::unique_ptr<GpuAssistedDescriptorSetManager> desc_set_manager(new GpuAssistedDescriptorSetManager(device_gpu_assisted));
Karl Schultz7b024b42018-08-30 16:18:18 -0600487
488 // The descriptor indexing checks require only the first "output" binding.
489 const VkDescriptorSetLayoutBinding debug_desc_layout_bindings[kNumBindingsInSet] = {
490 {
491 0, // output
492 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
493 1,
Jason Macnak67407e72019-07-11 11:05:09 -0700494 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT | kShaderStageAllRayTracing,
Karl Schultz7b024b42018-08-30 16:18:18 -0600495 NULL,
496 },
Tony-LunarG1b2e0c32019-02-07 17:13:27 -0700497 {
498 1, // input
499 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
500 1,
Jason Macnak67407e72019-07-11 11:05:09 -0700501 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT | kShaderStageAllRayTracing,
Tony-LunarG1b2e0c32019-02-07 17:13:27 -0700502 NULL,
503 },
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600504 {
505 2, // input
506 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
507 1,
508 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT | kShaderStageAllRayTracing,
509 NULL,
510 },
Karl Schultz7b024b42018-08-30 16:18:18 -0600511 };
Karl Schultz7b024b42018-08-30 16:18:18 -0600512 const VkDescriptorSetLayoutCreateInfo debug_desc_layout_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, 0,
513 kNumBindingsInSet, debug_desc_layout_bindings};
514
515 const VkDescriptorSetLayoutCreateInfo dummy_desc_layout_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, 0, 0,
516 NULL};
517
Tony-LunarG99b880b2019-09-26 11:19:52 -0600518 result1 = DispatchCreateDescriptorSetLayout(*pDevice, &debug_desc_layout_info, NULL, &device_gpu_assisted->debug_desc_layout);
Karl Schultz7b024b42018-08-30 16:18:18 -0600519
520 // This is a layout used to "pad" a pipeline layout to fill in any gaps to the selected bind index.
Tony-LunarG99b880b2019-09-26 11:19:52 -0600521 VkResult result2 =
522 DispatchCreateDescriptorSetLayout(*pDevice, &dummy_desc_layout_info, NULL, &device_gpu_assisted->dummy_desc_layout);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600523 assert((result1 == VK_SUCCESS) && (result2 == VK_SUCCESS));
524 if ((result1 != VK_SUCCESS) || (result2 != VK_SUCCESS)) {
525 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(*pDevice),
Karl Schultz7b024b42018-08-30 16:18:18 -0600526 "Unable to create descriptor set layout. GPU-Assisted Validation disabled.");
527 if (result == VK_SUCCESS) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600528 DispatchDestroyDescriptorSetLayout(*pDevice, device_gpu_assisted->debug_desc_layout, NULL);
Karl Schultz7b024b42018-08-30 16:18:18 -0600529 }
530 if (result2 == VK_SUCCESS) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600531 DispatchDestroyDescriptorSetLayout(*pDevice, device_gpu_assisted->dummy_desc_layout, NULL);
Karl Schultz7b024b42018-08-30 16:18:18 -0600532 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600533 device_gpu_assisted->debug_desc_layout = VK_NULL_HANDLE;
534 device_gpu_assisted->dummy_desc_layout = VK_NULL_HANDLE;
535 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600536 return;
537 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600538 device_gpu_assisted->desc_set_manager = std::move(desc_set_manager);
Jason Macnak83cfd582019-07-31 10:14:24 -0700539
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600540 // Register callback to be called at any ResetCommandBuffer time
541 device_gpu_assisted->SetCommandBufferResetCallback(
542 [device_gpu_assisted](VkCommandBuffer command_buffer) -> void { device_gpu_assisted->ResetCommandBuffer(command_buffer); });
543
544 CreateAccelerationStructureBuildValidationState(device_gpu_assisted);
Karl Schultz7b024b42018-08-30 16:18:18 -0600545}
546
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600547void GpuAssisted::PostCallRecordGetBufferDeviceAddressEXT(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
548 VkDeviceAddress address) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600549 BUFFER_STATE *buffer_state = GetBufferState(pInfo->buffer);
550 // Validate against the size requested when the buffer was created
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600551 if (buffer_state) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600552 buffer_map[address] = buffer_state->createInfo.size;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600553 buffer_state->deviceAddress = address;
554 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600555}
556
Tony-LunarG7e0842f2019-12-10 09:26:34 -0700557void GpuAssisted::PostCallRecordGetBufferDeviceAddressKHR(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
558 VkDeviceAddress address) {
559 BUFFER_STATE *buffer_state = GetBufferState(pInfo->buffer);
560 // Validate against the size requested when the buffer was created
561 if (buffer_state) {
562 buffer_map[address] = buffer_state->createInfo.size;
563 buffer_state->deviceAddress = address;
564 }
565}
566
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600567void GpuAssisted::PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600568 BUFFER_STATE *buffer_state = GetBufferState(buffer);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600569 if (buffer_state) buffer_map.erase(buffer_state->deviceAddress);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600570}
Karl Schultz7b024b42018-08-30 16:18:18 -0600571// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600572void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600573 for (auto &queue_barrier_command_info_kv : queue_barrier_command_infos) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600574 GpuAssistedQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_kv.second;
Jason Macnak8eae5722019-07-17 15:17:45 -0700575
576 DispatchFreeCommandBuffers(device, queue_barrier_command_info.barrier_command_pool, 1,
577 &queue_barrier_command_info.barrier_command_buffer);
578 queue_barrier_command_info.barrier_command_buffer = VK_NULL_HANDLE;
579
580 DispatchDestroyCommandPool(device, queue_barrier_command_info.barrier_command_pool, NULL);
581 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
Karl Schultz58674242019-01-22 15:35:02 -0700582 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600583 queue_barrier_command_infos.clear();
584 if (debug_desc_layout) {
585 DispatchDestroyDescriptorSetLayout(device, debug_desc_layout, NULL);
586 debug_desc_layout = VK_NULL_HANDLE;
Karl Schultz7b024b42018-08-30 16:18:18 -0600587 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600588 if (dummy_desc_layout) {
589 DispatchDestroyDescriptorSetLayout(device, dummy_desc_layout, NULL);
590 dummy_desc_layout = VK_NULL_HANDLE;
Karl Schultz7b024b42018-08-30 16:18:18 -0600591 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600592 desc_set_manager.reset();
Jason Macnak83cfd582019-07-31 10:14:24 -0700593
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600594 DestroyAccelerationStructureBuildValidationState();
Jason Macnak83cfd582019-07-31 10:14:24 -0700595
Tony-LunarG99b880b2019-09-26 11:19:52 -0600596 if (vmaAllocator) {
597 vmaDestroyAllocator(vmaAllocator);
Tony-LunarG29f48a72019-04-16 11:53:37 -0600598 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600599}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600600void GpuAssisted::CreateAccelerationStructureBuildValidationState(GpuAssisted *device_gpuav) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600601 if (device_gpuav->aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700602 return;
603 }
604
Tony-LunarG99b880b2019-09-26 11:19:52 -0600605 auto &as_validation_state = device_gpuav->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700606 if (as_validation_state.initialized) {
607 return;
608 }
609
610 if (!device_extensions.vk_nv_ray_tracing) {
611 return;
612 }
613
614 // Outline:
615 // - Create valid bottom level acceleration structure which acts as replacement
616 // - Create and load vertex buffer
617 // - Create and load index buffer
618 // - Create, allocate memory for, and bind memory for acceleration structure
619 // - Query acceleration structure handle
620 // - Create command pool and command buffer
621 // - Record build acceleration structure command
622 // - Submit command buffer and wait for completion
623 // - Cleanup
624 // - Create compute pipeline for validating instance buffers
625 // - Create descriptor set layout
626 // - Create pipeline layout
627 // - Create pipeline
628 // - Cleanup
629
630 VkResult result = VK_SUCCESS;
631
632 VkBuffer vbo = VK_NULL_HANDLE;
633 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
634 if (result == VK_SUCCESS) {
635 VkBufferCreateInfo vbo_ci = {};
636 vbo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
637 vbo_ci.size = sizeof(float) * 9;
638 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
639
640 VmaAllocationCreateInfo vbo_ai = {};
641 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
642 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
643
Tony-LunarG99b880b2019-09-26 11:19:52 -0600644 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700645 if (result != VK_SUCCESS) {
646 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
647 "Failed to create vertex buffer for acceleration structure build validation.");
648 }
649 }
650
651 if (result == VK_SUCCESS) {
652 uint8_t *mapped_vbo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600653 result = vmaMapMemory(device_gpuav->vmaAllocator, vbo_allocation, (void **)&mapped_vbo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700654 if (result != VK_SUCCESS) {
655 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
656 "Failed to map vertex buffer for acceleration structure build validation.");
657 } else {
658 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
659 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600660 vmaUnmapMemory(device_gpuav->vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700661 }
662 }
663
664 VkBuffer ibo = VK_NULL_HANDLE;
665 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
666 if (result == VK_SUCCESS) {
667 VkBufferCreateInfo ibo_ci = {};
668 ibo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
669 ibo_ci.size = sizeof(uint32_t) * 3;
670 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
671
672 VmaAllocationCreateInfo ibo_ai = {};
673 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
674 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
675
Tony-LunarG99b880b2019-09-26 11:19:52 -0600676 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700677 if (result != VK_SUCCESS) {
678 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
679 "Failed to create index buffer for acceleration structure build validation.");
680 }
681 }
682
683 if (result == VK_SUCCESS) {
684 uint8_t *mapped_ibo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600685 result = vmaMapMemory(device_gpuav->vmaAllocator, ibo_allocation, (void **)&mapped_ibo_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700686 if (result != VK_SUCCESS) {
687 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
688 "Failed to map index buffer for acceleration structure build validation.");
689 } else {
690 const std::vector<uint32_t> indicies = {0, 1, 2};
691 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600692 vmaUnmapMemory(device_gpuav->vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700693 }
694 }
695
696 VkGeometryNV geometry = {};
697 geometry.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
698 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
699 geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
700 geometry.geometry.triangles.vertexData = vbo;
701 geometry.geometry.triangles.vertexOffset = 0;
702 geometry.geometry.triangles.vertexCount = 3;
703 geometry.geometry.triangles.vertexStride = 12;
704 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
705 geometry.geometry.triangles.indexData = ibo;
706 geometry.geometry.triangles.indexOffset = 0;
707 geometry.geometry.triangles.indexCount = 3;
708 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
709 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
710 geometry.geometry.triangles.transformOffset = 0;
711 geometry.geometry.aabbs = {};
712 geometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
713
714 VkAccelerationStructureCreateInfoNV as_ci = {};
715 as_ci.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
716 as_ci.info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
717 as_ci.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV;
718 as_ci.info.instanceCount = 0;
719 as_ci.info.geometryCount = 1;
720 as_ci.info.pGeometries = &geometry;
721 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600722 result = DispatchCreateAccelerationStructureNV(device_gpuav->device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700723 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600724 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700725 "Failed to create acceleration structure for acceleration structure build validation.");
726 }
727 }
728
729 VkMemoryRequirements2 as_mem_requirements = {};
730 if (result == VK_SUCCESS) {
731 VkAccelerationStructureMemoryRequirementsInfoNV as_mem_requirements_info = {};
732 as_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
733 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
734 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
735
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600736 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700737 }
738
739 VmaAllocationInfo as_memory_ai = {};
740 if (result == VK_SUCCESS) {
741 VmaAllocationCreateInfo as_memory_aci = {};
742 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
743
Tony-LunarG99b880b2019-09-26 11:19:52 -0600744 result = vmaAllocateMemory(device_gpuav->vmaAllocator, &as_mem_requirements.memoryRequirements, &as_memory_aci,
745 &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700746 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600747 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700748 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
749 }
750 }
751
752 if (result == VK_SUCCESS) {
753 VkBindAccelerationStructureMemoryInfoNV as_bind_info = {};
754 as_bind_info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
755 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
756 as_bind_info.memory = as_memory_ai.deviceMemory;
757 as_bind_info.memoryOffset = as_memory_ai.offset;
758
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600759 result = DispatchBindAccelerationStructureMemoryNV(device_gpuav->device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700760 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600761 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700762 "Failed to bind acceleration structure memory for acceleration structure build validation.");
763 }
764 }
765
766 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600767 result = DispatchGetAccelerationStructureHandleNV(device_gpuav->device, as_validation_state.replacement_as,
768 sizeof(uint64_t), &as_validation_state.replacement_as_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700769 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600770 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700771 "Failed to get acceleration structure handle for acceleration structure build validation.");
772 }
773 }
774
775 VkMemoryRequirements2 scratch_mem_requirements = {};
776 if (result == VK_SUCCESS) {
777 VkAccelerationStructureMemoryRequirementsInfoNV scratch_mem_requirements_info = {};
778 scratch_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
779 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
780 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
781
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600782 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &scratch_mem_requirements_info,
783 &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700784 }
785
786 VkBuffer scratch = VK_NULL_HANDLE;
787 if (result == VK_SUCCESS) {
788 VkBufferCreateInfo scratch_ci = {};
789 scratch_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
790 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
791 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
792
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600793 result = DispatchCreateBuffer(device_gpuav->device, &scratch_ci, nullptr, &scratch);
Jason Macnak83cfd582019-07-31 10:14:24 -0700794 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600795 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700796 "Failed to create scratch buffer for acceleration structure build validation.");
797 }
798 }
799
800 VmaAllocation scratch_allocation = VK_NULL_HANDLE;
801 VmaAllocationInfo scratch_allocation_info = {};
802 if (result == VK_SUCCESS) {
803 VmaAllocationCreateInfo scratch_aci = {};
804 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
805
Tony-LunarG99b880b2019-09-26 11:19:52 -0600806 result = vmaAllocateMemory(device_gpuav->vmaAllocator, &scratch_mem_requirements.memoryRequirements, &scratch_aci,
807 &scratch_allocation, &scratch_allocation_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700808 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600809 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700810 "Failed to alloc scratch memory for acceleration structure build validation.");
811 }
812 }
813
814 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600815 result = DispatchBindBufferMemory(device_gpuav->device, scratch, scratch_allocation_info.deviceMemory,
816 scratch_allocation_info.offset);
Jason Macnak83cfd582019-07-31 10:14:24 -0700817 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600818 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700819 "Failed to bind scratch memory for acceleration structure build validation.");
820 }
821 }
822
823 VkCommandPool command_pool = VK_NULL_HANDLE;
824 if (result == VK_SUCCESS) {
825 VkCommandPoolCreateInfo command_pool_ci = {};
826 command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
827 command_pool_ci.queueFamilyIndex = 0;
828
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600829 result = DispatchCreateCommandPool(device_gpuav->device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700830 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600831 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700832 "Failed to create command pool for acceleration structure build validation.");
833 }
834 }
835
836 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
837
838 if (result == VK_SUCCESS) {
839 VkCommandBufferAllocateInfo command_buffer_ai = {};
840 command_buffer_ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
841 command_buffer_ai.commandPool = command_pool;
842 command_buffer_ai.commandBufferCount = 1;
843 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
844
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600845 result = DispatchAllocateCommandBuffers(device_gpuav->device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700846 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600847 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700848 "Failed to create command buffer for acceleration structure build validation.");
849 }
850
851 // Hook up command buffer dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600852 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700853 }
854
855 if (result == VK_SUCCESS) {
856 VkCommandBufferBeginInfo command_buffer_bi = {};
857 command_buffer_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
858
859 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
860 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600861 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700862 "Failed to begin command buffer for acceleration structure build validation.");
863 }
864 }
865
866 if (result == VK_SUCCESS) {
867 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
868 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
869 DispatchEndCommandBuffer(command_buffer);
870 }
871
872 VkQueue queue = VK_NULL_HANDLE;
873 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600874 DispatchGetDeviceQueue(device_gpuav->device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700875
876 // Hook up queue dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600877 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700878
879 VkSubmitInfo submit_info = {};
880 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
881 submit_info.commandBufferCount = 1;
882 submit_info.pCommandBuffers = &command_buffer;
883 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
884 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600885 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700886 "Failed to submit command buffer for acceleration structure build validation.");
887 }
888 }
889
890 if (result == VK_SUCCESS) {
891 result = DispatchQueueWaitIdle(queue);
892 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600893 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700894 "Failed to wait for queue idle for acceleration structure build validation.");
895 }
896 }
897
898 if (vbo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600899 vmaDestroyBuffer(device_gpuav->vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700900 }
901 if (ibo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600902 vmaDestroyBuffer(device_gpuav->vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700903 }
904 if (scratch != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600905 DispatchDestroyBuffer(device_gpuav->device, scratch, nullptr);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600906 vmaFreeMemory(device_gpuav->vmaAllocator, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700907 }
908 if (command_pool != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600909 DispatchDestroyCommandPool(device_gpuav->device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700910 }
911
Tony-LunarG99b880b2019-09-26 11:19:52 -0600912 if (device_gpuav->debug_desc_layout == VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600913 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700914 "Failed to find descriptor set layout for acceleration structure build validation.");
915 result = VK_INCOMPLETE;
916 }
917
918 if (result == VK_SUCCESS) {
919 VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
920 pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
921 pipeline_layout_ci.setLayoutCount = 1;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600922 pipeline_layout_ci.pSetLayouts = &device_gpuav->debug_desc_layout;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600923 result = DispatchCreatePipelineLayout(device_gpuav->device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700924 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600925 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700926 "Failed to create pipeline layout for acceleration structure build validation.");
927 }
928 }
929
930 VkShaderModule shader_module = VK_NULL_HANDLE;
931 if (result == VK_SUCCESS) {
932 VkShaderModuleCreateInfo shader_module_ci = {};
933 shader_module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
934 shader_module_ci.codeSize = sizeof(kComputeShaderSpirv);
935 shader_module_ci.pCode = (uint32_t *)kComputeShaderSpirv;
936
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600937 result = DispatchCreateShaderModule(device_gpuav->device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700938 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600939 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700940 "Failed to create compute shader module for acceleration structure build validation.");
941 }
942 }
943
944 if (result == VK_SUCCESS) {
945 VkPipelineShaderStageCreateInfo pipeline_stage_ci = {};
946 pipeline_stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
947 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
948 pipeline_stage_ci.module = shader_module;
949 pipeline_stage_ci.pName = "main";
950
951 VkComputePipelineCreateInfo pipeline_ci = {};
952 pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
953 pipeline_ci.stage = pipeline_stage_ci;
954 pipeline_ci.layout = as_validation_state.pipeline_layout;
955
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600956 result = DispatchCreateComputePipelines(device_gpuav->device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr,
957 &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700958 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600959 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700960 "Failed to create compute pipeline for acceleration structure build validation.");
961 }
962 }
963
964 if (shader_module != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600965 DispatchDestroyShaderModule(device_gpuav->device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700966 }
967
968 if (result == VK_SUCCESS) {
969 as_validation_state.initialized = true;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600970 log_msg(report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
971 HandleToUint64(device_gpuav->device), "UNASSIGNED-GPU-Assisted Validation.",
972 "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700973 } else {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600974 device_gpuav->aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700975 }
976}
977
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600978void GpuAssisted::DestroyAccelerationStructureBuildValidationState() {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600979 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700980 if (as_validation_state.pipeline != VK_NULL_HANDLE) {
981 DispatchDestroyPipeline(device, as_validation_state.pipeline, nullptr);
982 }
983 if (as_validation_state.pipeline_layout != VK_NULL_HANDLE) {
984 DispatchDestroyPipelineLayout(device, as_validation_state.pipeline_layout, nullptr);
985 }
986 if (as_validation_state.replacement_as != VK_NULL_HANDLE) {
987 DispatchDestroyAccelerationStructureNV(device, as_validation_state.replacement_as, nullptr);
988 }
989 if (as_validation_state.replacement_as_allocation != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600990 vmaFreeMemory(vmaAllocator, as_validation_state.replacement_as_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700991 }
992}
993
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600994struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700995 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
996 VkPipeline pipeline = VK_NULL_HANDLE;
997 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
998 std::vector<VkDescriptorSet> descriptor_sets;
999 std::vector<std::vector<uint32_t>> dynamic_offsets;
1000 uint32_t push_descriptor_set_index = 0;
1001 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
1002 std::vector<uint8_t> push_constants_data;
1003 PushConstantRangesId push_constants_ranges;
1004
1005 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
1006 pipeline_bind_point = bind_point;
1007
1008 LAST_BOUND_STATE &last_bound = cb_state->lastBound[bind_point];
1009 if (last_bound.pipeline_state) {
1010 pipeline = last_bound.pipeline_state->pipeline;
1011 pipeline_layout = last_bound.pipeline_layout;
1012 descriptor_sets.reserve(last_bound.per_set.size());
1013 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
1014 const auto *bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
1015
1016 descriptor_sets.push_back(bound_descriptor_set->GetSet());
1017 if (bound_descriptor_set->IsPushDescriptor()) {
1018 push_descriptor_set_index = static_cast<uint32_t>(i);
1019 }
1020 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
1021 }
1022
1023 if (last_bound.push_descriptor_set) {
1024 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
1025 }
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001026 if (last_bound.pipeline_state->pipeline_layout->push_constant_ranges == cb_state->push_constant_data_ranges) {
Jason Macnak83cfd582019-07-31 10:14:24 -07001027 push_constants_data = cb_state->push_constant_data;
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001028 push_constants_ranges = last_bound.pipeline_state->pipeline_layout->push_constant_ranges;
Jason Macnak83cfd582019-07-31 10:14:24 -07001029 }
1030 }
1031 }
1032
1033 void Restore(VkCommandBuffer command_buffer) const {
1034 if (pipeline != VK_NULL_HANDLE) {
1035 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
1036 if (!descriptor_sets.empty()) {
1037 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
1038 VkDescriptorSet descriptor_set = descriptor_sets[i];
1039 if (descriptor_set != VK_NULL_HANDLE) {
1040 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
1041 static_cast<uint32_t>(i), 1, &descriptor_set,
1042 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
1043 }
1044 }
1045 }
1046 if (!push_descriptor_set_writes.empty()) {
1047 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
1048 static_cast<uint32_t>(push_descriptor_set_writes.size()),
1049 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
1050 }
1051 for (const auto &push_constant_range : *push_constants_ranges) {
1052 if (push_constant_range.size == 0) continue;
1053 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
1054 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
1055 }
1056 }
1057 }
1058};
1059
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001060void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
1061 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
1062 VkDeviceSize instanceOffset, VkBool32 update,
1063 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
1064 VkBuffer scratch, VkDeviceSize scratchOffset) {
Jason Macnak83cfd582019-07-31 10:14:24 -07001065 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
1066 return;
1067 }
1068
Tony-LunarG99b880b2019-09-26 11:19:52 -06001069 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001070 if (!as_validation_state.initialized) {
1071 return;
1072 }
1073
1074 // Empty acceleration structure is valid according to the spec.
1075 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
1076 return;
1077 }
1078
1079 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1080 assert(cb_state != nullptr);
1081
1082 std::vector<uint64_t> current_valid_handles;
1083 for (const auto &as_state_kv : accelerationStructureMap) {
1084 const ACCELERATION_STRUCTURE_STATE &as_state = *as_state_kv.second;
1085 if (as_state.built && as_state.create_info.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
1086 current_valid_handles.push_back(as_state.opaque_handle);
1087 }
1088 }
1089
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001090 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -07001091 as_validation_buffer_info.acceleration_structure = dst;
1092
1093 const VkDeviceSize validation_buffer_size =
1094 // One uint for number of instances to validate
1095 4 +
1096 // Two uint for the replacement acceleration structure handle
1097 8 +
1098 // One uint for number of invalid handles found
1099 4 +
1100 // Two uint for the first invalid handle found
1101 8 +
1102 // One uint for the number of current valid handles
1103 4 +
1104 // Two uint for each current valid handle
1105 (8 * current_valid_handles.size());
1106
1107 VkBufferCreateInfo validation_buffer_create_info = {};
1108 validation_buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1109 validation_buffer_create_info.size = validation_buffer_size;
1110 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1111
1112 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
1113 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
1114
Tony-LunarG99b880b2019-09-26 11:19:52 -06001115 VkResult result = vmaCreateBuffer(vmaAllocator, &validation_buffer_create_info, &validation_buffer_alloc_info,
1116 &as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -07001117 &as_validation_buffer_info.validation_buffer_allocation, nullptr);
1118 if (result != VK_SUCCESS) {
1119 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
1120 "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001121 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -07001122 return;
1123 }
1124
1125 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001126 result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001127 if (result != VK_SUCCESS) {
1128 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
1129 "Unable to allocate device memory for acceleration structure build val buffer.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001130 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -07001131 return;
1132 }
1133
1134 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
1135 mapped_validation_buffer->replacement_handle_bits_0 =
1136 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
1137 mapped_validation_buffer->replacement_handle_bits_1 =
1138 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
1139 mapped_validation_buffer->invalid_handle_found = 0;
1140 mapped_validation_buffer->invalid_handle_bits_0 = 0;
1141 mapped_validation_buffer->invalid_handle_bits_1 = 0;
1142 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
1143
1144 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
1145 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
1146 const uint64_t current_valid_handle = current_valid_handles[i];
1147
1148 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
1149 ++mapped_valid_handles;
1150 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
1151 ++mapped_valid_handles;
1152 }
1153
Tony-LunarG99b880b2019-09-26 11:19:52 -06001154 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -07001155
1156 static constexpr const VkDeviceSize kInstanceSize = 64;
1157 const VkDeviceSize instance_buffer_size = kInstanceSize * pInfo->instanceCount;
1158
Tony-LunarG99b880b2019-09-26 11:19:52 -06001159 result =
1160 desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool, &as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -07001161 if (result != VK_SUCCESS) {
1162 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
1163 "Unable to get descriptor set for acceleration structure build.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001164 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -07001165 return;
1166 }
1167
1168 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
1169 descriptor_buffer_infos[0].buffer = instanceData;
1170 descriptor_buffer_infos[0].offset = instanceOffset;
1171 descriptor_buffer_infos[0].range = instance_buffer_size;
1172 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.validation_buffer;
1173 descriptor_buffer_infos[1].offset = 0;
1174 descriptor_buffer_infos[1].range = validation_buffer_size;
1175
1176 VkWriteDescriptorSet descriptor_set_writes[2] = {};
1177 descriptor_set_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1178 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
1179 descriptor_set_writes[0].dstBinding = 0;
1180 descriptor_set_writes[0].descriptorCount = 1;
1181 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1182 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
1183 descriptor_set_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1184 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
1185 descriptor_set_writes[1].dstBinding = 1;
1186 descriptor_set_writes[1].descriptorCount = 1;
1187 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1188 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
1189
1190 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
1191
1192 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
1193 VkMemoryBarrier memory_barrier = {};
1194 memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
1195 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
1196 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
1197 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
1198 &memory_barrier, 0, nullptr, 0, nullptr);
1199
1200 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001201 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001202 restorable_state.Create(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
1203
1204 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
1205 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
1206 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
1207 &as_validation_buffer_info.descriptor_set, 0, nullptr);
1208 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
1209
1210 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
1211 // have been replaced by the validation compute shader before any builds take place.
1212 VkBufferMemoryBarrier instance_buffer_barrier = {};
1213 instance_buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1214 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1215 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
1216 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1217 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1218 instance_buffer_barrier.buffer = instanceData;
1219 instance_buffer_barrier.offset = instanceOffset;
1220 instance_buffer_barrier.size = instance_buffer_size;
1221 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1222 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
1223 nullptr);
1224
1225 // Restore the previous compute pipeline state.
1226 restorable_state.Restore(commandBuffer);
1227
1228 as_validation_state.validation_buffers[commandBuffer].push_back(std::move(as_validation_buffer_info));
1229}
1230
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001231void GpuAssisted::ProcessAccelerationStructureBuildValidationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Jason Macnak83cfd582019-07-31 10:14:24 -07001232 if (cb_node == nullptr || !cb_node->hasBuildAccelerationStructureCmd) {
1233 return;
1234 }
1235
Tony-LunarG99b880b2019-09-26 11:19:52 -06001236 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001237 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[cb_node->commandBuffer];
1238 for (const auto &as_validation_buffer_info : as_validation_buffer_infos) {
1239 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
1240
Tony-LunarG99b880b2019-09-26 11:19:52 -06001241 VkResult result =
1242 vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001243 if (result == VK_SUCCESS) {
1244 if (mapped_validation_buffer->invalid_handle_found > 0) {
1245 uint64_t invalid_handle = 0;
1246 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
1247 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
1248
1249 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT,
1250 HandleToUint64(as_validation_buffer_info.acceleration_structure), "UNASSIGNED-AccelerationStructure",
1251 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
1252 "handle (%" PRIu64 ")",
1253 invalid_handle);
1254 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001255 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -07001256 }
1257 }
1258}
1259
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001260void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
1261 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
1262 VkResult result) {
1263 if (VK_SUCCESS != result) return;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001264 ValidationStateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001265 for (uint32_t i = 0; i < bindInfoCount; i++) {
1266 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
1267 ACCELERATION_STRUCTURE_STATE *as_state = GetAccelerationStructureState(info.accelerationStructure);
1268 if (as_state) {
1269 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
1270 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001271 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001272}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -07001273
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001274// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
1275void GpuAssisted::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
1276 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
1277 void *cpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001278 if (aborted) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001279 return;
1280 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001281
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001282 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
1283
Tony-LunarG99b880b2019-09-26 11:19:52 -06001284 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001285 std::ostringstream strm;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001286 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Karl Schultz7b024b42018-08-30 16:18:18 -06001287 << "Application has too many descriptor sets in the pipeline layout to continue with gpu validation. "
1288 << "Validation is not modifying the pipeline layout. "
1289 << "Instrumented shaders are replaced with non-instrumented shaders.";
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001290 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device), strm.str().c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -06001291 } else {
1292 // Modify the pipeline layout by:
1293 // 1. Copying the caller's descriptor set desc_layouts
1294 // 2. Fill in dummy descriptor layouts up to the max binding
1295 // 3. Fill in with the debug descriptor layout at the max binding slot
Tony-LunarG99b880b2019-09-26 11:19:52 -06001296 cpl_state->new_layouts.reserve(adjusted_max_desc_sets);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001297 cpl_state->new_layouts.insert(cpl_state->new_layouts.end(), &pCreateInfo->pSetLayouts[0],
1298 &pCreateInfo->pSetLayouts[pCreateInfo->setLayoutCount]);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001299 for (uint32_t i = pCreateInfo->setLayoutCount; i < adjusted_max_desc_sets - 1; ++i) {
1300 cpl_state->new_layouts.push_back(dummy_desc_layout);
Karl Schultz7b024b42018-08-30 16:18:18 -06001301 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001302 cpl_state->new_layouts.push_back(debug_desc_layout);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001303 cpl_state->modified_create_info.pSetLayouts = cpl_state->new_layouts.data();
Tony-LunarG99b880b2019-09-26 11:19:52 -06001304 cpl_state->modified_create_info.setLayoutCount = adjusted_max_desc_sets;
Karl Schultz7b024b42018-08-30 16:18:18 -06001305 }
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -07001306}
1307
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001308void GpuAssisted::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
1309 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
1310 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001311 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1312
Karl Schultz7b024b42018-08-30 16:18:18 -06001313 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001314 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz7b024b42018-08-30 16:18:18 -06001315 "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001316 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -06001317 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001318}
1319
Karl Schultz7b024b42018-08-30 16:18:18 -06001320// Free the device memory and descriptor set associated with a command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001321void GpuAssisted::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001322 if (aborted) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001323 return;
1324 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001325 auto gpuav_buffer_list = GetGpuAssistedBufferInfo(commandBuffer);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001326 for (auto buffer_info : gpuav_buffer_list) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001327 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001328 if (buffer_info.di_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001329 vmaDestroyBuffer(vmaAllocator, buffer_info.di_input_mem_block.buffer, buffer_info.di_input_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001330 }
1331 if (buffer_info.bda_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001332 vmaDestroyBuffer(vmaAllocator, buffer_info.bda_input_mem_block.buffer, buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -06001333 }
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001334 if (buffer_info.desc_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001335 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001336 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001337 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001338 command_buffer_map.erase(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001339
Tony-LunarG99b880b2019-09-26 11:19:52 -06001340 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001341 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[commandBuffer];
1342 for (auto &as_validation_buffer_info : as_validation_buffer_infos) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001343 vmaDestroyBuffer(vmaAllocator, as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -07001344 as_validation_buffer_info.validation_buffer_allocation);
1345
1346 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001347 desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool,
1348 as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -07001349 }
1350 }
1351 as_validation_info.validation_buffers.erase(commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -06001352}
Karl Schultz7b024b42018-08-30 16:18:18 -06001353// Just gives a warning about a possible deadlock.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001354bool GpuAssisted::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
1355 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
1356 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1357 uint32_t bufferMemoryBarrierCount,
1358 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
Jeff Bolz5c801d12019-10-09 10:38:45 -05001359 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001360 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
1361 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer),
Karl Schultz7b024b42018-08-30 16:18:18 -06001362 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1363 "GPU_Assisted validation waits on queue completion. "
1364 "This wait could block the host's signaling of this event, resulting in deadlock.");
1365 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001366 return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001367}
1368
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001369void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1370 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
1371 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
1372 if (enabled.gpu_validation_reserve_binding_slot && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
1373 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
1374 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
1375 } else {
1376 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1377 HandleToUint64(physicalDevice), "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1378 "Unable to reserve descriptor binding slot on a device with only one slot.");
1379 }
1380 }
1381}
1382
1383void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1384 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
1385 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
1386 if (enabled.gpu_validation_reserve_binding_slot && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
1387 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
1388 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
1389 } else {
1390 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1391 HandleToUint64(physicalDevice), "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1392 "Unable to reserve descriptor binding slot on a device with only one slot.");
1393 }
1394 }
1395}
1396
1397void GpuAssisted::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1398 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1399 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1400 void *cgpl_state_data) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001401 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001402 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
1403 PreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state, &new_pipeline_create_infos,
1404 VK_PIPELINE_BIND_POINT_GRAPHICS);
1405 cgpl_state->gpu_create_infos = new_pipeline_create_infos;
1406 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001407}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001408
1409void GpuAssisted::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1410 const VkComputePipelineCreateInfo *pCreateInfos,
1411 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1412 void *ccpl_state_data) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001413 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001414 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
1415 PreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state, &new_pipeline_create_infos,
1416 VK_PIPELINE_BIND_POINT_COMPUTE);
1417 ccpl_state->gpu_create_infos = new_pipeline_create_infos;
1418 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
Jason Macnak67407e72019-07-11 11:05:09 -07001419}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001420
1421void GpuAssisted::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1422 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1423 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1424 void *crtpl_state_data) {
Jason Macnak67407e72019-07-11 11:05:09 -07001425 std::vector<safe_VkRayTracingPipelineCreateInfoNV> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001426 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
1427 PreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state, &new_pipeline_create_infos,
1428 VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
1429 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1430 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001431}
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001432template <typename CreateInfo>
1433struct CreatePipelineTraits {};
1434template <>
1435struct CreatePipelineTraits<VkGraphicsPipelineCreateInfo> {
1436 using SafeType = safe_VkGraphicsPipelineCreateInfo;
1437 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->graphicsPipelineCI; }
1438 static uint32_t GetStageCount(const VkGraphicsPipelineCreateInfo &createInfo) { return createInfo.stageCount; }
1439 static VkShaderModule GetShaderModule(const VkGraphicsPipelineCreateInfo &createInfo, uint32_t stage) {
1440 return createInfo.pStages[stage].module;
1441 }
1442 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
1443 createInfo->pStages[stage].module = shader_module;
1444 }
1445};
1446
1447template <>
1448struct CreatePipelineTraits<VkComputePipelineCreateInfo> {
1449 using SafeType = safe_VkComputePipelineCreateInfo;
1450 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->computePipelineCI; }
1451 static uint32_t GetStageCount(const VkComputePipelineCreateInfo &createInfo) { return 1; }
1452 static VkShaderModule GetShaderModule(const VkComputePipelineCreateInfo &createInfo, uint32_t stage) {
1453 return createInfo.stage.module;
1454 }
1455 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
1456 assert(stage == 0);
1457 createInfo->stage.module = shader_module;
1458 }
1459};
1460template <>
1461struct CreatePipelineTraits<VkRayTracingPipelineCreateInfoNV> {
1462 using SafeType = safe_VkRayTracingPipelineCreateInfoNV;
1463 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->raytracingPipelineCI; }
1464 static uint32_t GetStageCount(const VkRayTracingPipelineCreateInfoNV &createInfo) { return createInfo.stageCount; }
1465 static VkShaderModule GetShaderModule(const VkRayTracingPipelineCreateInfoNV &createInfo, uint32_t stage) {
1466 return createInfo.pStages[stage].module;
1467 }
1468 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
1469 createInfo->pStages[stage].module = shader_module;
1470 }
1471};
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001472
1473// Examine the pipelines to see if they use the debug descriptor set binding index.
1474// If any do, create new non-instrumented shader modules and use them to replace the instrumented
1475// shaders in the pipeline. Return the (possibly) modified create infos to the caller.
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001476template <typename CreateInfo, typename SafeCreateInfo>
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001477void GpuAssisted::PreCallRecordPipelineCreations(uint32_t count, const CreateInfo *pCreateInfos,
1478 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001479 std::vector<std::shared_ptr<PIPELINE_STATE>> &pipe_state,
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001480 std::vector<SafeCreateInfo> *new_pipeline_create_infos,
1481 const VkPipelineBindPoint bind_point) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001482 using Accessor = CreatePipelineTraits<CreateInfo>;
Jason Macnak67407e72019-07-11 11:05:09 -07001483 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1484 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001485 return;
1486 }
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001487
Karl Schultz7b024b42018-08-30 16:18:18 -06001488 // Walk through all the pipelines, make a copy of each and flag each pipeline that contains a shader that uses the debug
1489 // descriptor set index.
1490 for (uint32_t pipeline = 0; pipeline < count; ++pipeline) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001491 uint32_t stageCount = Accessor::GetStageCount(pCreateInfos[pipeline]);
1492 new_pipeline_create_infos->push_back(Accessor::GetPipelineCI(pipe_state[pipeline].get()));
Jason Macnak67407e72019-07-11 11:05:09 -07001493
1494 bool replace_shaders = false;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001495 if (pipe_state[pipeline]->active_slots.find(desc_set_bind_index) != pipe_state[pipeline]->active_slots.end()) {
Tony-LunarGd4da33b2019-04-16 16:28:22 -06001496 replace_shaders = true;
Karl Schultz7b024b42018-08-30 16:18:18 -06001497 }
Tony-LunarGd4da33b2019-04-16 16:28:22 -06001498 // If the app requests all available sets, the pipeline layout was not modified at pipeline layout creation and the already
1499 // instrumented shaders need to be replaced with uninstrumented shaders
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001500 if (pipe_state[pipeline]->pipeline_layout->set_layouts.size() >= adjusted_max_desc_sets) {
Tony-LunarGd4da33b2019-04-16 16:28:22 -06001501 replace_shaders = true;
1502 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001503
Tony-LunarGd4da33b2019-04-16 16:28:22 -06001504 if (replace_shaders) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001505 for (uint32_t stage = 0; stage < stageCount; ++stage) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001506 const SHADER_MODULE_STATE *shader = GetShaderModuleState(Accessor::GetShaderModule(pCreateInfos[pipeline], stage));
Jason Macnak67407e72019-07-11 11:05:09 -07001507
Karl Schultz7b024b42018-08-30 16:18:18 -06001508 VkShaderModuleCreateInfo create_info = {};
1509 VkShaderModule shader_module;
1510 create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
1511 create_info.pCode = shader->words.data();
1512 create_info.codeSize = shader->words.size() * sizeof(uint32_t);
Tony-LunarG152a88b2019-03-20 15:42:24 -06001513 VkResult result = DispatchCreateShaderModule(device, &create_info, pAllocator, &shader_module);
Karl Schultz7b024b42018-08-30 16:18:18 -06001514 if (result == VK_SUCCESS) {
Petr Kraus6c4bdce2019-08-27 17:35:01 +02001515 Accessor::SetShaderModule(&(*new_pipeline_create_infos)[pipeline], shader_module, stage);
Karl Schultz7b024b42018-08-30 16:18:18 -06001516 } else {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001517 uint64_t moduleHandle = HandleToUint64(Accessor::GetShaderModule(pCreateInfos[pipeline], stage));
Jason Macnak67407e72019-07-11 11:05:09 -07001518 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, moduleHandle,
Karl Schultz7b024b42018-08-30 16:18:18 -06001519 "Unable to replace instrumented shader with non-instrumented one. "
1520 "Device could become unstable.");
1521 }
1522 }
1523 }
1524 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001525}
1526
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001527void GpuAssisted::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1528 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1529 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1530 VkResult result, void *cgpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001531 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
1532 pPipelines, result, cgpl_state_data);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001533 PostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001534}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001535
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001536void GpuAssisted::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1537 const VkComputePipelineCreateInfo *pCreateInfos,
1538 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1539 VkResult result, void *ccpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001540 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1541 result, ccpl_state_data);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001542 PostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001543}
Tony-LunarG99b880b2019-09-26 11:19:52 -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) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001549 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
1550 pPipelines, result, crtpl_state_data);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001551 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) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001585 if (pipeline_state->active_slots.find(desc_set_bind_index) != pipeline_state->active_slots.end()) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001586 DispatchDestroyShaderModule(device, Accessor::GetShaderModule(pCreateInfos[pipeline], stage), pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001587 }
Jason Macnak67407e72019-07-11 11:05:09 -07001588
1589 const SHADER_MODULE_STATE *shader_state = nullptr;
1590 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1591 shader_state = GetShaderModuleState(pipeline_state->graphicsPipelineCI.pStages[stage].module);
1592 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1593 assert(stage == 0);
1594 shader_state = GetShaderModuleState(pipeline_state->computePipelineCI.stage.module);
1595 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1596 shader_state = GetShaderModuleState(pipeline_state->raytracingPipelineCI.pStages[stage].module);
1597 } else {
1598 assert(false);
1599 }
1600
Petr Krausede07f12019-11-13 01:45:15 +01001601 if (shader_state) {
1602 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->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 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001613 }
1614 }
Petr Krausede07f12019-11-13 01:45:15 +01001615 shader_map[shader_state->gpu_validation_shader_id].pipeline = pipeline_state->pipeline;
1616 // 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.
1618 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 shader_map[shader_state->gpu_validation_shader_id].shader_module = shader_module;
1630 shader_map[shader_state->gpu_validation_shader_id].pgm = std::move(code);
Karl Schultz7b024b42018-08-30 16:18:18 -06001631 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001632 }
1633 }
1634}
1635
1636// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001637void GpuAssisted::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001638 for (auto it = shader_map.begin(); it != shader_map.end();) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001639 if (it->second.pipeline == pipeline) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001640 it = shader_map.erase(it);
Karl Schultz7b024b42018-08-30 16:18:18 -06001641 } else {
1642 ++it;
1643 }
1644 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001645 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001646}
1647
1648// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001649bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
1650 uint32_t *unique_shader_id) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001651 if (aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001652 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
1653
1654 // Load original shader SPIR-V
1655 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
1656 new_pgm.clear();
1657 new_pgm.reserve(num_words);
1658 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
1659
1660 // Call the optimizer to instrument the shader.
1661 // 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 -07001662 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Tony-LunarG2ec96bb2019-11-26 13:43:02 -07001663 const bool descriptor_indexing = IsExtEnabled(device_extensions.vk_ext_descriptor_indexing);
Karl Schultz7b024b42018-08-30 16:18:18 -06001664 using namespace spvtools;
1665 spv_target_env target_env = SPV_ENV_VULKAN_1_1;
1666 Optimizer optimizer(target_env);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001667 optimizer.RegisterPass(
1668 CreateInstBindlessCheckPass(desc_set_bind_index, unique_shader_module_id, descriptor_indexing, descriptor_indexing, 2));
Karl Schultz7b024b42018-08-30 16:18:18 -06001669 optimizer.RegisterPass(CreateAggressiveDCEPass());
Tony-LunarG7e0842f2019-12-10 09:26:34 -07001670 if ((device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) && shaderInt64)
Tony-LunarG99b880b2019-09-26 11:19:52 -06001671 optimizer.RegisterPass(CreateInstBuffAddrCheckPass(desc_set_bind_index, unique_shader_module_id));
Karl Schultz7b024b42018-08-30 16:18:18 -06001672 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm);
1673 if (!pass) {
Mark Lobodzinski586d10e2019-03-08 18:19:48 -07001674 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, VK_NULL_HANDLE,
Karl Schultz7b024b42018-08-30 16:18:18 -06001675 "Failure to instrument shader. Proceeding with non-instrumented shader.");
1676 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001677 *unique_shader_id = unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -06001678 return pass;
1679}
Mark Lobodzinski01734072019-02-13 17:39:15 -07001680// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001681void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
1682 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
1683 void *csm_state_data) {
1684 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
1685 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -06001686 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001687 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
1688 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
Karl Schultz7b024b42018-08-30 16:18:18 -06001689 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001690}
1691
1692// Generate the stage-specific part of the message.
1693static void GenerateStageMessage(const uint32_t *debug_record, std::string &msg) {
1694 using namespace spvtools;
1695 std::ostringstream strm;
1696 switch (debug_record[kInstCommonOutStageIdx]) {
Jason Macnak67407e72019-07-11 11:05:09 -07001697 case spv::ExecutionModelVertex: {
Tony-LunarG6ff87582019-02-08 10:29:07 -07001698 strm << "Stage = Vertex. Vertex Index = " << debug_record[kInstVertOutVertexIndex]
1699 << " Instance Index = " << debug_record[kInstVertOutInstanceIndex] << ". ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001700 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001701 case spv::ExecutionModelTessellationControl: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001702 strm << "Stage = Tessellation Control. Invocation ID = " << debug_record[kInstTessCtlOutInvocationId]
1703 << ", Primitive ID = " << debug_record[kInstTessCtlOutPrimitiveId];
Karl Schultz7b024b42018-08-30 16:18:18 -06001704 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001705 case spv::ExecutionModelTessellationEvaluation: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001706 strm << "Stage = Tessellation Eval. Primitive ID = " << debug_record[kInstTessEvalOutPrimitiveId]
1707 << ", TessCoord (u, v) = (" << debug_record[kInstTessEvalOutTessCoordU] << ", "
1708 << debug_record[kInstTessEvalOutTessCoordV] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001709 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001710 case spv::ExecutionModelGeometry: {
Karl Schultz7b024b42018-08-30 16:18:18 -06001711 strm << "Stage = Geometry. Primitive ID = " << debug_record[kInstGeomOutPrimitiveId]
1712 << " Invocation ID = " << debug_record[kInstGeomOutInvocationId] << ". ";
1713 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001714 case spv::ExecutionModelFragment: {
Karl Schultz7b024b42018-08-30 16:18:18 -06001715 strm << "Stage = Fragment. Fragment coord (x,y) = ("
1716 << *reinterpret_cast<const float *>(&debug_record[kInstFragOutFragCoordX]) << ", "
1717 << *reinterpret_cast<const float *>(&debug_record[kInstFragOutFragCoordY]) << "). ";
1718 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001719 case spv::ExecutionModelGLCompute: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001720 strm << "Stage = Compute. Global invocation ID (x, y, z) = (" << debug_record[kInstCompOutGlobalInvocationIdX] << ", "
1721 << debug_record[kInstCompOutGlobalInvocationIdY] << ", " << debug_record[kInstCompOutGlobalInvocationIdZ] << " )";
Karl Schultz7b024b42018-08-30 16:18:18 -06001722 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001723 case spv::ExecutionModelRayGenerationNV: {
1724 strm << "Stage = Ray Generation. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1725 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1726 } break;
1727 case spv::ExecutionModelIntersectionNV: {
1728 strm << "Stage = Intersection. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1729 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1730 } break;
1731 case spv::ExecutionModelAnyHitNV: {
1732 strm << "Stage = Any Hit. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1733 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1734 } break;
1735 case spv::ExecutionModelClosestHitNV: {
1736 strm << "Stage = Closest Hit. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1737 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1738 } break;
1739 case spv::ExecutionModelMissNV: {
1740 strm << "Stage = Miss. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1741 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1742 } break;
1743 case spv::ExecutionModelCallableNV: {
1744 strm << "Stage = Callable. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1745 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1746 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001747 default: {
1748 strm << "Internal Error (unexpected stage = " << debug_record[kInstCommonOutStageIdx] << "). ";
1749 assert(false);
1750 } break;
1751 }
1752 msg = strm.str();
1753}
1754
1755// Generate the part of the message describing the violation.
1756static void GenerateValidationMessage(const uint32_t *debug_record, std::string &msg, std::string &vuid_msg) {
1757 using namespace spvtools;
1758 std::ostringstream strm;
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001759 switch (debug_record[kInst2ValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001760 case kInstErrorBindlessBounds: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001761 strm << "Index of " << debug_record[kInst2BindlessBoundsOutDescIndex] << " used to index descriptor array of length "
1762 << debug_record[kInst2BindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001763 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -06001764 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001765 case kInstErrorBindlessUninit: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001766 strm << "Descriptor index " << debug_record[kInst2BindlessUninitOutDescIndex] << " is uninitialized. ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001767 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -06001768 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001769 case kInstErrorBuffAddrUnallocRef: {
1770 uint64_t *ptr = (uint64_t *)&debug_record[kInst2BuffAddrUnallocOutDescPtrLo];
1771 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
1772 vuid_msg = "UNASSIGNED-Device address out of bounds";
1773 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001774 default: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001775 strm << "Internal Error (unexpected error type = " << debug_record[kInst2ValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001776 vuid_msg = "UNASSIGNED-Internal Error";
1777 assert(false);
1778 } break;
1779 }
1780 msg = strm.str();
1781}
1782
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001783static std::string LookupDebugUtilsName(const debug_report_data *report_data, const uint64_t object) {
Mark Lobodzinski1d7313a2019-02-07 11:04:42 -07001784 auto object_label = report_data->DebugReportGetUtilsObjectName(object);
1785 if (object_label != "") {
1786 object_label = "(" + object_label + ")";
Karl Schultz7b024b42018-08-30 16:18:18 -06001787 }
Mark Lobodzinski1d7313a2019-02-07 11:04:42 -07001788 return object_label;
Karl Schultz7b024b42018-08-30 16:18:18 -06001789}
1790
1791// Generate message from the common portion of the debug report record.
Mark Lobodzinski33a34b82019-04-25 11:38:36 -06001792static void GenerateCommonMessage(const debug_report_data *report_data, const CMD_BUFFER_STATE *cb_node,
1793 const uint32_t *debug_record, const VkShaderModule shader_module_handle,
Jason Macnak67407e72019-07-11 11:05:09 -07001794 const VkPipeline pipeline_handle, const VkPipelineBindPoint pipeline_bind_point,
1795 const uint32_t operation_index, std::string &msg) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001796 using namespace spvtools;
1797 std::ostringstream strm;
1798 if (shader_module_handle == VK_NULL_HANDLE) {
1799 strm << std::hex << std::showbase << "Internal Error: Unable to locate information for shader used in command buffer "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001800 << LookupDebugUtilsName(report_data, HandleToUint64(cb_node->commandBuffer)) << "("
Karl Schultz7b024b42018-08-30 16:18:18 -06001801 << HandleToUint64(cb_node->commandBuffer) << "). ";
1802 assert(true);
1803 } else {
1804 strm << std::hex << std::showbase << "Command buffer "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001805 << LookupDebugUtilsName(report_data, HandleToUint64(cb_node->commandBuffer)) << "("
Jason Macnak67407e72019-07-11 11:05:09 -07001806 << HandleToUint64(cb_node->commandBuffer) << "). ";
1807 if (pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1808 strm << "Draw ";
1809 } else if (pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1810 strm << "Compute ";
1811 } else if (pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1812 strm << "Ray Trace ";
1813 } else {
1814 assert(false);
1815 strm << "Unknown Pipeline Operation ";
1816 }
1817 strm << "Index " << operation_index << ". "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001818 << "Pipeline " << LookupDebugUtilsName(report_data, HandleToUint64(pipeline_handle)) << "("
Karl Schultz7b024b42018-08-30 16:18:18 -06001819 << HandleToUint64(pipeline_handle) << "). "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001820 << "Shader Module " << LookupDebugUtilsName(report_data, HandleToUint64(shader_module_handle)) << "("
Karl Schultz7b024b42018-08-30 16:18:18 -06001821 << HandleToUint64(shader_module_handle) << "). ";
1822 }
1823 strm << std::dec << std::noshowbase;
1824 strm << "Shader Instruction Index = " << debug_record[kInstCommonOutInstructionIdx] << ". ";
1825 msg = strm.str();
1826}
1827
1828// Read the contents of the SPIR-V OpSource instruction and any following continuation instructions.
1829// Split the single string into a vector of strings, one for each line, for easier processing.
Mark Lobodzinski3c59d972019-04-25 11:28:14 -06001830static void ReadOpSource(const SHADER_MODULE_STATE &shader, const uint32_t reported_file_id,
1831 std::vector<std::string> &opsource_lines) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001832 for (auto insn : shader) {
1833 if ((insn.opcode() == spv::OpSource) && (insn.len() >= 5) && (insn.word(3) == reported_file_id)) {
1834 std::istringstream in_stream;
1835 std::string cur_line;
1836 in_stream.str((char *)&insn.word(4));
1837 while (std::getline(in_stream, cur_line)) {
1838 opsource_lines.push_back(cur_line);
1839 }
1840 while ((++insn).opcode() == spv::OpSourceContinued) {
1841 in_stream.str((char *)&insn.word(1));
1842 while (std::getline(in_stream, cur_line)) {
1843 opsource_lines.push_back(cur_line);
1844 }
1845 }
1846 break;
1847 }
1848 }
1849}
Tony-LunarG03059b72019-02-19 13:57:41 -07001850
1851// The task here is to search the OpSource content to find the #line directive with the
1852// line number that is closest to, but still prior to the reported error line number and
1853// still within the reported filename.
1854// From this known position in the OpSource content we can add the difference between
1855// the #line line number and the reported error line number to determine the location
1856// in the OpSource content of the reported error line.
1857//
1858// Considerations:
1859// - Look only at #line directives that specify the reported_filename since
1860// the reported error line number refers to its location in the reported filename.
1861// - If a #line directive does not have a filename, the file is the reported filename, or
1862// the filename found in a prior #line directive. (This is C-preprocessor behavior)
1863// - It is possible (e.g., inlining) for blocks of code to get shuffled out of their
1864// original order and the #line directives are used to keep the numbering correct. This
1865// is why we need to examine the entire contents of the source, instead of leaving early
1866// when finding a #line line number larger than the reported error line number.
1867//
1868
1869// GCC 4.8 has a problem with std::regex that is fixed in GCC 4.9. Provide fallback code for 4.8
1870#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
1871
1872#if defined(__GNUC__) && GCC_VERSION < 40900
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001873static bool GetLineAndFilename(const std::string string, uint32_t *linenumber, std::string &filename) {
Tony-LunarG03059b72019-02-19 13:57:41 -07001874 // # line <linenumber> "<filename>" or
1875 // #line <linenumber> "<filename>"
1876 std::vector<std::string> tokens;
1877 std::stringstream stream(string);
1878 std::string temp;
1879 uint32_t line_index = 0;
1880
1881 while (stream >> temp) tokens.push_back(temp);
1882 auto size = tokens.size();
1883 if (size > 1) {
1884 if (tokens[0] == "#" && tokens[1] == "line") {
1885 line_index = 2;
1886 } else if (tokens[0] == "#line") {
1887 line_index = 1;
1888 }
1889 }
1890 if (0 == line_index) return false;
1891 *linenumber = std::stoul(tokens[line_index]);
1892 uint32_t filename_index = line_index + 1;
1893 // Remove enclosing double quotes around filename
1894 if (size > filename_index) filename = tokens[filename_index].substr(1, tokens[filename_index].size() - 2);
1895 return true;
1896}
1897#else
1898static bool GetLineAndFilename(const std::string string, uint32_t *linenumber, std::string &filename) {
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001899 static const std::regex line_regex( // matches #line directives
1900 "^" // beginning of line
1901 "\\s*" // optional whitespace
1902 "#" // required text
1903 "\\s*" // optional whitespace
1904 "line" // required text
1905 "\\s+" // required whitespace
1906 "([0-9]+)" // required first capture - line number
1907 "(\\s+)?" // optional second capture - whitespace
1908 "(\".+\")?" // optional third capture - quoted filename with at least one char inside
1909 ".*"); // rest of line (needed when using std::regex_match since the entire line is tested)
Karl Schultz7b024b42018-08-30 16:18:18 -06001910
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001911 std::smatch captures;
1912
1913 bool found_line = std::regex_match(string, captures, line_regex);
1914 if (!found_line) return false;
1915
1916 // filename is optional and considered found only if the whitespace and the filename are captured
1917 if (captures[2].matched && captures[3].matched) {
1918 // Remove enclosing double quotes. The regex guarantees the quotes and at least one char.
1919 filename = captures[3].str().substr(1, captures[3].str().size() - 2);
1920 }
1921 *linenumber = std::stoul(captures[1]);
1922 return true;
1923}
Tony-LunarG03059b72019-02-19 13:57:41 -07001924#endif // GCC_VERSION
1925
Karl Schultz7b024b42018-08-30 16:18:18 -06001926// Extract the filename, line number, and column number from the correct OpLine and build a message string from it.
1927// Scan the source (from OpSource) to find the line of source at the reported line number and place it in another message string.
1928static void GenerateSourceMessages(const std::vector<unsigned int> &pgm, const uint32_t *debug_record, std::string &filename_msg,
1929 std::string &source_msg) {
1930 using namespace spvtools;
1931 std::ostringstream filename_stream;
1932 std::ostringstream source_stream;
Mark Lobodzinski3c59d972019-04-25 11:28:14 -06001933 SHADER_MODULE_STATE shader;
Karl Schultz7b024b42018-08-30 16:18:18 -06001934 shader.words = pgm;
1935 // Find the OpLine just before the failing instruction indicated by the debug info.
1936 // SPIR-V can only be iterated in the forward direction due to its opcode/length encoding.
1937 uint32_t instruction_index = 0;
1938 uint32_t reported_file_id = 0;
1939 uint32_t reported_line_number = 0;
1940 uint32_t reported_column_number = 0;
1941 if (shader.words.size() > 0) {
1942 for (auto insn : shader) {
1943 if (insn.opcode() == spv::OpLine) {
1944 reported_file_id = insn.word(1);
1945 reported_line_number = insn.word(2);
1946 reported_column_number = insn.word(3);
1947 }
1948 if (instruction_index == debug_record[kInstCommonOutInstructionIdx]) {
1949 break;
1950 }
1951 instruction_index++;
1952 }
1953 }
1954 // Create message with file information obtained from the OpString pointed to by the discovered OpLine.
1955 std::string reported_filename;
1956 if (reported_file_id == 0) {
1957 filename_stream
1958 << "Unable to find SPIR-V OpLine for source information. Build shader with debug info to get source information.";
1959 } else {
1960 bool found_opstring = false;
1961 for (auto insn : shader) {
1962 if ((insn.opcode() == spv::OpString) && (insn.len() >= 3) && (insn.word(1) == reported_file_id)) {
1963 found_opstring = true;
1964 reported_filename = (char *)&insn.word(2);
1965 if (reported_filename.empty()) {
1966 filename_stream << "Shader validation error occurred at line " << reported_line_number;
1967 } else {
1968 filename_stream << "Shader validation error occurred in file: " << reported_filename << " at line "
1969 << reported_line_number;
1970 }
1971 if (reported_column_number > 0) {
1972 filename_stream << ", column " << reported_column_number;
1973 }
1974 filename_stream << ".";
1975 break;
1976 }
1977 }
1978 if (!found_opstring) {
1979 filename_stream << "Unable to find SPIR-V OpString for file id " << reported_file_id << " from OpLine instruction.";
1980 }
1981 }
1982 filename_msg = filename_stream.str();
1983
1984 // Create message to display source code line containing error.
1985 if ((reported_file_id != 0)) {
1986 // Read the source code and split it up into separate lines.
1987 std::vector<std::string> opsource_lines;
1988 ReadOpSource(shader, reported_file_id, opsource_lines);
1989 // Find the line in the OpSource content that corresponds to the reported error file and line.
1990 if (!opsource_lines.empty()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001991 uint32_t saved_line_number = 0;
1992 std::string current_filename = reported_filename; // current "preprocessor" filename state.
1993 std::vector<std::string>::size_type saved_opsource_offset = 0;
1994 bool found_best_line = false;
1995 for (auto it = opsource_lines.begin(); it != opsource_lines.end(); ++it) {
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001996 uint32_t parsed_line_number;
1997 std::string parsed_filename;
1998 bool found_line = GetLineAndFilename(*it, &parsed_line_number, parsed_filename);
Karl Schultz7b024b42018-08-30 16:18:18 -06001999 if (!found_line) continue;
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07002000
2001 bool found_filename = parsed_filename.size() > 0;
Karl Schultz7b024b42018-08-30 16:18:18 -06002002 if (found_filename) {
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07002003 current_filename = parsed_filename;
Karl Schultz7b024b42018-08-30 16:18:18 -06002004 }
2005 if ((!found_filename) || (current_filename == reported_filename)) {
Karl Schultz7b024b42018-08-30 16:18:18 -06002006 // Update the candidate best line directive, if the current one is prior and closer to the reported line
2007 if (reported_line_number >= parsed_line_number) {
2008 if (!found_best_line ||
2009 (reported_line_number - parsed_line_number <= reported_line_number - saved_line_number)) {
2010 saved_line_number = parsed_line_number;
2011 saved_opsource_offset = std::distance(opsource_lines.begin(), it);
2012 found_best_line = true;
2013 }
2014 }
2015 }
2016 }
2017 if (found_best_line) {
2018 assert(reported_line_number >= saved_line_number);
2019 std::vector<std::string>::size_type opsource_index =
2020 (reported_line_number - saved_line_number) + 1 + saved_opsource_offset;
2021 if (opsource_index < opsource_lines.size()) {
2022 source_stream << "\n" << reported_line_number << ": " << opsource_lines[opsource_index].c_str();
2023 } else {
2024 source_stream << "Internal error: calculated source line of " << opsource_index << " for source size of "
2025 << opsource_lines.size() << " lines.";
2026 }
2027 } else {
2028 source_stream << "Unable to find suitable #line directive in SPIR-V OpSource.";
2029 }
2030 } else {
2031 source_stream << "Unable to find SPIR-V OpSource.";
2032 }
2033 }
2034 source_msg = source_stream.str();
2035}
2036
2037// Pull together all the information from the debug record to build the error message strings,
2038// and then assemble them into a single message string.
2039// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
2040// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
2041// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
2042// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
2043//
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002044void GpuAssisted::AnalyzeAndReportError(CMD_BUFFER_STATE *cb_node, VkQueue queue, VkPipelineBindPoint pipeline_bind_point,
2045 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06002046 using namespace spvtools;
2047 const uint32_t total_words = debug_output_buffer[0];
2048 // A zero here means that the shader instrumentation didn't write anything.
2049 // If you have nothing to say, don't say it here.
2050 if (0 == total_words) {
2051 return;
2052 }
2053 // The first word in the debug output buffer is the number of words that would have
2054 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
2055 // The number of words actually written by the shaders is determined by the size of the buffer
2056 // we provide via the descriptor. So, we process only the number of words that can fit in the
2057 // buffer.
2058 // Each "report" written by the shader instrumentation is considered a "record". This function
2059 // is hard-coded to process only one record because it expects the buffer to be large enough to
2060 // hold only one record. If there is a desire to process more than one record, this function needs
2061 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06002062 std::string validation_message;
2063 std::string stage_message;
2064 std::string common_message;
2065 std::string filename_message;
2066 std::string source_message;
2067 std::string vuid_msg;
2068 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
2069 VkPipeline pipeline_handle = VK_NULL_HANDLE;
2070 std::vector<unsigned int> pgm;
2071 // The first record starts at this offset after the total_words.
2072 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
2073 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
2074 // by the instrumented shader.
Tony-LunarG99b880b2019-09-26 11:19:52 -06002075 auto it = shader_map.find(debug_record[kInstCommonOutShaderId]);
2076 if (it != shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06002077 shader_module_handle = it->second.shader_module;
2078 pipeline_handle = it->second.pipeline;
2079 pgm = it->second.pgm;
2080 }
2081 GenerateValidationMessage(debug_record, validation_message, vuid_msg);
2082 GenerateStageMessage(debug_record, stage_message);
Jason Macnak67407e72019-07-11 11:05:09 -07002083 GenerateCommonMessage(report_data, cb_node, debug_record, shader_module_handle, pipeline_handle, pipeline_bind_point,
2084 operation_index, common_message);
Karl Schultz7b024b42018-08-30 16:18:18 -06002085 GenerateSourceMessages(pgm, debug_record, filename_message, source_message);
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002086 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 -06002087 vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
2088 filename_message.c_str(), source_message.c_str());
2089 // The debug record at word kInstCommonOutSize is the number of words in the record
2090 // written by the shader. Clear the entire record plus the total_words word at the start.
Tony-LunarG751ebbe2019-07-24 16:41:36 -06002091 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], (uint32_t)kInst2MaxOutCnt);
Karl Schultz7b024b42018-08-30 16:18:18 -06002092 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
2093}
2094
Tony-LunarG5ad17272019-03-05 12:48:24 -07002095// For the given command buffer, map its debug data buffers and read their contents for analysis.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002096void GpuAssisted::ProcessInstrumentationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Petr Kraus6c4bdce2019-08-27 17:35:01 +02002097 if (cb_node && (cb_node->hasDrawCmd || cb_node->hasTraceRaysCmd || cb_node->hasDispatchCmd)) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002098 auto gpu_buffer_list = GetGpuAssistedBufferInfo(cb_node->commandBuffer);
Tony-LunarG5ad17272019-03-05 12:48:24 -07002099 uint32_t draw_index = 0;
Jason Macnak67407e72019-07-11 11:05:09 -07002100 uint32_t compute_index = 0;
2101 uint32_t ray_trace_index = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002102
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002103 for (auto &buffer_info : gpu_buffer_list) {
Petr Kraus6c4bdce2019-08-27 17:35:01 +02002104 char *pData;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002105 VkResult result = vmaMapMemory(vmaAllocator, buffer_info.output_mem_block.allocation, (void **)&pData);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002106 // Analyze debug output buffer
2107 if (result == VK_SUCCESS) {
Jason Macnak67407e72019-07-11 11:05:09 -07002108 uint32_t operation_index = 0;
2109 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
2110 operation_index = draw_index;
2111 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
2112 operation_index = compute_index;
2113 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
2114 operation_index = ray_trace_index;
2115 } else {
2116 assert(false);
2117 }
2118
2119 AnalyzeAndReportError(cb_node, queue, buffer_info.pipeline_bind_point, operation_index, (uint32_t *)pData);
Tony-LunarG99b880b2019-09-26 11:19:52 -06002120 vmaUnmapMemory(vmaAllocator, buffer_info.output_mem_block.allocation);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002121 }
Jason Macnak67407e72019-07-11 11:05:09 -07002122
2123 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
2124 draw_index++;
2125 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
2126 compute_index++;
2127 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
2128 ray_trace_index++;
2129 } else {
2130 assert(false);
2131 }
Karl Schultz7b024b42018-08-30 16:18:18 -06002132 }
2133 }
2134}
2135
Tony-LunarG81efe392019-03-07 15:43:27 -07002136// 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 -06002137void GpuAssisted::UpdateInstrumentationBuffer(CMD_BUFFER_STATE *cb_node) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002138 auto gpu_buffer_list = GetGpuAssistedBufferInfo(cb_node->commandBuffer);
Tony-LunarG81efe392019-03-07 15:43:27 -07002139 uint32_t *pData;
2140 for (auto &buffer_info : gpu_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002141 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002142 VkResult result = vmaMapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation, (void **)&pData);
Tony-LunarG81efe392019-03-07 15:43:27 -07002143 if (result == VK_SUCCESS) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002144 for (auto update : buffer_info.di_input_mem_block.update_at_submit) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002145 if (update.second->updated) pData[update.first] = 1;
2146 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06002147 vmaUnmapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07002148 }
2149 }
2150 }
2151}
2152
Karl Schultz58674242019-01-22 15:35:02 -07002153// Submit a memory barrier on graphics queues.
2154// Lazy-create and record the needed command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002155void GpuAssisted::SubmitBarrier(VkQueue queue) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002156 auto queue_barrier_command_info_it = queue_barrier_command_infos.emplace(queue, GpuAssistedQueueBarrierCommandInfo{});
Jason Macnak8eae5722019-07-17 15:17:45 -07002157 if (queue_barrier_command_info_it.second) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002158 GpuAssistedQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_it.first->second;
Karl Schultz58674242019-01-22 15:35:02 -07002159
Jason Macnak8eae5722019-07-17 15:17:45 -07002160 uint32_t queue_family_index = 0;
Karl Schultz58674242019-01-22 15:35:02 -07002161
Jason Macnak8eae5722019-07-17 15:17:45 -07002162 auto queue_state_it = queueMap.find(queue);
2163 if (queue_state_it != queueMap.end()) {
2164 queue_family_index = queue_state_it->second.queueFamilyIndex;
2165 }
Karl Schultz58674242019-01-22 15:35:02 -07002166
Jason Macnak8eae5722019-07-17 15:17:45 -07002167 VkResult result = VK_SUCCESS;
2168
Karl Schultz58674242019-01-22 15:35:02 -07002169 VkCommandPoolCreateInfo pool_create_info = {};
2170 pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
2171 pool_create_info.queueFamilyIndex = queue_family_index;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002172 result = DispatchCreateCommandPool(device, &pool_create_info, nullptr, &queue_barrier_command_info.barrier_command_pool);
Karl Schultz58674242019-01-22 15:35:02 -07002173 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002174 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz58674242019-01-22 15:35:02 -07002175 "Unable to create command pool for barrier CB.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002176 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
Karl Schultz58674242019-01-22 15:35:02 -07002177 return;
2178 }
2179
Jason Macnak8eae5722019-07-17 15:17:45 -07002180 VkCommandBufferAllocateInfo buffer_alloc_info = {};
2181 buffer_alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002182 buffer_alloc_info.commandPool = queue_barrier_command_info.barrier_command_pool;
Jason Macnak8eae5722019-07-17 15:17:45 -07002183 buffer_alloc_info.commandBufferCount = 1;
2184 buffer_alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002185 result = DispatchAllocateCommandBuffers(device, &buffer_alloc_info, &queue_barrier_command_info.barrier_command_buffer);
Karl Schultz58674242019-01-22 15:35:02 -07002186 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002187 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz58674242019-01-22 15:35:02 -07002188 "Unable to create barrier command buffer.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002189 DispatchDestroyCommandPool(device, queue_barrier_command_info.barrier_command_pool, nullptr);
2190 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
2191 queue_barrier_command_info.barrier_command_buffer = VK_NULL_HANDLE;
Karl Schultz58674242019-01-22 15:35:02 -07002192 return;
2193 }
2194
2195 // Hook up command buffer dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -06002196 vkSetDeviceLoaderData(device, queue_barrier_command_info.barrier_command_buffer);
Karl Schultz58674242019-01-22 15:35:02 -07002197
2198 // Record a global memory barrier to force availability of device memory operations to the host domain.
2199 VkCommandBufferBeginInfo command_buffer_begin_info = {};
2200 command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002201 result = DispatchBeginCommandBuffer(queue_barrier_command_info.barrier_command_buffer, &command_buffer_begin_info);
Karl Schultz58674242019-01-22 15:35:02 -07002202 if (result == VK_SUCCESS) {
2203 VkMemoryBarrier memory_barrier = {};
2204 memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2205 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
2206 memory_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
2207
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002208 DispatchCmdPipelineBarrier(queue_barrier_command_info.barrier_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
Mark Lobodzinskie514d1a2019-03-12 08:47:45 -06002209 VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &memory_barrier, 0, nullptr, 0, nullptr);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002210 DispatchEndCommandBuffer(queue_barrier_command_info.barrier_command_buffer);
Karl Schultz58674242019-01-22 15:35:02 -07002211 }
2212 }
2213
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002214 GpuAssistedQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_it.first->second;
2215 if (queue_barrier_command_info.barrier_command_buffer != VK_NULL_HANDLE) {
Karl Schultz58674242019-01-22 15:35:02 -07002216 VkSubmitInfo submit_info = {};
2217 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2218 submit_info.commandBufferCount = 1;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002219 submit_info.pCommandBuffers = &queue_barrier_command_info.barrier_command_buffer;
Tony-LunarG152a88b2019-03-20 15:42:24 -06002220 DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
Karl Schultz58674242019-01-22 15:35:02 -07002221 }
2222}
2223
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002224void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002225 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
2226 const VkSubmitInfo *submit = &pSubmits[submit_idx];
2227 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06002228 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07002229 UpdateInstrumentationBuffer(cb_node);
2230 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
2231 UpdateInstrumentationBuffer(secondaryCmdBuffer);
2232 }
2233 }
2234 }
2235}
2236
Karl Schultz58674242019-01-22 15:35:02 -07002237// Issue a memory barrier to make GPU-written data available to host.
2238// Wait for the queue to complete execution.
2239// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002240void GpuAssisted::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
2241 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002242 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002243
Tony-LunarG99b880b2019-09-26 11:19:52 -06002244 if (aborted) return;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06002245 bool buffers_present = false;
2246 // Don't QueueWaitIdle if there's nothing to process
2247 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
2248 const VkSubmitInfo *submit = &pSubmits[submit_idx];
2249 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
2250 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG99b880b2019-09-26 11:19:52 -06002251 if (GetGpuAssistedBufferInfo(cb_node->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd)
Jason Macnak83cfd582019-07-31 10:14:24 -07002252 buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06002253 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002254 if (GetGpuAssistedBufferInfo(secondaryCmdBuffer->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd)
Jason Macnak83cfd582019-07-31 10:14:24 -07002255 buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06002256 }
2257 }
2258 }
2259 if (!buffers_present) return;
Karl Schultz58674242019-01-22 15:35:02 -07002260
Mark Lobodzinskie377ac32019-03-07 16:12:46 -07002261 SubmitBarrier(queue);
Karl Schultz58674242019-01-22 15:35:02 -07002262
Tony-LunarG152a88b2019-03-20 15:42:24 -06002263 DispatchQueueWaitIdle(queue);
Karl Schultz58674242019-01-22 15:35:02 -07002264
Karl Schultz7b024b42018-08-30 16:18:18 -06002265 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
2266 const VkSubmitInfo *submit = &pSubmits[submit_idx];
2267 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06002268 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Mark Lobodzinskie377ac32019-03-07 16:12:46 -07002269 ProcessInstrumentationBuffer(queue, cb_node);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002270 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06002271 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Mark Lobodzinskie377ac32019-03-07 16:12:46 -07002272 ProcessInstrumentationBuffer(queue, secondaryCmdBuffer);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002273 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06002274 }
2275 }
2276 }
2277}
Tony-LunarGb2501d22019-01-28 09:59:13 -07002278
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002279void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
2280 uint32_t firstVertex, uint32_t firstInstance) {
2281 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2282}
2283
2284void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
2285 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
2286 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2287}
2288
2289void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
2290 uint32_t stride) {
2291 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2292}
2293
2294void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
2295 uint32_t count, uint32_t stride) {
2296 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2297}
2298
2299void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
2300 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
2301}
2302
2303void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
2304 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
2305}
2306
2307void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
2308 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
2309 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
2310 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
2311 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
2312 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
2313 uint32_t width, uint32_t height, uint32_t depth) {
2314 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
2315}
2316
2317void GpuAssisted::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
2318 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
2319 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
2320 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
2321 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
2322 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
2323 uint32_t width, uint32_t height, uint32_t depth) {
2324 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
2325 cb_state->hasTraceRaysCmd = true;
2326}
2327
2328void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Jason Macnak67407e72019-07-11 11:05:09 -07002329 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
2330 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
andreygca287f22019-04-10 00:15:33 +03002331 return;
2332 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002333 VkResult result;
2334
Tony-LunarG99b880b2019-09-26 11:19:52 -06002335 if (aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002336
2337 std::vector<VkDescriptorSet> desc_sets;
2338 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002339 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002340 assert(result == VK_SUCCESS);
2341 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002342 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Tony-LunarGb2501d22019-01-28 09:59:13 -07002343 "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002344 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002345 return;
2346 }
2347
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002348 VkDescriptorBufferInfo output_desc_buffer_info = {};
Tony-LunarG99b880b2019-09-26 11:19:52 -06002349 output_desc_buffer_info.range = output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002350
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06002351 auto cb_node = GetCBState(cmd_buffer);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002352 if (!cb_node) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002353 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device), "Unrecognized command buffer");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002354 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002355 return;
2356 }
2357
Tony-LunarG81efe392019-03-07 15:43:27 -07002358 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002359 GpuAssistedDeviceMemoryBlock output_block = {};
Tony-LunarG0e564722019-03-19 16:09:14 -06002360 VkBufferCreateInfo bufferInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
Tony-LunarG99b880b2019-09-26 11:19:52 -06002361 bufferInfo.size = output_buffer_size;
Tony-LunarG0e564722019-03-19 16:09:14 -06002362 bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
2363 VmaAllocationCreateInfo allocInfo = {};
2364 allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002365 result = vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002366 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002367 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Tony-LunarGb2501d22019-01-28 09:59:13 -07002368 "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002369 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002370 return;
2371 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002372
Tony-LunarG81efe392019-03-07 15:43:27 -07002373 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGa77cade2019-03-06 10:49:22 -07002374 uint32_t *pData;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002375 result = vmaMapMemory(vmaAllocator, output_block.allocation, (void **)&pData);
Tony-LunarG0e564722019-03-19 16:09:14 -06002376 if (result == VK_SUCCESS) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002377 memset(pData, 0, output_buffer_size);
2378 vmaUnmapMemory(vmaAllocator, output_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002379 }
Tony-LunarG81efe392019-03-07 15:43:27 -07002380
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002381 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002382 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
2383 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
2384 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002385 uint32_t desc_count = 1;
2386 auto const &state = cb_node->lastBound[bind_point];
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002387 uint32_t number_of_sets = (uint32_t)state.per_set.size();
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002388
Tony-LunarG81efe392019-03-07 15:43:27 -07002389 // Figure out how much memory we need for the input block based on how many sets and bindings there are
2390 // and how big each of the bindings is
Mark Lobodzinskif45e45f2019-04-19 14:15:39 -06002391 if (number_of_sets > 0 && device_extensions.vk_ext_descriptor_indexing) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002392 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
2393 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002394 for (auto s : state.per_set) {
2395 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06002396 if (desc && (desc->GetBindingCount() > 0)) {
2397 auto bindings = desc->GetLayout()->GetSortedBindingSet();
Tony-LunarGa77cade2019-03-06 10:49:22 -07002398 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
2399 for (auto binding : bindings) {
Tony-LunarG7564b382019-08-21 10:11:35 -06002400 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2401 // blocks
2402 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2403 descriptor_count++;
2404 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
2405 VK_NULL_HANDLE, "UNASSIGNED-GPU-Assisted Validation Warning",
2406 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
2407 "validation");
2408 } else if (binding == desc->GetLayout()->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002409 descriptor_count += desc->GetVariableDescriptorCount();
2410 } else {
2411 descriptor_count += desc->GetDescriptorCountFromBinding(binding);
2412 }
2413 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002414 }
2415 }
2416
Tony-LunarGa77cade2019-03-06 10:49:22 -07002417 // Note that the size of the input buffer is dependent on the maximum binding number, which
2418 // can be very large. This is because for (set = s, binding = b, index = i), the validation
2419 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
2420 // see if descriptors have been written. In gpu_validation.md, we note this and advise
2421 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
2422 uint32_t words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002423 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2424 bufferInfo.size = words_needed * 4;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002425 result =
2426 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &di_input_block.buffer, &di_input_block.allocation, nullptr);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002427 if (result != VK_SUCCESS) {
2428 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
2429 "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002430 aborted = true;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002431 return;
2432 }
2433
Tony-LunarGa77cade2019-03-06 10:49:22 -07002434 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
2435 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
2436 // outline of the input buffer format
Tony-LunarG99b880b2019-09-26 11:19:52 -06002437 result = vmaMapMemory(vmaAllocator, di_input_block.allocation, (void **)&pData);
Tony-LunarG76cdcac2019-05-22 16:13:12 -06002438 memset(pData, 0, static_cast<size_t>(bufferInfo.size));
Tony-LunarGa77cade2019-03-06 10:49:22 -07002439 // Pointer to a sets array that points into the sizes array
2440 uint32_t *sets_to_sizes = pData + 1;
2441 // Pointer to the sizes array that contains the array size of the descriptor at each binding
2442 uint32_t *sizes = sets_to_sizes + number_of_sets;
2443 // Pointer to another sets array that points into the bindings array that points into the written array
2444 uint32_t *sets_to_bindings = sizes + binding_count;
2445 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
2446 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
2447 // Index of the next entry in the written array to be updated
2448 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002449 uint32_t bindCounter = number_of_sets + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07002450 // Index of the start of the sets_to_bindings array
2451 pData[0] = number_of_sets + binding_count + 1;
2452
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002453 for (auto s : state.per_set) {
2454 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06002455 if (desc && (desc->GetBindingCount() > 0)) {
2456 auto layout = desc->GetLayout();
2457 auto bindings = layout->GetSortedBindingSet();
Tony-LunarG81efe392019-03-07 15:43:27 -07002458 // For each set, fill in index of its bindings sizes in the sizes array
Tony-LunarGa77cade2019-03-06 10:49:22 -07002459 *sets_to_sizes++ = bindCounter;
Tony-LunarG81efe392019-03-07 15:43:27 -07002460 // For each set, fill in the index of its bindings in the bindings_to_written array
Tony-LunarGa77cade2019-03-06 10:49:22 -07002461 *sets_to_bindings++ = bindCounter + number_of_sets + binding_count;
Tony-LunarG81efe392019-03-07 15:43:27 -07002462 for (auto binding : bindings) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002463 // For each binding, fill in its size in the sizes array
Tony-LunarG7564b382019-08-21 10:11:35 -06002464 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2465 // blocks
2466 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2467 sizes[binding] = 1;
2468 } else if (binding == layout->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002469 sizes[binding] = desc->GetVariableDescriptorCount();
2470 } else {
2471 sizes[binding] = desc->GetDescriptorCountFromBinding(binding);
2472 }
2473 // Fill in the starting index for this binding in the written array in the bindings_to_written array
2474 bindings_to_written[binding] = written_index;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002475
Tony-LunarG7564b382019-08-21 10:11:35 -06002476 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2477 // blocks
2478 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2479 pData[written_index++] = 1;
2480 continue;
2481 }
2482
Tony-LunarGa77cade2019-03-06 10:49:22 -07002483 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
2484 // For each array element in the binding, update the written array with whether it has been written
2485 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
2486 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
Tony-LunarG81efe392019-03-07 15:43:27 -07002487 if (descriptor->updated) {
2488 pData[written_index] = 1;
2489 } else if (desc->IsUpdateAfterBind(binding)) {
2490 // 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 -06002491 di_input_block.update_at_submit[written_index] = descriptor;
Tony-LunarG81efe392019-03-07 15:43:27 -07002492 }
Tony-LunarGa77cade2019-03-06 10:49:22 -07002493 written_index++;
2494 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002495 }
Tony-LunarG81efe392019-03-07 15:43:27 -07002496 auto last = desc->GetLayout()->GetMaxBinding();
2497 bindings_to_written += last + 1;
2498 bindCounter += last + 1;
2499 sizes += last + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07002500 } else {
2501 *sets_to_sizes++ = 0;
2502 *sets_to_bindings++ = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002503 }
2504 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06002505 vmaUnmapMemory(vmaAllocator, di_input_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002506
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002507 di_input_desc_buffer_info.range = (words_needed * 4);
2508 di_input_desc_buffer_info.buffer = di_input_block.buffer;
2509 di_input_desc_buffer_info.offset = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002510
2511 desc_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2512 desc_writes[1].dstBinding = 1;
2513 desc_writes[1].descriptorCount = 1;
2514 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002515 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002516 desc_writes[1].dstSet = desc_sets[0];
2517
2518 desc_count = 2;
Tony-LunarG0e564722019-03-19 16:09:14 -06002519 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002520
Tony-LunarG7e0842f2019-12-10 09:26:34 -07002521 if (number_of_sets > 0 && (device_extensions.vk_ext_buffer_device_address || device_extensions.vk_khr_buffer_device_address) &&
2522 buffer_map.size() && shaderInt64) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002523 // Example BDA input buffer assuming 2 buffers using BDA:
2524 // Word 0 | Index of start of buffer sizes (in this case 5)
2525 // Word 1 | 0x0000000000000000
2526 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
2527 // Word 3 | Device Address of second buffer
2528 // Word 4 | 0xffffffffffffffff
2529 // Word 5 | 0 (size of pretend buffer at word 1)
2530 // Word 6 | Size in bytes of first buffer
2531 // Word 7 | Size in bytes of second buffer
2532 // Word 8 | 0 (size of pretend buffer in word 4)
2533
Tony-LunarG99b880b2019-09-26 11:19:52 -06002534 uint32_t num_buffers = static_cast<uint32_t>(buffer_map.size());
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002535 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
2536 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2537 bufferInfo.size = words_needed * 8; // 64 bit words
Tony-LunarG99b880b2019-09-26 11:19:52 -06002538 result =
2539 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &bda_input_block.buffer, &bda_input_block.allocation, nullptr);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002540 if (result != VK_SUCCESS) {
2541 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
2542 "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002543 aborted = true;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002544 return;
2545 }
2546 uint64_t *bda_data;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002547 result = vmaMapMemory(vmaAllocator, bda_input_block.allocation, (void **)&bda_data);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002548 uint32_t address_index = 1;
2549 uint32_t size_index = 3 + num_buffers;
2550 memset(bda_data, 0, static_cast<size_t>(bufferInfo.size));
2551 bda_data[0] = size_index; // Start of buffer sizes
2552 bda_data[address_index++] = 0; // NULL address
2553 bda_data[size_index++] = 0;
2554
Tony-LunarG99b880b2019-09-26 11:19:52 -06002555 for (auto const &value : buffer_map) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002556 bda_data[address_index++] = value.first;
2557 bda_data[size_index++] = value.second;
2558 }
2559 bda_data[address_index] = UINTPTR_MAX;
2560 bda_data[size_index] = 0;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002561 vmaUnmapMemory(vmaAllocator, bda_input_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002562
2563 bda_input_desc_buffer_info.range = (words_needed * 8);
2564 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
2565 bda_input_desc_buffer_info.offset = 0;
2566
2567 desc_writes[desc_count].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2568 desc_writes[desc_count].dstBinding = 2;
2569 desc_writes[desc_count].descriptorCount = 1;
2570 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2571 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
2572 desc_writes[desc_count].dstSet = desc_sets[0];
2573 desc_count++;
2574 }
2575
Tony-LunarGb2501d22019-01-28 09:59:13 -07002576 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002577 output_desc_buffer_info.buffer = output_block.buffer;
2578 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002579
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002580 desc_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2581 desc_writes[0].descriptorCount = 1;
2582 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2583 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
2584 desc_writes[0].dstSet = desc_sets[0];
2585 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002586
andreyg25ce2622019-04-05 23:07:59 +03002587 auto iter = cb_node->lastBound.find(bind_point); // find() allows read-only access to cb_state
Tony-LunarGb2501d22019-01-28 09:59:13 -07002588 if (iter != cb_node->lastBound.end()) {
2589 auto pipeline_state = iter->second.pipeline_state;
Jeff Bolze7fc67b2019-10-04 12:29:31 -05002590 if (pipeline_state && (pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index)) {
2591 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout, desc_set_bind_index, 1,
Tony-LunarG99b880b2019-09-26 11:19:52 -06002592 desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002593 }
Tony-LunarG0e564722019-03-19 16:09:14 -06002594 // Record buffer and memory info in CB state tracking
Tony-LunarG99b880b2019-09-26 11:19:52 -06002595 GetGpuAssistedBufferInfo(cmd_buffer)
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002596 .emplace_back(output_block, di_input_block, bda_input_block, desc_sets[0], desc_pool, bind_point);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002597 } else {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002598 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device), "Unable to find pipeline state");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002599 vmaDestroyBuffer(vmaAllocator, di_input_block.buffer, di_input_block.allocation);
2600 vmaDestroyBuffer(vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
2601 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
2602 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002603 return;
2604 }
2605}