blob: 88ff748ed577ae46f58b6e278a24ad1073360a4a [file] [log] [blame]
Karl Schultz7b024b42018-08-30 16:18:18 -06001/* Copyright (c) 2018-2019 The Khronos Group Inc.
2 * Copyright (c) 2018-2019 Valve Corporation
3 * Copyright (c) 2018-2019 LunarG, Inc.
Karl Schultz7b024b42018-08-30 16:18:18 -06004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060017 * Author: Karl Schultz <karl@lunarg.com>
18 * Author: Tony Barbour <tony@lunarg.com>
Karl Schultz7b024b42018-08-30 16:18:18 -060019 */
20
21// Allow use of STL min and max functions in Windows
22#define NOMINMAX
Tony-LunarG0e564722019-03-19 16:09:14 -060023// This define indicates to build the VMA routines themselves
24#define VMA_IMPLEMENTATION
25// This define indicates that we will supply Vulkan function pointers at initialization
26#define VMA_STATIC_VULKAN_FUNCTIONS 0
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -070027#include "gpu_validation.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060028#include "shader_validation.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060029#include "spirv-tools/libspirv.h"
30#include "spirv-tools/optimizer.hpp"
31#include "spirv-tools/instrument.hpp"
32#include <SPIRV/spirv.hpp>
33#include <algorithm>
34#include <regex>
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060035#include "layer_chassis_dispatch.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060036
37// This is the number of bindings in the debug descriptor set.
Tony-LunarG8eb5a002019-07-25 16:49:00 -060038static const uint32_t kNumBindingsInSet = 3;
Karl Schultz7b024b42018-08-30 16:18:18 -060039
Jason Macnak67407e72019-07-11 11:05:09 -070040static const VkShaderStageFlags kShaderStageAllRayTracing =
41 VK_SHADER_STAGE_ANY_HIT_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV | VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV |
42 VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV | VK_SHADER_STAGE_RAYGEN_BIT_NV;
43
Jason Macnak83cfd582019-07-31 10:14:24 -070044// Keep in sync with the GLSL shader below.
45struct GpuAccelerationStructureBuildValidationBuffer {
46 uint32_t instances_to_validate;
47 uint32_t replacement_handle_bits_0;
48 uint32_t replacement_handle_bits_1;
49 uint32_t invalid_handle_found;
50 uint32_t invalid_handle_bits_0;
51 uint32_t invalid_handle_bits_1;
52 uint32_t valid_handles_count;
53};
54
55// This is the GLSL source for the compute shader that is used during ray tracing acceleration structure
56// building validation which inspects instance buffers for top level acceleration structure builds and
57// reports and replaces invalid bottom level acceleration structure handles with good bottom level
58// acceleration structure handle so that applications can continue without undefined behavior long enough
59// to report errors.
60//
61// #version 450
62// layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
63// struct VkGeometryInstanceNV {
64// uint unused[14];
65// uint handle_bits_0;
66// uint handle_bits_1;
67// };
68// layout(set=0, binding=0, std430) buffer InstanceBuffer {
69// VkGeometryInstanceNV instances[];
70// };
71// layout(set=0, binding=1, std430) buffer ValidationBuffer {
72// uint instances_to_validate;
73// uint replacement_handle_bits_0;
74// uint replacement_handle_bits_1;
75// uint invalid_handle_found;
76// uint invalid_handle_bits_0;
77// uint invalid_handle_bits_1;
78// uint valid_handles_count;
79// uint valid_handles[];
80// };
81// void main() {
82// for (uint instance_index = 0; instance_index < instances_to_validate; instance_index++) {
83// uint instance_handle_bits_0 = instances[instance_index].handle_bits_0;
84// uint instance_handle_bits_1 = instances[instance_index].handle_bits_1;
85// bool valid = false;
86// for (uint valid_handle_index = 0; valid_handle_index < valid_handles_count; valid_handle_index++) {
87// if (instance_handle_bits_0 == valid_handles[2*valid_handle_index+0] &&
88// instance_handle_bits_1 == valid_handles[2*valid_handle_index+1]) {
89// valid = true;
90// break;
91// }
92// }
93// if (!valid) {
94// invalid_handle_found += 1;
95// invalid_handle_bits_0 = instance_handle_bits_0;
96// invalid_handle_bits_1 = instance_handle_bits_1;
97// instances[instance_index].handle_bits_0 = replacement_handle_bits_0;
98// instances[instance_index].handle_bits_1 = replacement_handle_bits_1;
99// }
100// }
101// }
102//
103// To regenerate the spirv below:
104// 1. Save the above GLSL source to a file called validation_shader.comp.
105// 2. Run in terminal
106//
107// glslangValidator.exe -x -V validation_shader.comp -o validation_shader.comp.spv
108//
109// 4. Copy-paste the contents of validation_shader.comp.spv here (clang-format will fix up the alignment).
110static const uint32_t kComputeShaderSpirv[] = {
111 0x07230203, 0x00010000, 0x00080007, 0x0000006d, 0x00000000, 0x00020011, 0x00000001, 0x0006000b, 0x00000001, 0x4c534c47,
112 0x6474732e, 0x3035342e, 0x00000000, 0x0003000e, 0x00000000, 0x00000001, 0x0005000f, 0x00000005, 0x00000004, 0x6e69616d,
113 0x00000000, 0x00060010, 0x00000004, 0x00000011, 0x00000001, 0x00000001, 0x00000001, 0x00030003, 0x00000002, 0x000001c2,
114 0x00040005, 0x00000004, 0x6e69616d, 0x00000000, 0x00060005, 0x00000008, 0x74736e69, 0x65636e61, 0x646e695f, 0x00007865,
115 0x00070005, 0x00000011, 0x696c6156, 0x69746164, 0x75426e6f, 0x72656666, 0x00000000, 0x00090006, 0x00000011, 0x00000000,
116 0x74736e69, 0x65636e61, 0x6f745f73, 0x6c61765f, 0x74616469, 0x00000065, 0x000a0006, 0x00000011, 0x00000001, 0x6c706572,
117 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x000a0006, 0x00000011, 0x00000002, 0x6c706572,
118 0x6d656361, 0x5f746e65, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00090006, 0x00000011, 0x00000003, 0x61766e69,
119 0x5f64696c, 0x646e6168, 0x665f656c, 0x646e756f, 0x00000000, 0x00090006, 0x00000011, 0x00000004, 0x61766e69, 0x5f64696c,
120 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00090006, 0x00000011, 0x00000005, 0x61766e69, 0x5f64696c, 0x646e6168,
121 0x625f656c, 0x5f737469, 0x00000031, 0x00080006, 0x00000011, 0x00000006, 0x696c6176, 0x61685f64, 0x656c646e, 0x6f635f73,
122 0x00746e75, 0x00070006, 0x00000011, 0x00000007, 0x696c6176, 0x61685f64, 0x656c646e, 0x00000073, 0x00030005, 0x00000013,
123 0x00000000, 0x00080005, 0x0000001b, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000305f, 0x00080005,
124 0x0000001e, 0x65476b56, 0x74656d6f, 0x6e497972, 0x6e617473, 0x564e6563, 0x00000000, 0x00050006, 0x0000001e, 0x00000000,
125 0x73756e75, 0x00006465, 0x00070006, 0x0000001e, 0x00000001, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000030, 0x00070006,
126 0x0000001e, 0x00000002, 0x646e6168, 0x625f656c, 0x5f737469, 0x00000031, 0x00060005, 0x00000020, 0x74736e49, 0x65636e61,
127 0x66667542, 0x00007265, 0x00060006, 0x00000020, 0x00000000, 0x74736e69, 0x65636e61, 0x00000073, 0x00030005, 0x00000022,
128 0x00000000, 0x00080005, 0x00000027, 0x74736e69, 0x65636e61, 0x6e61685f, 0x5f656c64, 0x73746962, 0x0000315f, 0x00040005,
129 0x0000002d, 0x696c6176, 0x00000064, 0x00070005, 0x0000002f, 0x696c6176, 0x61685f64, 0x656c646e, 0x646e695f, 0x00007865,
130 0x00040047, 0x00000010, 0x00000006, 0x00000004, 0x00050048, 0x00000011, 0x00000000, 0x00000023, 0x00000000, 0x00050048,
131 0x00000011, 0x00000001, 0x00000023, 0x00000004, 0x00050048, 0x00000011, 0x00000002, 0x00000023, 0x00000008, 0x00050048,
132 0x00000011, 0x00000003, 0x00000023, 0x0000000c, 0x00050048, 0x00000011, 0x00000004, 0x00000023, 0x00000010, 0x00050048,
133 0x00000011, 0x00000005, 0x00000023, 0x00000014, 0x00050048, 0x00000011, 0x00000006, 0x00000023, 0x00000018, 0x00050048,
134 0x00000011, 0x00000007, 0x00000023, 0x0000001c, 0x00030047, 0x00000011, 0x00000003, 0x00040047, 0x00000013, 0x00000022,
135 0x00000000, 0x00040047, 0x00000013, 0x00000021, 0x00000001, 0x00040047, 0x0000001d, 0x00000006, 0x00000004, 0x00050048,
136 0x0000001e, 0x00000000, 0x00000023, 0x00000000, 0x00050048, 0x0000001e, 0x00000001, 0x00000023, 0x00000038, 0x00050048,
137 0x0000001e, 0x00000002, 0x00000023, 0x0000003c, 0x00040047, 0x0000001f, 0x00000006, 0x00000040, 0x00050048, 0x00000020,
138 0x00000000, 0x00000023, 0x00000000, 0x00030047, 0x00000020, 0x00000003, 0x00040047, 0x00000022, 0x00000022, 0x00000000,
139 0x00040047, 0x00000022, 0x00000021, 0x00000000, 0x00020013, 0x00000002, 0x00030021, 0x00000003, 0x00000002, 0x00040015,
140 0x00000006, 0x00000020, 0x00000000, 0x00040020, 0x00000007, 0x00000007, 0x00000006, 0x0004002b, 0x00000006, 0x00000009,
141 0x00000000, 0x0003001d, 0x00000010, 0x00000006, 0x000a001e, 0x00000011, 0x00000006, 0x00000006, 0x00000006, 0x00000006,
142 0x00000006, 0x00000006, 0x00000006, 0x00000010, 0x00040020, 0x00000012, 0x00000002, 0x00000011, 0x0004003b, 0x00000012,
143 0x00000013, 0x00000002, 0x00040015, 0x00000014, 0x00000020, 0x00000001, 0x0004002b, 0x00000014, 0x00000015, 0x00000000,
144 0x00040020, 0x00000016, 0x00000002, 0x00000006, 0x00020014, 0x00000019, 0x0004002b, 0x00000006, 0x0000001c, 0x0000000e,
145 0x0004001c, 0x0000001d, 0x00000006, 0x0000001c, 0x0005001e, 0x0000001e, 0x0000001d, 0x00000006, 0x00000006, 0x0003001d,
146 0x0000001f, 0x0000001e, 0x0003001e, 0x00000020, 0x0000001f, 0x00040020, 0x00000021, 0x00000002, 0x00000020, 0x0004003b,
147 0x00000021, 0x00000022, 0x00000002, 0x0004002b, 0x00000014, 0x00000024, 0x00000001, 0x0004002b, 0x00000014, 0x00000029,
148 0x00000002, 0x00040020, 0x0000002c, 0x00000007, 0x00000019, 0x0003002a, 0x00000019, 0x0000002e, 0x0004002b, 0x00000014,
149 0x00000036, 0x00000006, 0x0004002b, 0x00000014, 0x0000003b, 0x00000007, 0x0004002b, 0x00000006, 0x0000003c, 0x00000002,
150 0x0004002b, 0x00000006, 0x00000048, 0x00000001, 0x00030029, 0x00000019, 0x00000050, 0x0004002b, 0x00000014, 0x00000058,
151 0x00000003, 0x0004002b, 0x00000014, 0x0000005d, 0x00000004, 0x0004002b, 0x00000014, 0x00000060, 0x00000005, 0x00050036,
152 0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x000200f8, 0x00000005, 0x0004003b, 0x00000007, 0x00000008, 0x00000007,
153 0x0004003b, 0x00000007, 0x0000001b, 0x00000007, 0x0004003b, 0x00000007, 0x00000027, 0x00000007, 0x0004003b, 0x0000002c,
154 0x0000002d, 0x00000007, 0x0004003b, 0x00000007, 0x0000002f, 0x00000007, 0x0003003e, 0x00000008, 0x00000009, 0x000200f9,
155 0x0000000a, 0x000200f8, 0x0000000a, 0x000400f6, 0x0000000c, 0x0000000d, 0x00000000, 0x000200f9, 0x0000000e, 0x000200f8,
156 0x0000000e, 0x0004003d, 0x00000006, 0x0000000f, 0x00000008, 0x00050041, 0x00000016, 0x00000017, 0x00000013, 0x00000015,
157 0x0004003d, 0x00000006, 0x00000018, 0x00000017, 0x000500b0, 0x00000019, 0x0000001a, 0x0000000f, 0x00000018, 0x000400fa,
158 0x0000001a, 0x0000000b, 0x0000000c, 0x000200f8, 0x0000000b, 0x0004003d, 0x00000006, 0x00000023, 0x00000008, 0x00070041,
159 0x00000016, 0x00000025, 0x00000022, 0x00000015, 0x00000023, 0x00000024, 0x0004003d, 0x00000006, 0x00000026, 0x00000025,
160 0x0003003e, 0x0000001b, 0x00000026, 0x0004003d, 0x00000006, 0x00000028, 0x00000008, 0x00070041, 0x00000016, 0x0000002a,
161 0x00000022, 0x00000015, 0x00000028, 0x00000029, 0x0004003d, 0x00000006, 0x0000002b, 0x0000002a, 0x0003003e, 0x00000027,
162 0x0000002b, 0x0003003e, 0x0000002d, 0x0000002e, 0x0003003e, 0x0000002f, 0x00000009, 0x000200f9, 0x00000030, 0x000200f8,
163 0x00000030, 0x000400f6, 0x00000032, 0x00000033, 0x00000000, 0x000200f9, 0x00000034, 0x000200f8, 0x00000034, 0x0004003d,
164 0x00000006, 0x00000035, 0x0000002f, 0x00050041, 0x00000016, 0x00000037, 0x00000013, 0x00000036, 0x0004003d, 0x00000006,
165 0x00000038, 0x00000037, 0x000500b0, 0x00000019, 0x00000039, 0x00000035, 0x00000038, 0x000400fa, 0x00000039, 0x00000031,
166 0x00000032, 0x000200f8, 0x00000031, 0x0004003d, 0x00000006, 0x0000003a, 0x0000001b, 0x0004003d, 0x00000006, 0x0000003d,
167 0x0000002f, 0x00050084, 0x00000006, 0x0000003e, 0x0000003c, 0x0000003d, 0x00050080, 0x00000006, 0x0000003f, 0x0000003e,
168 0x00000009, 0x00060041, 0x00000016, 0x00000040, 0x00000013, 0x0000003b, 0x0000003f, 0x0004003d, 0x00000006, 0x00000041,
169 0x00000040, 0x000500aa, 0x00000019, 0x00000042, 0x0000003a, 0x00000041, 0x000300f7, 0x00000044, 0x00000000, 0x000400fa,
170 0x00000042, 0x00000043, 0x00000044, 0x000200f8, 0x00000043, 0x0004003d, 0x00000006, 0x00000045, 0x00000027, 0x0004003d,
171 0x00000006, 0x00000046, 0x0000002f, 0x00050084, 0x00000006, 0x00000047, 0x0000003c, 0x00000046, 0x00050080, 0x00000006,
172 0x00000049, 0x00000047, 0x00000048, 0x00060041, 0x00000016, 0x0000004a, 0x00000013, 0x0000003b, 0x00000049, 0x0004003d,
173 0x00000006, 0x0000004b, 0x0000004a, 0x000500aa, 0x00000019, 0x0000004c, 0x00000045, 0x0000004b, 0x000200f9, 0x00000044,
174 0x000200f8, 0x00000044, 0x000700f5, 0x00000019, 0x0000004d, 0x00000042, 0x00000031, 0x0000004c, 0x00000043, 0x000300f7,
175 0x0000004f, 0x00000000, 0x000400fa, 0x0000004d, 0x0000004e, 0x0000004f, 0x000200f8, 0x0000004e, 0x0003003e, 0x0000002d,
176 0x00000050, 0x000200f9, 0x00000032, 0x000200f8, 0x0000004f, 0x000200f9, 0x00000033, 0x000200f8, 0x00000033, 0x0004003d,
177 0x00000006, 0x00000052, 0x0000002f, 0x00050080, 0x00000006, 0x00000053, 0x00000052, 0x00000024, 0x0003003e, 0x0000002f,
178 0x00000053, 0x000200f9, 0x00000030, 0x000200f8, 0x00000032, 0x0004003d, 0x00000019, 0x00000054, 0x0000002d, 0x000400a8,
179 0x00000019, 0x00000055, 0x00000054, 0x000300f7, 0x00000057, 0x00000000, 0x000400fa, 0x00000055, 0x00000056, 0x00000057,
180 0x000200f8, 0x00000056, 0x00050041, 0x00000016, 0x00000059, 0x00000013, 0x00000058, 0x0004003d, 0x00000006, 0x0000005a,
181 0x00000059, 0x00050080, 0x00000006, 0x0000005b, 0x0000005a, 0x00000048, 0x00050041, 0x00000016, 0x0000005c, 0x00000013,
182 0x00000058, 0x0003003e, 0x0000005c, 0x0000005b, 0x0004003d, 0x00000006, 0x0000005e, 0x0000001b, 0x00050041, 0x00000016,
183 0x0000005f, 0x00000013, 0x0000005d, 0x0003003e, 0x0000005f, 0x0000005e, 0x0004003d, 0x00000006, 0x00000061, 0x00000027,
184 0x00050041, 0x00000016, 0x00000062, 0x00000013, 0x00000060, 0x0003003e, 0x00000062, 0x00000061, 0x0004003d, 0x00000006,
185 0x00000063, 0x00000008, 0x00050041, 0x00000016, 0x00000064, 0x00000013, 0x00000024, 0x0004003d, 0x00000006, 0x00000065,
186 0x00000064, 0x00070041, 0x00000016, 0x00000066, 0x00000022, 0x00000015, 0x00000063, 0x00000024, 0x0003003e, 0x00000066,
187 0x00000065, 0x0004003d, 0x00000006, 0x00000067, 0x00000008, 0x00050041, 0x00000016, 0x00000068, 0x00000013, 0x00000029,
188 0x0004003d, 0x00000006, 0x00000069, 0x00000068, 0x00070041, 0x00000016, 0x0000006a, 0x00000022, 0x00000015, 0x00000067,
189 0x00000029, 0x0003003e, 0x0000006a, 0x00000069, 0x000200f9, 0x00000057, 0x000200f8, 0x00000057, 0x000200f9, 0x0000000d,
190 0x000200f8, 0x0000000d, 0x0004003d, 0x00000006, 0x0000006b, 0x00000008, 0x00050080, 0x00000006, 0x0000006c, 0x0000006b,
191 0x00000024, 0x0003003e, 0x00000008, 0x0000006c, 0x000200f9, 0x0000000a, 0x000200f8, 0x0000000c, 0x000100fd, 0x00010038};
192
Karl Schultz7b024b42018-08-30 16:18:18 -0600193// Implementation for Descriptor Set Manager class
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600194GpuAssistedDescriptorSetManager::GpuAssistedDescriptorSetManager(GpuAssisted *dev_data) { dev_data_ = dev_data; }
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700195
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600196GpuAssistedDescriptorSetManager::~GpuAssistedDescriptorSetManager() {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700197 for (auto &pool : desc_pool_map_) {
Tony-LunarG152a88b2019-03-20 15:42:24 -0600198 DispatchDestroyDescriptorPool(dev_data_->device, pool.first, NULL);
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700199 }
200 desc_pool_map_.clear();
201}
202
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600203VkResult GpuAssistedDescriptorSetManager::GetDescriptorSet(VkDescriptorPool *desc_pool, VkDescriptorSet *desc_set) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700204 std::vector<VkDescriptorSet> desc_sets;
205 VkResult result = GetDescriptorSets(1, desc_pool, &desc_sets);
206 if (result == VK_SUCCESS) {
207 *desc_set = desc_sets[0];
208 }
209 return result;
210}
211
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600212VkResult GpuAssistedDescriptorSetManager::GetDescriptorSets(uint32_t count, VkDescriptorPool *pool,
213 std::vector<VkDescriptorSet> *desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600214 const uint32_t default_pool_size = kItemsPerChunk;
215 VkResult result = VK_SUCCESS;
216 VkDescriptorPool pool_to_use = VK_NULL_HANDLE;
217
218 if (0 == count) {
219 return result;
220 }
221 desc_sets->clear();
222 desc_sets->resize(count);
223
224 for (auto &pool : desc_pool_map_) {
225 if (pool.second.used + count < pool.second.size) {
226 pool_to_use = pool.first;
227 break;
228 }
229 }
230 if (VK_NULL_HANDLE == pool_to_use) {
231 uint32_t pool_count = default_pool_size;
232 if (count > default_pool_size) {
233 pool_count = count;
234 }
235 const VkDescriptorPoolSize size_counts = {
236 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
237 pool_count * kNumBindingsInSet,
238 };
239 VkDescriptorPoolCreateInfo desc_pool_info = {};
240 desc_pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
241 desc_pool_info.pNext = NULL;
242 desc_pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
243 desc_pool_info.maxSets = pool_count;
244 desc_pool_info.poolSizeCount = 1;
245 desc_pool_info.pPoolSizes = &size_counts;
Tony-LunarG152a88b2019-03-20 15:42:24 -0600246 result = DispatchCreateDescriptorPool(dev_data_->device, &desc_pool_info, NULL, &pool_to_use);
Karl Schultz7b024b42018-08-30 16:18:18 -0600247 assert(result == VK_SUCCESS);
248 if (result != VK_SUCCESS) {
249 return result;
250 }
251 desc_pool_map_[pool_to_use].size = desc_pool_info.maxSets;
252 desc_pool_map_[pool_to_use].used = 0;
253 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600254 std::vector<VkDescriptorSetLayout> desc_layouts(count, dev_data_->debug_desc_layout);
Karl Schultz7b024b42018-08-30 16:18:18 -0600255
256 VkDescriptorSetAllocateInfo alloc_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, NULL, pool_to_use, count,
257 desc_layouts.data()};
258
Tony-LunarG152a88b2019-03-20 15:42:24 -0600259 result = DispatchAllocateDescriptorSets(dev_data_->device, &alloc_info, desc_sets->data());
Karl Schultz7b024b42018-08-30 16:18:18 -0600260 assert(result == VK_SUCCESS);
261 if (result != VK_SUCCESS) {
262 return result;
263 }
264 *pool = pool_to_use;
265 desc_pool_map_[pool_to_use].used += count;
266 return result;
267}
268
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600269void GpuAssistedDescriptorSetManager::PutBackDescriptorSet(VkDescriptorPool desc_pool, VkDescriptorSet desc_set) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600270 auto iter = desc_pool_map_.find(desc_pool);
271 if (iter != desc_pool_map_.end()) {
Tony-LunarG152a88b2019-03-20 15:42:24 -0600272 VkResult result = DispatchFreeDescriptorSets(dev_data_->device, desc_pool, 1, &desc_set);
Karl Schultz7b024b42018-08-30 16:18:18 -0600273 assert(result == VK_SUCCESS);
274 if (result != VK_SUCCESS) {
275 return;
276 }
277 desc_pool_map_[desc_pool].used--;
278 if (0 == desc_pool_map_[desc_pool].used) {
Tony-LunarG152a88b2019-03-20 15:42:24 -0600279 DispatchDestroyDescriptorPool(dev_data_->device, desc_pool, NULL);
Karl Schultz7b024b42018-08-30 16:18:18 -0600280 desc_pool_map_.erase(desc_pool);
281 }
282 }
283 return;
284}
285
Tony-LunarG0e564722019-03-19 16:09:14 -0600286// Trampolines to make VMA call Dispatch for Vulkan calls
287static VKAPI_ATTR void VKAPI_CALL gpuVkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
288 VkPhysicalDeviceProperties *pProperties) {
289 DispatchGetPhysicalDeviceProperties(physicalDevice, pProperties);
290}
291static VKAPI_ATTR void VKAPI_CALL gpuVkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
292 VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
293 DispatchGetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
294}
295static VKAPI_ATTR VkResult VKAPI_CALL gpuVkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
296 const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
297 return DispatchAllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
298}
299static VKAPI_ATTR void VKAPI_CALL gpuVkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks *pAllocator) {
300 DispatchFreeMemory(device, memory, pAllocator);
301}
302static VKAPI_ATTR VkResult VKAPI_CALL gpuVkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size,
303 VkMemoryMapFlags flags, void **ppData) {
304 return DispatchMapMemory(device, memory, offset, size, flags, ppData);
305}
306static VKAPI_ATTR void VKAPI_CALL gpuVkUnmapMemory(VkDevice device, VkDeviceMemory memory) { DispatchUnmapMemory(device, memory); }
307static VKAPI_ATTR VkResult VKAPI_CALL gpuVkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
308 const VkMappedMemoryRange *pMemoryRanges) {
309 return DispatchFlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
310}
311static VKAPI_ATTR VkResult VKAPI_CALL gpuVkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount,
312 const VkMappedMemoryRange *pMemoryRanges) {
313 return DispatchInvalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
314}
315static VKAPI_ATTR VkResult VKAPI_CALL gpuVkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory,
316 VkDeviceSize memoryOffset) {
317 return DispatchBindBufferMemory(device, buffer, memory, memoryOffset);
318}
319static VKAPI_ATTR VkResult VKAPI_CALL gpuVkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory,
320 VkDeviceSize memoryOffset) {
321 return DispatchBindImageMemory(device, image, memory, memoryOffset);
322}
323static VKAPI_ATTR void VKAPI_CALL gpuVkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer,
324 VkMemoryRequirements *pMemoryRequirements) {
325 DispatchGetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
326}
327static VKAPI_ATTR void VKAPI_CALL gpuVkGetImageMemoryRequirements(VkDevice device, VkImage image,
328 VkMemoryRequirements *pMemoryRequirements) {
329 DispatchGetImageMemoryRequirements(device, image, pMemoryRequirements);
330}
331static VKAPI_ATTR VkResult VKAPI_CALL gpuVkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
332 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
333 return DispatchCreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
334}
335static VKAPI_ATTR void VKAPI_CALL gpuVkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
336 return DispatchDestroyBuffer(device, buffer, pAllocator);
337}
338static VKAPI_ATTR VkResult VKAPI_CALL gpuVkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
339 const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
340 return DispatchCreateImage(device, pCreateInfo, pAllocator, pImage);
341}
342static VKAPI_ATTR void VKAPI_CALL gpuVkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
343 DispatchDestroyImage(device, image, pAllocator);
344}
345static VKAPI_ATTR void VKAPI_CALL gpuVkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
346 uint32_t regionCount, const VkBufferCopy *pRegions) {
347 DispatchCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
348}
349
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600350VkResult GpuAssisted::InitializeVma(VkPhysicalDevice physical_device, VkDevice device, VmaAllocator *pAllocator) {
Tony-LunarG0e564722019-03-19 16:09:14 -0600351 VmaVulkanFunctions functions;
352 VmaAllocatorCreateInfo allocatorInfo = {};
353 allocatorInfo.device = device;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600354 allocatorInfo.physicalDevice = physical_device;
Tony-LunarG0e564722019-03-19 16:09:14 -0600355
356 functions.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)gpuVkGetPhysicalDeviceProperties;
357 functions.vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)gpuVkGetPhysicalDeviceMemoryProperties;
358 functions.vkAllocateMemory = (PFN_vkAllocateMemory)gpuVkAllocateMemory;
359 functions.vkFreeMemory = (PFN_vkFreeMemory)gpuVkFreeMemory;
360 functions.vkMapMemory = (PFN_vkMapMemory)gpuVkMapMemory;
361 functions.vkUnmapMemory = (PFN_vkUnmapMemory)gpuVkUnmapMemory;
362 functions.vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)gpuVkFlushMappedMemoryRanges;
363 functions.vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges)gpuVkInvalidateMappedMemoryRanges;
364 functions.vkBindBufferMemory = (PFN_vkBindBufferMemory)gpuVkBindBufferMemory;
365 functions.vkBindImageMemory = (PFN_vkBindImageMemory)gpuVkBindImageMemory;
366 functions.vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements)gpuVkGetBufferMemoryRequirements;
367 functions.vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements)gpuVkGetImageMemoryRequirements;
368 functions.vkCreateBuffer = (PFN_vkCreateBuffer)gpuVkCreateBuffer;
369 functions.vkDestroyBuffer = (PFN_vkDestroyBuffer)gpuVkDestroyBuffer;
370 functions.vkCreateImage = (PFN_vkCreateImage)gpuVkCreateImage;
371 functions.vkDestroyImage = (PFN_vkDestroyImage)gpuVkDestroyImage;
372 functions.vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer)gpuVkCmdCopyBuffer;
373 allocatorInfo.pVulkanFunctions = &functions;
374
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600375 return vmaCreateAllocator(&allocatorInfo, pAllocator);
Tony-LunarG0e564722019-03-19 16:09:14 -0600376}
377
Karl Schultz7b024b42018-08-30 16:18:18 -0600378// Convenience function for reporting problems with setting up GPU Validation.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600379void GpuAssisted::ReportSetupProblem(VkDebugReportObjectTypeEXT object_type, uint64_t object_handle,
Jeff Bolz46c0ea02019-10-09 13:06:29 -0500380 const char *const specific_message) const {
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -0700381 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, object_type, object_handle, "UNASSIGNED-GPU-Assisted Validation Error. ",
382 "Detail: (%s)", specific_message);
Karl Schultz7b024b42018-08-30 16:18:18 -0600383}
384
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600385void GpuAssisted::PreCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
386 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer, void *cb_state_data) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700387 // Ray tracing acceleration structure instance buffers also need the storage buffer usage as
388 // acceleration structure build validation will find and replace invalid acceleration structure
389 // handles inside of a compute shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600390 create_buffer_api_state *cb_state = reinterpret_cast<create_buffer_api_state *>(cb_state_data);
391 if (cb_state && cb_state->modified_create_info.usage & VK_BUFFER_USAGE_RAY_TRACING_BIT_NV) {
392 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
Jason Macnak83cfd582019-07-31 10:14:24 -0700393 }
394}
395
Karl Schultz7b024b42018-08-30 16:18:18 -0600396// Turn on necessary device features.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600397void GpuAssisted::PreCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info,
398 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
399 safe_VkDeviceCreateInfo *modified_create_info) {
400 VkPhysicalDeviceFeatures supported_features;
401 DispatchGetPhysicalDeviceFeatures(gpu, &supported_features);
402 if (supported_features.fragmentStoresAndAtomics || supported_features.vertexPipelineStoresAndAtomics ||
403 supported_features.shaderInt64) {
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600404 VkPhysicalDeviceFeatures *features = nullptr;
Petr Kraus08d51062019-08-21 00:14:16 +0200405 if (modified_create_info->pEnabledFeatures) {
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600406 // If pEnabledFeatures, VkPhysicalDeviceFeatures2 in pNext chain is not allowed
Petr Kraus08d51062019-08-21 00:14:16 +0200407 features = const_cast<VkPhysicalDeviceFeatures *>(modified_create_info->pEnabledFeatures);
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600408 } else {
409 VkPhysicalDeviceFeatures2 *features2 = nullptr;
Petr Kraus08d51062019-08-21 00:14:16 +0200410 features2 =
411 const_cast<VkPhysicalDeviceFeatures2 *>(lvl_find_in_chain<VkPhysicalDeviceFeatures2>(modified_create_info->pNext));
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600412 if (features2) features = &features2->features;
Tony-LunarG48b478a2019-01-15 16:35:22 -0700413 }
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600414 if (features) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600415 features->fragmentStoresAndAtomics = supported_features.fragmentStoresAndAtomics;
416 features->vertexPipelineStoresAndAtomics = supported_features.vertexPipelineStoresAndAtomics;
417 features->shaderInt64 = supported_features.shaderInt64;
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600418 } else {
419 VkPhysicalDeviceFeatures new_features = {};
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600420 new_features.fragmentStoresAndAtomics = supported_features.fragmentStoresAndAtomics;
421 new_features.vertexPipelineStoresAndAtomics = supported_features.vertexPipelineStoresAndAtomics;
422 new_features.shaderInt64 = supported_features.shaderInt64;
Petr Krausbd5b7b22019-08-21 00:12:33 +0200423 delete modified_create_info->pEnabledFeatures;
Petr Kraus08d51062019-08-21 00:14:16 +0200424 modified_create_info->pEnabledFeatures = new VkPhysicalDeviceFeatures(new_features);
Tony-LunarG7800bfd2019-07-26 15:26:03 -0600425 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600426 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600427}
Karl Schultz7b024b42018-08-30 16:18:18 -0600428// Perform initializations that can be done at Create Device time.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600429void GpuAssisted::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
430 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result) {
431 // The state tracker sets up the device state
Tony-LunarG99b880b2019-09-26 11:19:52 -0600432 ValidationStateTracker::PostCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice, result);
Mark Lobodzinski5dc3dcd2019-04-23 14:26:28 -0600433
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600434 ValidationObject *device_object = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
435 ValidationObject *validation_data = GetValidationObject(device_object->object_dispatch, this->container_type);
436 GpuAssisted *device_gpu_assisted = static_cast<GpuAssisted *>(validation_data);
Tony-LunarG65f9c492019-01-17 14:24:42 -0700437
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600438 if (device_gpu_assisted->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600439 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz7b024b42018-08-30 16:18:18 -0600440 "GPU-Assisted validation requires Vulkan 1.1 or later. GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600441 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600442 return;
443 }
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600444
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600445 if (!device_gpu_assisted->enabled_features.core.fragmentStoresAndAtomics ||
446 !device_gpu_assisted->enabled_features.core.vertexPipelineStoresAndAtomics) {
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600447 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
448 "GPU-Assisted validation requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
449 "GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600450 device_gpu_assisted->aborted = true;
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600451 return;
452 }
453
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600454 if (device_extensions.vk_ext_buffer_device_address && !device_gpu_assisted->enabled_features.core.shaderInt64) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600455 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
456 "UNASSIGNED-GPU-Assisted Validation Warning",
457 "shaderInt64 feature is not available. No buffer device address checking will be attempted");
458 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600459 device_gpu_assisted->shaderInt64 = device_gpu_assisted->enabled_features.core.shaderInt64;
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600460
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600461 // If api version 1.1 or later, SetDeviceLoaderData will be in the loader
462 auto chain_info = get_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK);
463 assert(chain_info->u.pfnSetDeviceLoaderData);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600464 device_gpu_assisted->vkSetDeviceLoaderData = chain_info->u.pfnSetDeviceLoaderData;
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600465
Karl Schultz7b024b42018-08-30 16:18:18 -0600466 // Some devices have extremely high limits here, so set a reasonable max because we have to pad
467 // the pipeline layout with dummy descriptor set layouts.
Tony-LunarG99b880b2019-09-26 11:19:52 -0600468 device_gpu_assisted->adjusted_max_desc_sets = device_gpu_assisted->phys_dev_props.limits.maxBoundDescriptorSets;
469 device_gpu_assisted->adjusted_max_desc_sets = std::min(33U, device_gpu_assisted->adjusted_max_desc_sets);
Karl Schultz7b024b42018-08-30 16:18:18 -0600470
471 // We can't do anything if there is only one.
472 // Device probably not a legit Vulkan device, since there should be at least 4. Protect ourselves.
Tony-LunarG99b880b2019-09-26 11:19:52 -0600473 if (device_gpu_assisted->adjusted_max_desc_sets == 1) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600474 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz7b024b42018-08-30 16:18:18 -0600475 "Device can bind only a single descriptor set. GPU-Assisted Validation disabled.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600476 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600477 return;
478 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600479 device_gpu_assisted->desc_set_bind_index = device_gpu_assisted->adjusted_max_desc_sets - 1;
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -0600480 log_msg(report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
481 "UNASSIGNED-GPU-Assisted Validation. ", "Shaders using descriptor set at index %d. ",
Tony-LunarG99b880b2019-09-26 11:19:52 -0600482 device_gpu_assisted->desc_set_bind_index);
Karl Schultz7b024b42018-08-30 16:18:18 -0600483
Tony-LunarG99b880b2019-09-26 11:19:52 -0600484 device_gpu_assisted->output_buffer_size = sizeof(uint32_t) * (spvtools::kInst2MaxOutCnt + 1);
485 VkResult result1 = InitializeVma(physicalDevice, *pDevice, &device_gpu_assisted->vmaAllocator);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600486 assert(result1 == VK_SUCCESS);
487 std::unique_ptr<GpuAssistedDescriptorSetManager> desc_set_manager(new GpuAssistedDescriptorSetManager(device_gpu_assisted));
Karl Schultz7b024b42018-08-30 16:18:18 -0600488
489 // The descriptor indexing checks require only the first "output" binding.
490 const VkDescriptorSetLayoutBinding debug_desc_layout_bindings[kNumBindingsInSet] = {
491 {
492 0, // output
493 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
494 1,
Jason Macnak67407e72019-07-11 11:05:09 -0700495 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT | kShaderStageAllRayTracing,
Karl Schultz7b024b42018-08-30 16:18:18 -0600496 NULL,
497 },
Tony-LunarG1b2e0c32019-02-07 17:13:27 -0700498 {
499 1, // input
500 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
501 1,
Jason Macnak67407e72019-07-11 11:05:09 -0700502 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT | kShaderStageAllRayTracing,
Tony-LunarG1b2e0c32019-02-07 17:13:27 -0700503 NULL,
504 },
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600505 {
506 2, // input
507 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
508 1,
509 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT | kShaderStageAllRayTracing,
510 NULL,
511 },
Karl Schultz7b024b42018-08-30 16:18:18 -0600512 };
Karl Schultz7b024b42018-08-30 16:18:18 -0600513 const VkDescriptorSetLayoutCreateInfo debug_desc_layout_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, 0,
514 kNumBindingsInSet, debug_desc_layout_bindings};
515
516 const VkDescriptorSetLayoutCreateInfo dummy_desc_layout_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, 0, 0,
517 NULL};
518
Tony-LunarG99b880b2019-09-26 11:19:52 -0600519 result1 = DispatchCreateDescriptorSetLayout(*pDevice, &debug_desc_layout_info, NULL, &device_gpu_assisted->debug_desc_layout);
Karl Schultz7b024b42018-08-30 16:18:18 -0600520
521 // 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 -0600522 VkResult result2 =
523 DispatchCreateDescriptorSetLayout(*pDevice, &dummy_desc_layout_info, NULL, &device_gpu_assisted->dummy_desc_layout);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600524 assert((result1 == VK_SUCCESS) && (result2 == VK_SUCCESS));
525 if ((result1 != VK_SUCCESS) || (result2 != VK_SUCCESS)) {
526 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(*pDevice),
Karl Schultz7b024b42018-08-30 16:18:18 -0600527 "Unable to create descriptor set layout. GPU-Assisted Validation disabled.");
528 if (result == VK_SUCCESS) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600529 DispatchDestroyDescriptorSetLayout(*pDevice, device_gpu_assisted->debug_desc_layout, NULL);
Karl Schultz7b024b42018-08-30 16:18:18 -0600530 }
531 if (result2 == VK_SUCCESS) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600532 DispatchDestroyDescriptorSetLayout(*pDevice, device_gpu_assisted->dummy_desc_layout, NULL);
Karl Schultz7b024b42018-08-30 16:18:18 -0600533 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600534 device_gpu_assisted->debug_desc_layout = VK_NULL_HANDLE;
535 device_gpu_assisted->dummy_desc_layout = VK_NULL_HANDLE;
536 device_gpu_assisted->aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600537 return;
538 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600539 device_gpu_assisted->desc_set_manager = std::move(desc_set_manager);
Jason Macnak83cfd582019-07-31 10:14:24 -0700540
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600541 // Register callback to be called at any ResetCommandBuffer time
542 device_gpu_assisted->SetCommandBufferResetCallback(
543 [device_gpu_assisted](VkCommandBuffer command_buffer) -> void { device_gpu_assisted->ResetCommandBuffer(command_buffer); });
544
545 CreateAccelerationStructureBuildValidationState(device_gpu_assisted);
Karl Schultz7b024b42018-08-30 16:18:18 -0600546}
547
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600548void GpuAssisted::PostCallRecordGetBufferDeviceAddressEXT(VkDevice device, const VkBufferDeviceAddressInfoEXT *pInfo,
549 VkDeviceAddress address) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600550 BUFFER_STATE *buffer_state = GetBufferState(pInfo->buffer);
551 // Validate against the size requested when the buffer was created
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600552 if (buffer_state) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600553 buffer_map[address] = buffer_state->createInfo.size;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600554 buffer_state->deviceAddress = address;
555 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600556}
557
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600558void GpuAssisted::PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600559 BUFFER_STATE *buffer_state = GetBufferState(buffer);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600560 if (buffer_state) buffer_map.erase(buffer_state->deviceAddress);
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600561}
Karl Schultz7b024b42018-08-30 16:18:18 -0600562// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600563void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600564 for (auto &queue_barrier_command_info_kv : queue_barrier_command_infos) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600565 GpuAssistedQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_kv.second;
Jason Macnak8eae5722019-07-17 15:17:45 -0700566
567 DispatchFreeCommandBuffers(device, queue_barrier_command_info.barrier_command_pool, 1,
568 &queue_barrier_command_info.barrier_command_buffer);
569 queue_barrier_command_info.barrier_command_buffer = VK_NULL_HANDLE;
570
571 DispatchDestroyCommandPool(device, queue_barrier_command_info.barrier_command_pool, NULL);
572 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
Karl Schultz58674242019-01-22 15:35:02 -0700573 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600574 queue_barrier_command_infos.clear();
575 if (debug_desc_layout) {
576 DispatchDestroyDescriptorSetLayout(device, debug_desc_layout, NULL);
577 debug_desc_layout = VK_NULL_HANDLE;
Karl Schultz7b024b42018-08-30 16:18:18 -0600578 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600579 if (dummy_desc_layout) {
580 DispatchDestroyDescriptorSetLayout(device, dummy_desc_layout, NULL);
581 dummy_desc_layout = VK_NULL_HANDLE;
Karl Schultz7b024b42018-08-30 16:18:18 -0600582 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600583 desc_set_manager.reset();
Jason Macnak83cfd582019-07-31 10:14:24 -0700584
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600585 DestroyAccelerationStructureBuildValidationState();
Jason Macnak83cfd582019-07-31 10:14:24 -0700586
Tony-LunarG99b880b2019-09-26 11:19:52 -0600587 if (vmaAllocator) {
588 vmaDestroyAllocator(vmaAllocator);
Tony-LunarG29f48a72019-04-16 11:53:37 -0600589 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600590}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600591void GpuAssisted::CreateAccelerationStructureBuildValidationState(GpuAssisted *device_gpuav) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600592 if (device_gpuav->aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700593 return;
594 }
595
Tony-LunarG99b880b2019-09-26 11:19:52 -0600596 auto &as_validation_state = device_gpuav->acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700597 if (as_validation_state.initialized) {
598 return;
599 }
600
601 if (!device_extensions.vk_nv_ray_tracing) {
602 return;
603 }
604
605 // Outline:
606 // - Create valid bottom level acceleration structure which acts as replacement
607 // - Create and load vertex buffer
608 // - Create and load index buffer
609 // - Create, allocate memory for, and bind memory for acceleration structure
610 // - Query acceleration structure handle
611 // - Create command pool and command buffer
612 // - Record build acceleration structure command
613 // - Submit command buffer and wait for completion
614 // - Cleanup
615 // - Create compute pipeline for validating instance buffers
616 // - Create descriptor set layout
617 // - Create pipeline layout
618 // - Create pipeline
619 // - Cleanup
620
621 VkResult result = VK_SUCCESS;
622
623 VkBuffer vbo = VK_NULL_HANDLE;
624 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
625 if (result == VK_SUCCESS) {
626 VkBufferCreateInfo vbo_ci = {};
627 vbo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
628 vbo_ci.size = sizeof(float) * 9;
629 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
630
631 VmaAllocationCreateInfo vbo_ai = {};
632 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
633 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
634
Tony-LunarG99b880b2019-09-26 11:19:52 -0600635 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700636 if (result != VK_SUCCESS) {
637 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
638 "Failed to create vertex buffer for acceleration structure build validation.");
639 }
640 }
641
642 if (result == VK_SUCCESS) {
643 uint8_t *mapped_vbo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600644 result = vmaMapMemory(device_gpuav->vmaAllocator, vbo_allocation, (void **)&mapped_vbo_buffer);
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 map vertex buffer for acceleration structure build validation.");
648 } else {
649 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
650 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600651 vmaUnmapMemory(device_gpuav->vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700652 }
653 }
654
655 VkBuffer ibo = VK_NULL_HANDLE;
656 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
657 if (result == VK_SUCCESS) {
658 VkBufferCreateInfo ibo_ci = {};
659 ibo_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
660 ibo_ci.size = sizeof(uint32_t) * 3;
661 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
662
663 VmaAllocationCreateInfo ibo_ai = {};
664 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
665 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
666
Tony-LunarG99b880b2019-09-26 11:19:52 -0600667 result = vmaCreateBuffer(device_gpuav->vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700668 if (result != VK_SUCCESS) {
669 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
670 "Failed to create index buffer for acceleration structure build validation.");
671 }
672 }
673
674 if (result == VK_SUCCESS) {
675 uint8_t *mapped_ibo_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600676 result = vmaMapMemory(device_gpuav->vmaAllocator, ibo_allocation, (void **)&mapped_ibo_buffer);
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 map index buffer for acceleration structure build validation.");
680 } else {
681 const std::vector<uint32_t> indicies = {0, 1, 2};
682 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Tony-LunarG99b880b2019-09-26 11:19:52 -0600683 vmaUnmapMemory(device_gpuav->vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700684 }
685 }
686
687 VkGeometryNV geometry = {};
688 geometry.sType = VK_STRUCTURE_TYPE_GEOMETRY_NV;
689 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
690 geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV;
691 geometry.geometry.triangles.vertexData = vbo;
692 geometry.geometry.triangles.vertexOffset = 0;
693 geometry.geometry.triangles.vertexCount = 3;
694 geometry.geometry.triangles.vertexStride = 12;
695 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
696 geometry.geometry.triangles.indexData = ibo;
697 geometry.geometry.triangles.indexOffset = 0;
698 geometry.geometry.triangles.indexCount = 3;
699 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
700 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
701 geometry.geometry.triangles.transformOffset = 0;
702 geometry.geometry.aabbs = {};
703 geometry.geometry.aabbs.sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV;
704
705 VkAccelerationStructureCreateInfoNV as_ci = {};
706 as_ci.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV;
707 as_ci.info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV;
708 as_ci.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV;
709 as_ci.info.instanceCount = 0;
710 as_ci.info.geometryCount = 1;
711 as_ci.info.pGeometries = &geometry;
712 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600713 result = DispatchCreateAccelerationStructureNV(device_gpuav->device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700714 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600715 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700716 "Failed to create acceleration structure for acceleration structure build validation.");
717 }
718 }
719
720 VkMemoryRequirements2 as_mem_requirements = {};
721 if (result == VK_SUCCESS) {
722 VkAccelerationStructureMemoryRequirementsInfoNV as_mem_requirements_info = {};
723 as_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
724 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
725 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
726
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600727 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700728 }
729
730 VmaAllocationInfo as_memory_ai = {};
731 if (result == VK_SUCCESS) {
732 VmaAllocationCreateInfo as_memory_aci = {};
733 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
734
Tony-LunarG99b880b2019-09-26 11:19:52 -0600735 result = vmaAllocateMemory(device_gpuav->vmaAllocator, &as_mem_requirements.memoryRequirements, &as_memory_aci,
736 &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700737 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600738 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700739 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
740 }
741 }
742
743 if (result == VK_SUCCESS) {
744 VkBindAccelerationStructureMemoryInfoNV as_bind_info = {};
745 as_bind_info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
746 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
747 as_bind_info.memory = as_memory_ai.deviceMemory;
748 as_bind_info.memoryOffset = as_memory_ai.offset;
749
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600750 result = DispatchBindAccelerationStructureMemoryNV(device_gpuav->device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700751 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600752 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700753 "Failed to bind acceleration structure memory for acceleration structure build validation.");
754 }
755 }
756
757 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600758 result = DispatchGetAccelerationStructureHandleNV(device_gpuav->device, as_validation_state.replacement_as,
759 sizeof(uint64_t), &as_validation_state.replacement_as_handle);
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 get acceleration structure handle for acceleration structure build validation.");
763 }
764 }
765
766 VkMemoryRequirements2 scratch_mem_requirements = {};
767 if (result == VK_SUCCESS) {
768 VkAccelerationStructureMemoryRequirementsInfoNV scratch_mem_requirements_info = {};
769 scratch_mem_requirements_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV;
770 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
771 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
772
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600773 DispatchGetAccelerationStructureMemoryRequirementsNV(device_gpuav->device, &scratch_mem_requirements_info,
774 &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700775 }
776
777 VkBuffer scratch = VK_NULL_HANDLE;
778 if (result == VK_SUCCESS) {
779 VkBufferCreateInfo scratch_ci = {};
780 scratch_ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
781 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
782 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
783
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600784 result = DispatchCreateBuffer(device_gpuav->device, &scratch_ci, nullptr, &scratch);
Jason Macnak83cfd582019-07-31 10:14:24 -0700785 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600786 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700787 "Failed to create scratch buffer for acceleration structure build validation.");
788 }
789 }
790
791 VmaAllocation scratch_allocation = VK_NULL_HANDLE;
792 VmaAllocationInfo scratch_allocation_info = {};
793 if (result == VK_SUCCESS) {
794 VmaAllocationCreateInfo scratch_aci = {};
795 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
796
Tony-LunarG99b880b2019-09-26 11:19:52 -0600797 result = vmaAllocateMemory(device_gpuav->vmaAllocator, &scratch_mem_requirements.memoryRequirements, &scratch_aci,
798 &scratch_allocation, &scratch_allocation_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700799 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600800 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700801 "Failed to alloc scratch memory for acceleration structure build validation.");
802 }
803 }
804
805 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600806 result = DispatchBindBufferMemory(device_gpuav->device, scratch, scratch_allocation_info.deviceMemory,
807 scratch_allocation_info.offset);
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 bind scratch memory for acceleration structure build validation.");
811 }
812 }
813
814 VkCommandPool command_pool = VK_NULL_HANDLE;
815 if (result == VK_SUCCESS) {
816 VkCommandPoolCreateInfo command_pool_ci = {};
817 command_pool_ci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
818 command_pool_ci.queueFamilyIndex = 0;
819
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600820 result = DispatchCreateCommandPool(device_gpuav->device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700821 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600822 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700823 "Failed to create command pool for acceleration structure build validation.");
824 }
825 }
826
827 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
828
829 if (result == VK_SUCCESS) {
830 VkCommandBufferAllocateInfo command_buffer_ai = {};
831 command_buffer_ai.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
832 command_buffer_ai.commandPool = command_pool;
833 command_buffer_ai.commandBufferCount = 1;
834 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
835
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600836 result = DispatchAllocateCommandBuffers(device_gpuav->device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700837 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600838 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700839 "Failed to create command buffer for acceleration structure build validation.");
840 }
841
842 // Hook up command buffer dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600843 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700844 }
845
846 if (result == VK_SUCCESS) {
847 VkCommandBufferBeginInfo command_buffer_bi = {};
848 command_buffer_bi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
849
850 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
851 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600852 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700853 "Failed to begin command buffer for acceleration structure build validation.");
854 }
855 }
856
857 if (result == VK_SUCCESS) {
858 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
859 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
860 DispatchEndCommandBuffer(command_buffer);
861 }
862
863 VkQueue queue = VK_NULL_HANDLE;
864 if (result == VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600865 DispatchGetDeviceQueue(device_gpuav->device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700866
867 // Hook up queue dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -0600868 device_gpuav->vkSetDeviceLoaderData(device_gpuav->device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700869
870 VkSubmitInfo submit_info = {};
871 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
872 submit_info.commandBufferCount = 1;
873 submit_info.pCommandBuffers = &command_buffer;
874 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
875 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600876 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700877 "Failed to submit command buffer for acceleration structure build validation.");
878 }
879 }
880
881 if (result == VK_SUCCESS) {
882 result = DispatchQueueWaitIdle(queue);
883 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600884 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700885 "Failed to wait for queue idle for acceleration structure build validation.");
886 }
887 }
888
889 if (vbo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600890 vmaDestroyBuffer(device_gpuav->vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700891 }
892 if (ibo != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600893 vmaDestroyBuffer(device_gpuav->vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700894 }
895 if (scratch != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600896 DispatchDestroyBuffer(device_gpuav->device, scratch, nullptr);
Tony-LunarG99b880b2019-09-26 11:19:52 -0600897 vmaFreeMemory(device_gpuav->vmaAllocator, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700898 }
899 if (command_pool != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600900 DispatchDestroyCommandPool(device_gpuav->device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700901 }
902
Tony-LunarG99b880b2019-09-26 11:19:52 -0600903 if (device_gpuav->debug_desc_layout == VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600904 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700905 "Failed to find descriptor set layout for acceleration structure build validation.");
906 result = VK_INCOMPLETE;
907 }
908
909 if (result == VK_SUCCESS) {
910 VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
911 pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
912 pipeline_layout_ci.setLayoutCount = 1;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600913 pipeline_layout_ci.pSetLayouts = &device_gpuav->debug_desc_layout;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600914 result = DispatchCreatePipelineLayout(device_gpuav->device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700915 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600916 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700917 "Failed to create pipeline layout for acceleration structure build validation.");
918 }
919 }
920
921 VkShaderModule shader_module = VK_NULL_HANDLE;
922 if (result == VK_SUCCESS) {
923 VkShaderModuleCreateInfo shader_module_ci = {};
924 shader_module_ci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
925 shader_module_ci.codeSize = sizeof(kComputeShaderSpirv);
926 shader_module_ci.pCode = (uint32_t *)kComputeShaderSpirv;
927
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600928 result = DispatchCreateShaderModule(device_gpuav->device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700929 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600930 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700931 "Failed to create compute shader module for acceleration structure build validation.");
932 }
933 }
934
935 if (result == VK_SUCCESS) {
936 VkPipelineShaderStageCreateInfo pipeline_stage_ci = {};
937 pipeline_stage_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
938 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
939 pipeline_stage_ci.module = shader_module;
940 pipeline_stage_ci.pName = "main";
941
942 VkComputePipelineCreateInfo pipeline_ci = {};
943 pipeline_ci.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
944 pipeline_ci.stage = pipeline_stage_ci;
945 pipeline_ci.layout = as_validation_state.pipeline_layout;
946
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600947 result = DispatchCreateComputePipelines(device_gpuav->device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr,
948 &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700949 if (result != VK_SUCCESS) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600950 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device_gpuav->device),
Jason Macnak83cfd582019-07-31 10:14:24 -0700951 "Failed to create compute pipeline for acceleration structure build validation.");
952 }
953 }
954
955 if (shader_module != VK_NULL_HANDLE) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600956 DispatchDestroyShaderModule(device_gpuav->device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700957 }
958
959 if (result == VK_SUCCESS) {
960 as_validation_state.initialized = true;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600961 log_msg(report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
962 HandleToUint64(device_gpuav->device), "UNASSIGNED-GPU-Assisted Validation.",
963 "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700964 } else {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600965 device_gpuav->aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700966 }
967}
968
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600969void GpuAssisted::DestroyAccelerationStructureBuildValidationState() {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600970 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700971 if (as_validation_state.pipeline != VK_NULL_HANDLE) {
972 DispatchDestroyPipeline(device, as_validation_state.pipeline, nullptr);
973 }
974 if (as_validation_state.pipeline_layout != VK_NULL_HANDLE) {
975 DispatchDestroyPipelineLayout(device, as_validation_state.pipeline_layout, nullptr);
976 }
977 if (as_validation_state.replacement_as != VK_NULL_HANDLE) {
978 DispatchDestroyAccelerationStructureNV(device, as_validation_state.replacement_as, nullptr);
979 }
980 if (as_validation_state.replacement_as_allocation != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600981 vmaFreeMemory(vmaAllocator, as_validation_state.replacement_as_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700982 }
983}
984
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600985struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700986 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
987 VkPipeline pipeline = VK_NULL_HANDLE;
988 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
989 std::vector<VkDescriptorSet> descriptor_sets;
990 std::vector<std::vector<uint32_t>> dynamic_offsets;
991 uint32_t push_descriptor_set_index = 0;
992 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
993 std::vector<uint8_t> push_constants_data;
994 PushConstantRangesId push_constants_ranges;
995
996 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
997 pipeline_bind_point = bind_point;
998
999 LAST_BOUND_STATE &last_bound = cb_state->lastBound[bind_point];
1000 if (last_bound.pipeline_state) {
1001 pipeline = last_bound.pipeline_state->pipeline;
1002 pipeline_layout = last_bound.pipeline_layout;
1003 descriptor_sets.reserve(last_bound.per_set.size());
1004 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
1005 const auto *bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
1006
1007 descriptor_sets.push_back(bound_descriptor_set->GetSet());
1008 if (bound_descriptor_set->IsPushDescriptor()) {
1009 push_descriptor_set_index = static_cast<uint32_t>(i);
1010 }
1011 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
1012 }
1013
1014 if (last_bound.push_descriptor_set) {
1015 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
1016 }
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001017 if (last_bound.pipeline_state->pipeline_layout->push_constant_ranges == cb_state->push_constant_data_ranges) {
Jason Macnak83cfd582019-07-31 10:14:24 -07001018 push_constants_data = cb_state->push_constant_data;
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001019 push_constants_ranges = last_bound.pipeline_state->pipeline_layout->push_constant_ranges;
Jason Macnak83cfd582019-07-31 10:14:24 -07001020 }
1021 }
1022 }
1023
1024 void Restore(VkCommandBuffer command_buffer) const {
1025 if (pipeline != VK_NULL_HANDLE) {
1026 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
1027 if (!descriptor_sets.empty()) {
1028 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
1029 VkDescriptorSet descriptor_set = descriptor_sets[i];
1030 if (descriptor_set != VK_NULL_HANDLE) {
1031 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
1032 static_cast<uint32_t>(i), 1, &descriptor_set,
1033 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
1034 }
1035 }
1036 }
1037 if (!push_descriptor_set_writes.empty()) {
1038 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
1039 static_cast<uint32_t>(push_descriptor_set_writes.size()),
1040 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
1041 }
1042 for (const auto &push_constant_range : *push_constants_ranges) {
1043 if (push_constant_range.size == 0) continue;
1044 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
1045 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
1046 }
1047 }
1048 }
1049};
1050
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001051void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
1052 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
1053 VkDeviceSize instanceOffset, VkBool32 update,
1054 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
1055 VkBuffer scratch, VkDeviceSize scratchOffset) {
Jason Macnak83cfd582019-07-31 10:14:24 -07001056 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
1057 return;
1058 }
1059
Tony-LunarG99b880b2019-09-26 11:19:52 -06001060 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001061 if (!as_validation_state.initialized) {
1062 return;
1063 }
1064
1065 // Empty acceleration structure is valid according to the spec.
1066 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
1067 return;
1068 }
1069
1070 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
1071 assert(cb_state != nullptr);
1072
1073 std::vector<uint64_t> current_valid_handles;
1074 for (const auto &as_state_kv : accelerationStructureMap) {
1075 const ACCELERATION_STRUCTURE_STATE &as_state = *as_state_kv.second;
1076 if (as_state.built && as_state.create_info.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
1077 current_valid_handles.push_back(as_state.opaque_handle);
1078 }
1079 }
1080
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001081 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -07001082 as_validation_buffer_info.acceleration_structure = dst;
1083
1084 const VkDeviceSize validation_buffer_size =
1085 // One uint for number of instances to validate
1086 4 +
1087 // Two uint for the replacement acceleration structure handle
1088 8 +
1089 // One uint for number of invalid handles found
1090 4 +
1091 // Two uint for the first invalid handle found
1092 8 +
1093 // One uint for the number of current valid handles
1094 4 +
1095 // Two uint for each current valid handle
1096 (8 * current_valid_handles.size());
1097
1098 VkBufferCreateInfo validation_buffer_create_info = {};
1099 validation_buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1100 validation_buffer_create_info.size = validation_buffer_size;
1101 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1102
1103 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
1104 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
1105
Tony-LunarG99b880b2019-09-26 11:19:52 -06001106 VkResult result = vmaCreateBuffer(vmaAllocator, &validation_buffer_create_info, &validation_buffer_alloc_info,
1107 &as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -07001108 &as_validation_buffer_info.validation_buffer_allocation, nullptr);
1109 if (result != VK_SUCCESS) {
1110 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
1111 "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001112 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -07001113 return;
1114 }
1115
1116 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001117 result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001118 if (result != VK_SUCCESS) {
1119 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
1120 "Unable to allocate device memory for acceleration structure build val buffer.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001121 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -07001122 return;
1123 }
1124
1125 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
1126 mapped_validation_buffer->replacement_handle_bits_0 =
1127 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
1128 mapped_validation_buffer->replacement_handle_bits_1 =
1129 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
1130 mapped_validation_buffer->invalid_handle_found = 0;
1131 mapped_validation_buffer->invalid_handle_bits_0 = 0;
1132 mapped_validation_buffer->invalid_handle_bits_1 = 0;
1133 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
1134
1135 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
1136 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
1137 const uint64_t current_valid_handle = current_valid_handles[i];
1138
1139 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
1140 ++mapped_valid_handles;
1141 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
1142 ++mapped_valid_handles;
1143 }
1144
Tony-LunarG99b880b2019-09-26 11:19:52 -06001145 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -07001146
1147 static constexpr const VkDeviceSize kInstanceSize = 64;
1148 const VkDeviceSize instance_buffer_size = kInstanceSize * pInfo->instanceCount;
1149
Tony-LunarG99b880b2019-09-26 11:19:52 -06001150 result =
1151 desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool, &as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -07001152 if (result != VK_SUCCESS) {
1153 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
1154 "Unable to get descriptor set for acceleration structure build.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001155 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -07001156 return;
1157 }
1158
1159 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
1160 descriptor_buffer_infos[0].buffer = instanceData;
1161 descriptor_buffer_infos[0].offset = instanceOffset;
1162 descriptor_buffer_infos[0].range = instance_buffer_size;
1163 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.validation_buffer;
1164 descriptor_buffer_infos[1].offset = 0;
1165 descriptor_buffer_infos[1].range = validation_buffer_size;
1166
1167 VkWriteDescriptorSet descriptor_set_writes[2] = {};
1168 descriptor_set_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1169 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
1170 descriptor_set_writes[0].dstBinding = 0;
1171 descriptor_set_writes[0].descriptorCount = 1;
1172 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1173 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
1174 descriptor_set_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1175 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
1176 descriptor_set_writes[1].dstBinding = 1;
1177 descriptor_set_writes[1].descriptorCount = 1;
1178 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1179 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
1180
1181 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
1182
1183 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
1184 VkMemoryBarrier memory_barrier = {};
1185 memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
1186 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
1187 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
1188 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
1189 &memory_barrier, 0, nullptr, 0, nullptr);
1190
1191 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001192 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001193 restorable_state.Create(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
1194
1195 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
1196 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
1197 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
1198 &as_validation_buffer_info.descriptor_set, 0, nullptr);
1199 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
1200
1201 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
1202 // have been replaced by the validation compute shader before any builds take place.
1203 VkBufferMemoryBarrier instance_buffer_barrier = {};
1204 instance_buffer_barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1205 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1206 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
1207 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1208 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1209 instance_buffer_barrier.buffer = instanceData;
1210 instance_buffer_barrier.offset = instanceOffset;
1211 instance_buffer_barrier.size = instance_buffer_size;
1212 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1213 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
1214 nullptr);
1215
1216 // Restore the previous compute pipeline state.
1217 restorable_state.Restore(commandBuffer);
1218
1219 as_validation_state.validation_buffers[commandBuffer].push_back(std::move(as_validation_buffer_info));
1220}
1221
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001222void GpuAssisted::ProcessAccelerationStructureBuildValidationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Jason Macnak83cfd582019-07-31 10:14:24 -07001223 if (cb_node == nullptr || !cb_node->hasBuildAccelerationStructureCmd) {
1224 return;
1225 }
1226
Tony-LunarG99b880b2019-09-26 11:19:52 -06001227 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001228 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[cb_node->commandBuffer];
1229 for (const auto &as_validation_buffer_info : as_validation_buffer_infos) {
1230 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
1231
Tony-LunarG99b880b2019-09-26 11:19:52 -06001232 VkResult result =
1233 vmaMapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation, (void **)&mapped_validation_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001234 if (result == VK_SUCCESS) {
1235 if (mapped_validation_buffer->invalid_handle_found > 0) {
1236 uint64_t invalid_handle = 0;
1237 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
1238 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
1239
1240 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT,
1241 HandleToUint64(as_validation_buffer_info.acceleration_structure), "UNASSIGNED-AccelerationStructure",
1242 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
1243 "handle (%" PRIu64 ")",
1244 invalid_handle);
1245 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001246 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.validation_buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -07001247 }
1248 }
1249}
1250
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001251void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
1252 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
1253 VkResult result) {
1254 if (VK_SUCCESS != result) return;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001255 ValidationStateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001256 for (uint32_t i = 0; i < bindInfoCount; i++) {
1257 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
1258 ACCELERATION_STRUCTURE_STATE *as_state = GetAccelerationStructureState(info.accelerationStructure);
1259 if (as_state) {
1260 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
1261 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001262 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001263}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -07001264
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001265// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
1266void GpuAssisted::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
1267 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
1268 void *cpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001269 if (aborted) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001270 return;
1271 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001272
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001273 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
1274
Tony-LunarG99b880b2019-09-26 11:19:52 -06001275 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001276 std::ostringstream strm;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001277 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Karl Schultz7b024b42018-08-30 16:18:18 -06001278 << "Application has too many descriptor sets in the pipeline layout to continue with gpu validation. "
1279 << "Validation is not modifying the pipeline layout. "
1280 << "Instrumented shaders are replaced with non-instrumented shaders.";
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001281 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device), strm.str().c_str());
Karl Schultz7b024b42018-08-30 16:18:18 -06001282 } else {
1283 // Modify the pipeline layout by:
1284 // 1. Copying the caller's descriptor set desc_layouts
1285 // 2. Fill in dummy descriptor layouts up to the max binding
1286 // 3. Fill in with the debug descriptor layout at the max binding slot
Tony-LunarG99b880b2019-09-26 11:19:52 -06001287 cpl_state->new_layouts.reserve(adjusted_max_desc_sets);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001288 cpl_state->new_layouts.insert(cpl_state->new_layouts.end(), &pCreateInfo->pSetLayouts[0],
1289 &pCreateInfo->pSetLayouts[pCreateInfo->setLayoutCount]);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001290 for (uint32_t i = pCreateInfo->setLayoutCount; i < adjusted_max_desc_sets - 1; ++i) {
1291 cpl_state->new_layouts.push_back(dummy_desc_layout);
Karl Schultz7b024b42018-08-30 16:18:18 -06001292 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001293 cpl_state->new_layouts.push_back(debug_desc_layout);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001294 cpl_state->modified_create_info.pSetLayouts = cpl_state->new_layouts.data();
Tony-LunarG99b880b2019-09-26 11:19:52 -06001295 cpl_state->modified_create_info.setLayoutCount = adjusted_max_desc_sets;
Karl Schultz7b024b42018-08-30 16:18:18 -06001296 }
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -07001297}
1298
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001299void GpuAssisted::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
1300 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
1301 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001302 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
1303
Karl Schultz7b024b42018-08-30 16:18:18 -06001304 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06001305 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz7b024b42018-08-30 16:18:18 -06001306 "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001307 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -06001308 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001309}
1310
Karl Schultz7b024b42018-08-30 16:18:18 -06001311// Free the device memory and descriptor set associated with a command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001312void GpuAssisted::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001313 if (aborted) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001314 return;
1315 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001316 auto gpuav_buffer_list = GetGpuAssistedBufferInfo(commandBuffer);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001317 for (auto buffer_info : gpuav_buffer_list) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001318 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001319 if (buffer_info.di_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001320 vmaDestroyBuffer(vmaAllocator, buffer_info.di_input_mem_block.buffer, buffer_info.di_input_mem_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001321 }
1322 if (buffer_info.bda_input_mem_block.buffer) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001323 vmaDestroyBuffer(vmaAllocator, buffer_info.bda_input_mem_block.buffer, buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -06001324 }
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001325 if (buffer_info.desc_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001326 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Tony-LunarGdcbc2c32019-05-06 10:17:44 -06001327 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001328 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001329 command_buffer_map.erase(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -07001330
Tony-LunarG99b880b2019-09-26 11:19:52 -06001331 auto &as_validation_info = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -07001332 auto &as_validation_buffer_infos = as_validation_info.validation_buffers[commandBuffer];
1333 for (auto &as_validation_buffer_info : as_validation_buffer_infos) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001334 vmaDestroyBuffer(vmaAllocator, as_validation_buffer_info.validation_buffer,
Jason Macnak83cfd582019-07-31 10:14:24 -07001335 as_validation_buffer_info.validation_buffer_allocation);
1336
1337 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001338 desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool,
1339 as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -07001340 }
1341 }
1342 as_validation_info.validation_buffers.erase(commandBuffer);
Karl Schultz7b024b42018-08-30 16:18:18 -06001343}
Karl Schultz7b024b42018-08-30 16:18:18 -06001344// Just gives a warning about a possible deadlock.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001345bool GpuAssisted::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
1346 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
1347 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
1348 uint32_t bufferMemoryBarrierCount,
1349 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
Jeff Bolz5c801d12019-10-09 10:38:45 -05001350 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001351 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
1352 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, HandleToUint64(commandBuffer),
Karl Schultz7b024b42018-08-30 16:18:18 -06001353 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
1354 "GPU_Assisted validation waits on queue completion. "
1355 "This wait could block the host's signaling of this event, resulting in deadlock.");
1356 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001357 return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001358}
1359
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001360void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1361 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
1362 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
1363 if (enabled.gpu_validation_reserve_binding_slot && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
1364 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
1365 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
1366 } else {
1367 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1368 HandleToUint64(physicalDevice), "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1369 "Unable to reserve descriptor binding slot on a device with only one slot.");
1370 }
1371 }
1372}
1373
1374void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1375 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
1376 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
1377 if (enabled.gpu_validation_reserve_binding_slot && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
1378 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
1379 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
1380 } else {
1381 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1382 HandleToUint64(physicalDevice), "UNASSIGNED-GPU-Assisted Validation Setup Error.",
1383 "Unable to reserve descriptor binding slot on a device with only one slot.");
1384 }
1385 }
1386}
1387
1388void GpuAssisted::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1389 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1390 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1391 void *cgpl_state_data) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001392 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001393 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
1394 PreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state, &new_pipeline_create_infos,
1395 VK_PIPELINE_BIND_POINT_GRAPHICS);
1396 cgpl_state->gpu_create_infos = new_pipeline_create_infos;
1397 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001398}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001399
1400void GpuAssisted::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1401 const VkComputePipelineCreateInfo *pCreateInfos,
1402 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1403 void *ccpl_state_data) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001404 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001405 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
1406 PreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state, &new_pipeline_create_infos,
1407 VK_PIPELINE_BIND_POINT_COMPUTE);
1408 ccpl_state->gpu_create_infos = new_pipeline_create_infos;
1409 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
Jason Macnak67407e72019-07-11 11:05:09 -07001410}
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001411
1412void GpuAssisted::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1413 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1414 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1415 void *crtpl_state_data) {
Jason Macnak67407e72019-07-11 11:05:09 -07001416 std::vector<safe_VkRayTracingPipelineCreateInfoNV> new_pipeline_create_infos;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001417 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
1418 PreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state, &new_pipeline_create_infos,
1419 VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
1420 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
1421 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001422}
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001423template <typename CreateInfo>
1424struct CreatePipelineTraits {};
1425template <>
1426struct CreatePipelineTraits<VkGraphicsPipelineCreateInfo> {
1427 using SafeType = safe_VkGraphicsPipelineCreateInfo;
1428 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->graphicsPipelineCI; }
1429 static uint32_t GetStageCount(const VkGraphicsPipelineCreateInfo &createInfo) { return createInfo.stageCount; }
1430 static VkShaderModule GetShaderModule(const VkGraphicsPipelineCreateInfo &createInfo, uint32_t stage) {
1431 return createInfo.pStages[stage].module;
1432 }
1433 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
1434 createInfo->pStages[stage].module = shader_module;
1435 }
1436};
1437
1438template <>
1439struct CreatePipelineTraits<VkComputePipelineCreateInfo> {
1440 using SafeType = safe_VkComputePipelineCreateInfo;
1441 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->computePipelineCI; }
1442 static uint32_t GetStageCount(const VkComputePipelineCreateInfo &createInfo) { return 1; }
1443 static VkShaderModule GetShaderModule(const VkComputePipelineCreateInfo &createInfo, uint32_t stage) {
1444 return createInfo.stage.module;
1445 }
1446 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
1447 assert(stage == 0);
1448 createInfo->stage.module = shader_module;
1449 }
1450};
1451template <>
1452struct CreatePipelineTraits<VkRayTracingPipelineCreateInfoNV> {
1453 using SafeType = safe_VkRayTracingPipelineCreateInfoNV;
1454 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->raytracingPipelineCI; }
1455 static uint32_t GetStageCount(const VkRayTracingPipelineCreateInfoNV &createInfo) { return createInfo.stageCount; }
1456 static VkShaderModule GetShaderModule(const VkRayTracingPipelineCreateInfoNV &createInfo, uint32_t stage) {
1457 return createInfo.pStages[stage].module;
1458 }
1459 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
1460 createInfo->pStages[stage].module = shader_module;
1461 }
1462};
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001463
1464// Examine the pipelines to see if they use the debug descriptor set binding index.
1465// If any do, create new non-instrumented shader modules and use them to replace the instrumented
1466// shaders in the pipeline. Return the (possibly) modified create infos to the caller.
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001467template <typename CreateInfo, typename SafeCreateInfo>
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001468void GpuAssisted::PreCallRecordPipelineCreations(uint32_t count, const CreateInfo *pCreateInfos,
1469 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001470 std::vector<std::shared_ptr<PIPELINE_STATE>> &pipe_state,
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001471 std::vector<SafeCreateInfo> *new_pipeline_create_infos,
1472 const VkPipelineBindPoint bind_point) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001473 using Accessor = CreatePipelineTraits<CreateInfo>;
Jason Macnak67407e72019-07-11 11:05:09 -07001474 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1475 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001476 return;
1477 }
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001478
Karl Schultz7b024b42018-08-30 16:18:18 -06001479 // Walk through all the pipelines, make a copy of each and flag each pipeline that contains a shader that uses the debug
1480 // descriptor set index.
1481 for (uint32_t pipeline = 0; pipeline < count; ++pipeline) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001482 uint32_t stageCount = Accessor::GetStageCount(pCreateInfos[pipeline]);
1483 new_pipeline_create_infos->push_back(Accessor::GetPipelineCI(pipe_state[pipeline].get()));
Jason Macnak67407e72019-07-11 11:05:09 -07001484
1485 bool replace_shaders = false;
Tony-LunarG99b880b2019-09-26 11:19:52 -06001486 if (pipe_state[pipeline]->active_slots.find(desc_set_bind_index) != pipe_state[pipeline]->active_slots.end()) {
Tony-LunarGd4da33b2019-04-16 16:28:22 -06001487 replace_shaders = true;
Karl Schultz7b024b42018-08-30 16:18:18 -06001488 }
Tony-LunarGd4da33b2019-04-16 16:28:22 -06001489 // If the app requests all available sets, the pipeline layout was not modified at pipeline layout creation and the already
1490 // instrumented shaders need to be replaced with uninstrumented shaders
Jeff Bolze7fc67b2019-10-04 12:29:31 -05001491 if (pipe_state[pipeline]->pipeline_layout->set_layouts.size() >= adjusted_max_desc_sets) {
Tony-LunarGd4da33b2019-04-16 16:28:22 -06001492 replace_shaders = true;
1493 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001494
Tony-LunarGd4da33b2019-04-16 16:28:22 -06001495 if (replace_shaders) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001496 for (uint32_t stage = 0; stage < stageCount; ++stage) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001497 const SHADER_MODULE_STATE *shader = GetShaderModuleState(Accessor::GetShaderModule(pCreateInfos[pipeline], stage));
Jason Macnak67407e72019-07-11 11:05:09 -07001498
Karl Schultz7b024b42018-08-30 16:18:18 -06001499 VkShaderModuleCreateInfo create_info = {};
1500 VkShaderModule shader_module;
1501 create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
1502 create_info.pCode = shader->words.data();
1503 create_info.codeSize = shader->words.size() * sizeof(uint32_t);
Tony-LunarG152a88b2019-03-20 15:42:24 -06001504 VkResult result = DispatchCreateShaderModule(device, &create_info, pAllocator, &shader_module);
Karl Schultz7b024b42018-08-30 16:18:18 -06001505 if (result == VK_SUCCESS) {
Petr Kraus6c4bdce2019-08-27 17:35:01 +02001506 Accessor::SetShaderModule(&(*new_pipeline_create_infos)[pipeline], shader_module, stage);
Karl Schultz7b024b42018-08-30 16:18:18 -06001507 } else {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001508 uint64_t moduleHandle = HandleToUint64(Accessor::GetShaderModule(pCreateInfos[pipeline], stage));
Jason Macnak67407e72019-07-11 11:05:09 -07001509 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, moduleHandle,
Karl Schultz7b024b42018-08-30 16:18:18 -06001510 "Unable to replace instrumented shader with non-instrumented one. "
1511 "Device could become unstable.");
1512 }
1513 }
1514 }
1515 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001516}
1517
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001518void GpuAssisted::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1519 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1520 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1521 VkResult result, void *cgpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001522 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
1523 pPipelines, result, cgpl_state_data);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001524 PostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001525}
Tony-LunarG99b880b2019-09-26 11:19:52 -06001526
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001527void GpuAssisted::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1528 const VkComputePipelineCreateInfo *pCreateInfos,
1529 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1530 VkResult result, void *ccpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001531 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
1532 result, ccpl_state_data);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001533 PostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE);
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::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
1537 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
1538 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1539 VkResult result, void *crtpl_state_data) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001540 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
1541 pPipelines, result, crtpl_state_data);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001542 PostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
Jason Macnak67407e72019-07-11 11:05:09 -07001543}
1544
Karl Schultz7b024b42018-08-30 16:18:18 -06001545// For every pipeline:
1546// - For every shader in a pipeline:
1547// - If the shader had to be replaced in PreCallRecord (because the pipeline is using the debug desc set index):
1548// - Destroy it since it has been bound into the pipeline by now. This is our only chance to delete it.
1549// - Track the shader in the shader_map
1550// - Save the shader binary if it contains debug code
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001551template <typename CreateInfo>
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001552void GpuAssisted::PostCallRecordPipelineCreations(const uint32_t count, const CreateInfo *pCreateInfos,
1553 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
1554 const VkPipelineBindPoint bind_point) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001555 using Accessor = CreatePipelineTraits<CreateInfo>;
Jason Macnak67407e72019-07-11 11:05:09 -07001556 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
1557 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
Tony-LunarGeb25bf52019-04-26 10:46:41 -06001558 return;
1559 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001560 for (uint32_t pipeline = 0; pipeline < count; ++pipeline) {
Tobin Ehlisfd68ba12019-08-22 08:16:18 -06001561 auto pipeline_state = ValidationStateTracker::GetPipelineState(pPipelines[pipeline]);
Karl Schultz7b024b42018-08-30 16:18:18 -06001562 if (nullptr == pipeline_state) continue;
Jason Macnak67407e72019-07-11 11:05:09 -07001563
1564 uint32_t stageCount = 0;
1565 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1566 stageCount = pipeline_state->graphicsPipelineCI.stageCount;
1567 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1568 stageCount = 1;
1569 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1570 stageCount = pipeline_state->raytracingPipelineCI.stageCount;
1571 } else {
1572 assert(false);
1573 }
1574
1575 for (uint32_t stage = 0; stage < stageCount; ++stage) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001576 if (pipeline_state->active_slots.find(desc_set_bind_index) != pipeline_state->active_slots.end()) {
Tony-LunarG7a804cd2019-07-23 15:01:41 -06001577 DispatchDestroyShaderModule(device, Accessor::GetShaderModule(pCreateInfos[pipeline], stage), pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001578 }
Jason Macnak67407e72019-07-11 11:05:09 -07001579
1580 const SHADER_MODULE_STATE *shader_state = nullptr;
1581 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1582 shader_state = GetShaderModuleState(pipeline_state->graphicsPipelineCI.pStages[stage].module);
1583 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1584 assert(stage == 0);
1585 shader_state = GetShaderModuleState(pipeline_state->computePipelineCI.stage.module);
1586 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1587 shader_state = GetShaderModuleState(pipeline_state->raytracingPipelineCI.pStages[stage].module);
1588 } else {
1589 assert(false);
1590 }
1591
Petr Krausede07f12019-11-13 01:45:15 +01001592 if (shader_state) {
1593 std::vector<unsigned int> code;
1594 // Save the shader binary if debug info is present.
1595 // The core_validation ShaderModule tracker saves the binary too, but discards it when the ShaderModule
1596 // is destroyed. Applications may destroy ShaderModules after they are placed in a pipeline and before
1597 // the pipeline is used, so we have to keep another copy.
1598 if (shader_state->has_valid_spirv) { // really checking for presense of SPIR-V code.
1599 for (auto insn : *shader_state) {
1600 if (insn.opcode() == spv::OpLine) {
1601 code = shader_state->words;
1602 break;
1603 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001604 }
1605 }
Petr Krausede07f12019-11-13 01:45:15 +01001606 shader_map[shader_state->gpu_validation_shader_id].pipeline = pipeline_state->pipeline;
1607 // Be careful to use the originally bound (instrumented) shader here, even if PreCallRecord had to back it
1608 // out with a non-instrumented shader. The non-instrumented shader (found in pCreateInfo) was destroyed above.
1609 VkShaderModule shader_module = VK_NULL_HANDLE;
1610 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1611 shader_module = pipeline_state->graphicsPipelineCI.pStages[stage].module;
1612 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1613 assert(stage == 0);
1614 shader_module = pipeline_state->computePipelineCI.stage.module;
1615 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1616 shader_module = pipeline_state->raytracingPipelineCI.pStages[stage].module;
1617 } else {
1618 assert(false);
1619 }
1620 shader_map[shader_state->gpu_validation_shader_id].shader_module = shader_module;
1621 shader_map[shader_state->gpu_validation_shader_id].pgm = std::move(code);
Karl Schultz7b024b42018-08-30 16:18:18 -06001622 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001623 }
1624 }
1625}
1626
1627// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001628void GpuAssisted::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001629 for (auto it = shader_map.begin(); it != shader_map.end();) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001630 if (it->second.pipeline == pipeline) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001631 it = shader_map.erase(it);
Karl Schultz7b024b42018-08-30 16:18:18 -06001632 } else {
1633 ++it;
1634 }
1635 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001636 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -06001637}
1638
1639// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001640bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
1641 uint32_t *unique_shader_id) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06001642 if (aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -06001643 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
1644
1645 // Load original shader SPIR-V
1646 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
1647 new_pgm.clear();
1648 new_pgm.reserve(num_words);
1649 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
1650
1651 // Call the optimizer to instrument the shader.
1652 // 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 -07001653 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Mark Lobodzinskif45e45f2019-04-19 14:15:39 -06001654 const bool descriptor_indexing = device_extensions.vk_ext_descriptor_indexing;
Karl Schultz7b024b42018-08-30 16:18:18 -06001655 using namespace spvtools;
1656 spv_target_env target_env = SPV_ENV_VULKAN_1_1;
1657 Optimizer optimizer(target_env);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001658 optimizer.RegisterPass(
1659 CreateInstBindlessCheckPass(desc_set_bind_index, unique_shader_module_id, descriptor_indexing, descriptor_indexing, 2));
Karl Schultz7b024b42018-08-30 16:18:18 -06001660 optimizer.RegisterPass(CreateAggressiveDCEPass());
Tony-LunarG99b880b2019-09-26 11:19:52 -06001661 if (device_extensions.vk_ext_buffer_device_address && shaderInt64)
1662 optimizer.RegisterPass(CreateInstBuffAddrCheckPass(desc_set_bind_index, unique_shader_module_id));
Karl Schultz7b024b42018-08-30 16:18:18 -06001663 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm);
1664 if (!pass) {
Mark Lobodzinski586d10e2019-03-08 18:19:48 -07001665 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, VK_NULL_HANDLE,
Karl Schultz7b024b42018-08-30 16:18:18 -06001666 "Failure to instrument shader. Proceeding with non-instrumented shader.");
1667 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001668 *unique_shader_id = unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -06001669 return pass;
1670}
Mark Lobodzinski01734072019-02-13 17:39:15 -07001671// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001672void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
1673 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
1674 void *csm_state_data) {
1675 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
1676 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -06001677 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001678 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
1679 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
Karl Schultz7b024b42018-08-30 16:18:18 -06001680 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001681}
1682
1683// Generate the stage-specific part of the message.
1684static void GenerateStageMessage(const uint32_t *debug_record, std::string &msg) {
1685 using namespace spvtools;
1686 std::ostringstream strm;
1687 switch (debug_record[kInstCommonOutStageIdx]) {
Jason Macnak67407e72019-07-11 11:05:09 -07001688 case spv::ExecutionModelVertex: {
Tony-LunarG6ff87582019-02-08 10:29:07 -07001689 strm << "Stage = Vertex. Vertex Index = " << debug_record[kInstVertOutVertexIndex]
1690 << " Instance Index = " << debug_record[kInstVertOutInstanceIndex] << ". ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001691 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001692 case spv::ExecutionModelTessellationControl: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001693 strm << "Stage = Tessellation Control. Invocation ID = " << debug_record[kInstTessCtlOutInvocationId]
1694 << ", Primitive ID = " << debug_record[kInstTessCtlOutPrimitiveId];
Karl Schultz7b024b42018-08-30 16:18:18 -06001695 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001696 case spv::ExecutionModelTessellationEvaluation: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001697 strm << "Stage = Tessellation Eval. Primitive ID = " << debug_record[kInstTessEvalOutPrimitiveId]
1698 << ", TessCoord (u, v) = (" << debug_record[kInstTessEvalOutTessCoordU] << ", "
1699 << debug_record[kInstTessEvalOutTessCoordV] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001700 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001701 case spv::ExecutionModelGeometry: {
Karl Schultz7b024b42018-08-30 16:18:18 -06001702 strm << "Stage = Geometry. Primitive ID = " << debug_record[kInstGeomOutPrimitiveId]
1703 << " Invocation ID = " << debug_record[kInstGeomOutInvocationId] << ". ";
1704 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001705 case spv::ExecutionModelFragment: {
Karl Schultz7b024b42018-08-30 16:18:18 -06001706 strm << "Stage = Fragment. Fragment coord (x,y) = ("
1707 << *reinterpret_cast<const float *>(&debug_record[kInstFragOutFragCoordX]) << ", "
1708 << *reinterpret_cast<const float *>(&debug_record[kInstFragOutFragCoordY]) << "). ";
1709 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001710 case spv::ExecutionModelGLCompute: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001711 strm << "Stage = Compute. Global invocation ID (x, y, z) = (" << debug_record[kInstCompOutGlobalInvocationIdX] << ", "
1712 << debug_record[kInstCompOutGlobalInvocationIdY] << ", " << debug_record[kInstCompOutGlobalInvocationIdZ] << " )";
Karl Schultz7b024b42018-08-30 16:18:18 -06001713 } break;
Jason Macnak67407e72019-07-11 11:05:09 -07001714 case spv::ExecutionModelRayGenerationNV: {
1715 strm << "Stage = Ray Generation. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1716 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1717 } break;
1718 case spv::ExecutionModelIntersectionNV: {
1719 strm << "Stage = Intersection. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1720 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1721 } break;
1722 case spv::ExecutionModelAnyHitNV: {
1723 strm << "Stage = Any Hit. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1724 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1725 } break;
1726 case spv::ExecutionModelClosestHitNV: {
1727 strm << "Stage = Closest Hit. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1728 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1729 } break;
1730 case spv::ExecutionModelMissNV: {
1731 strm << "Stage = Miss. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1732 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1733 } break;
1734 case spv::ExecutionModelCallableNV: {
1735 strm << "Stage = Callable. Global Launch ID (x,y,z) = (" << debug_record[kInstRayTracingOutLaunchIdX] << ", "
1736 << debug_record[kInstRayTracingOutLaunchIdY] << ", " << debug_record[kInstRayTracingOutLaunchIdZ] << "). ";
1737 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001738 default: {
1739 strm << "Internal Error (unexpected stage = " << debug_record[kInstCommonOutStageIdx] << "). ";
1740 assert(false);
1741 } break;
1742 }
1743 msg = strm.str();
1744}
1745
1746// Generate the part of the message describing the violation.
1747static void GenerateValidationMessage(const uint32_t *debug_record, std::string &msg, std::string &vuid_msg) {
1748 using namespace spvtools;
1749 std::ostringstream strm;
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001750 switch (debug_record[kInst2ValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001751 case kInstErrorBindlessBounds: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001752 strm << "Index of " << debug_record[kInst2BindlessBoundsOutDescIndex] << " used to index descriptor array of length "
1753 << debug_record[kInst2BindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001754 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -06001755 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001756 case kInstErrorBindlessUninit: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001757 strm << "Descriptor index " << debug_record[kInst2BindlessUninitOutDescIndex] << " is uninitialized. ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -07001758 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -06001759 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001760 case kInstErrorBuffAddrUnallocRef: {
1761 uint64_t *ptr = (uint64_t *)&debug_record[kInst2BuffAddrUnallocOutDescPtrLo];
1762 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
1763 vuid_msg = "UNASSIGNED-Device address out of bounds";
1764 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001765 default: {
Tony-LunarG751ebbe2019-07-24 16:41:36 -06001766 strm << "Internal Error (unexpected error type = " << debug_record[kInst2ValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001767 vuid_msg = "UNASSIGNED-Internal Error";
1768 assert(false);
1769 } break;
1770 }
1771 msg = strm.str();
1772}
1773
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001774static std::string LookupDebugUtilsName(const debug_report_data *report_data, const uint64_t object) {
Mark Lobodzinski1d7313a2019-02-07 11:04:42 -07001775 auto object_label = report_data->DebugReportGetUtilsObjectName(object);
1776 if (object_label != "") {
1777 object_label = "(" + object_label + ")";
Karl Schultz7b024b42018-08-30 16:18:18 -06001778 }
Mark Lobodzinski1d7313a2019-02-07 11:04:42 -07001779 return object_label;
Karl Schultz7b024b42018-08-30 16:18:18 -06001780}
1781
1782// Generate message from the common portion of the debug report record.
Mark Lobodzinski33a34b82019-04-25 11:38:36 -06001783static void GenerateCommonMessage(const debug_report_data *report_data, const CMD_BUFFER_STATE *cb_node,
1784 const uint32_t *debug_record, const VkShaderModule shader_module_handle,
Jason Macnak67407e72019-07-11 11:05:09 -07001785 const VkPipeline pipeline_handle, const VkPipelineBindPoint pipeline_bind_point,
1786 const uint32_t operation_index, std::string &msg) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001787 using namespace spvtools;
1788 std::ostringstream strm;
1789 if (shader_module_handle == VK_NULL_HANDLE) {
1790 strm << std::hex << std::showbase << "Internal Error: Unable to locate information for shader used in command buffer "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001791 << LookupDebugUtilsName(report_data, HandleToUint64(cb_node->commandBuffer)) << "("
Karl Schultz7b024b42018-08-30 16:18:18 -06001792 << HandleToUint64(cb_node->commandBuffer) << "). ";
1793 assert(true);
1794 } else {
1795 strm << std::hex << std::showbase << "Command buffer "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001796 << LookupDebugUtilsName(report_data, HandleToUint64(cb_node->commandBuffer)) << "("
Jason Macnak67407e72019-07-11 11:05:09 -07001797 << HandleToUint64(cb_node->commandBuffer) << "). ";
1798 if (pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1799 strm << "Draw ";
1800 } else if (pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1801 strm << "Compute ";
1802 } else if (pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
1803 strm << "Ray Trace ";
1804 } else {
1805 assert(false);
1806 strm << "Unknown Pipeline Operation ";
1807 }
1808 strm << "Index " << operation_index << ". "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001809 << "Pipeline " << LookupDebugUtilsName(report_data, HandleToUint64(pipeline_handle)) << "("
Karl Schultz7b024b42018-08-30 16:18:18 -06001810 << HandleToUint64(pipeline_handle) << "). "
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -07001811 << "Shader Module " << LookupDebugUtilsName(report_data, HandleToUint64(shader_module_handle)) << "("
Karl Schultz7b024b42018-08-30 16:18:18 -06001812 << HandleToUint64(shader_module_handle) << "). ";
1813 }
1814 strm << std::dec << std::noshowbase;
1815 strm << "Shader Instruction Index = " << debug_record[kInstCommonOutInstructionIdx] << ". ";
1816 msg = strm.str();
1817}
1818
1819// Read the contents of the SPIR-V OpSource instruction and any following continuation instructions.
1820// Split the single string into a vector of strings, one for each line, for easier processing.
Mark Lobodzinski3c59d972019-04-25 11:28:14 -06001821static void ReadOpSource(const SHADER_MODULE_STATE &shader, const uint32_t reported_file_id,
1822 std::vector<std::string> &opsource_lines) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001823 for (auto insn : shader) {
1824 if ((insn.opcode() == spv::OpSource) && (insn.len() >= 5) && (insn.word(3) == reported_file_id)) {
1825 std::istringstream in_stream;
1826 std::string cur_line;
1827 in_stream.str((char *)&insn.word(4));
1828 while (std::getline(in_stream, cur_line)) {
1829 opsource_lines.push_back(cur_line);
1830 }
1831 while ((++insn).opcode() == spv::OpSourceContinued) {
1832 in_stream.str((char *)&insn.word(1));
1833 while (std::getline(in_stream, cur_line)) {
1834 opsource_lines.push_back(cur_line);
1835 }
1836 }
1837 break;
1838 }
1839 }
1840}
Tony-LunarG03059b72019-02-19 13:57:41 -07001841
1842// The task here is to search the OpSource content to find the #line directive with the
1843// line number that is closest to, but still prior to the reported error line number and
1844// still within the reported filename.
1845// From this known position in the OpSource content we can add the difference between
1846// the #line line number and the reported error line number to determine the location
1847// in the OpSource content of the reported error line.
1848//
1849// Considerations:
1850// - Look only at #line directives that specify the reported_filename since
1851// the reported error line number refers to its location in the reported filename.
1852// - If a #line directive does not have a filename, the file is the reported filename, or
1853// the filename found in a prior #line directive. (This is C-preprocessor behavior)
1854// - It is possible (e.g., inlining) for blocks of code to get shuffled out of their
1855// original order and the #line directives are used to keep the numbering correct. This
1856// is why we need to examine the entire contents of the source, instead of leaving early
1857// when finding a #line line number larger than the reported error line number.
1858//
1859
1860// GCC 4.8 has a problem with std::regex that is fixed in GCC 4.9. Provide fallback code for 4.8
1861#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
1862
1863#if defined(__GNUC__) && GCC_VERSION < 40900
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001864static bool GetLineAndFilename(const std::string string, uint32_t *linenumber, std::string &filename) {
Tony-LunarG03059b72019-02-19 13:57:41 -07001865 // # line <linenumber> "<filename>" or
1866 // #line <linenumber> "<filename>"
1867 std::vector<std::string> tokens;
1868 std::stringstream stream(string);
1869 std::string temp;
1870 uint32_t line_index = 0;
1871
1872 while (stream >> temp) tokens.push_back(temp);
1873 auto size = tokens.size();
1874 if (size > 1) {
1875 if (tokens[0] == "#" && tokens[1] == "line") {
1876 line_index = 2;
1877 } else if (tokens[0] == "#line") {
1878 line_index = 1;
1879 }
1880 }
1881 if (0 == line_index) return false;
1882 *linenumber = std::stoul(tokens[line_index]);
1883 uint32_t filename_index = line_index + 1;
1884 // Remove enclosing double quotes around filename
1885 if (size > filename_index) filename = tokens[filename_index].substr(1, tokens[filename_index].size() - 2);
1886 return true;
1887}
1888#else
1889static bool GetLineAndFilename(const std::string string, uint32_t *linenumber, std::string &filename) {
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001890 static const std::regex line_regex( // matches #line directives
1891 "^" // beginning of line
1892 "\\s*" // optional whitespace
1893 "#" // required text
1894 "\\s*" // optional whitespace
1895 "line" // required text
1896 "\\s+" // required whitespace
1897 "([0-9]+)" // required first capture - line number
1898 "(\\s+)?" // optional second capture - whitespace
1899 "(\".+\")?" // optional third capture - quoted filename with at least one char inside
1900 ".*"); // rest of line (needed when using std::regex_match since the entire line is tested)
Karl Schultz7b024b42018-08-30 16:18:18 -06001901
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001902 std::smatch captures;
1903
1904 bool found_line = std::regex_match(string, captures, line_regex);
1905 if (!found_line) return false;
1906
1907 // filename is optional and considered found only if the whitespace and the filename are captured
1908 if (captures[2].matched && captures[3].matched) {
1909 // Remove enclosing double quotes. The regex guarantees the quotes and at least one char.
1910 filename = captures[3].str().substr(1, captures[3].str().size() - 2);
1911 }
1912 *linenumber = std::stoul(captures[1]);
1913 return true;
1914}
Tony-LunarG03059b72019-02-19 13:57:41 -07001915#endif // GCC_VERSION
1916
Karl Schultz7b024b42018-08-30 16:18:18 -06001917// Extract the filename, line number, and column number from the correct OpLine and build a message string from it.
1918// Scan the source (from OpSource) to find the line of source at the reported line number and place it in another message string.
1919static void GenerateSourceMessages(const std::vector<unsigned int> &pgm, const uint32_t *debug_record, std::string &filename_msg,
1920 std::string &source_msg) {
1921 using namespace spvtools;
1922 std::ostringstream filename_stream;
1923 std::ostringstream source_stream;
Mark Lobodzinski3c59d972019-04-25 11:28:14 -06001924 SHADER_MODULE_STATE shader;
Karl Schultz7b024b42018-08-30 16:18:18 -06001925 shader.words = pgm;
1926 // Find the OpLine just before the failing instruction indicated by the debug info.
1927 // SPIR-V can only be iterated in the forward direction due to its opcode/length encoding.
1928 uint32_t instruction_index = 0;
1929 uint32_t reported_file_id = 0;
1930 uint32_t reported_line_number = 0;
1931 uint32_t reported_column_number = 0;
1932 if (shader.words.size() > 0) {
1933 for (auto insn : shader) {
1934 if (insn.opcode() == spv::OpLine) {
1935 reported_file_id = insn.word(1);
1936 reported_line_number = insn.word(2);
1937 reported_column_number = insn.word(3);
1938 }
1939 if (instruction_index == debug_record[kInstCommonOutInstructionIdx]) {
1940 break;
1941 }
1942 instruction_index++;
1943 }
1944 }
1945 // Create message with file information obtained from the OpString pointed to by the discovered OpLine.
1946 std::string reported_filename;
1947 if (reported_file_id == 0) {
1948 filename_stream
1949 << "Unable to find SPIR-V OpLine for source information. Build shader with debug info to get source information.";
1950 } else {
1951 bool found_opstring = false;
1952 for (auto insn : shader) {
1953 if ((insn.opcode() == spv::OpString) && (insn.len() >= 3) && (insn.word(1) == reported_file_id)) {
1954 found_opstring = true;
1955 reported_filename = (char *)&insn.word(2);
1956 if (reported_filename.empty()) {
1957 filename_stream << "Shader validation error occurred at line " << reported_line_number;
1958 } else {
1959 filename_stream << "Shader validation error occurred in file: " << reported_filename << " at line "
1960 << reported_line_number;
1961 }
1962 if (reported_column_number > 0) {
1963 filename_stream << ", column " << reported_column_number;
1964 }
1965 filename_stream << ".";
1966 break;
1967 }
1968 }
1969 if (!found_opstring) {
1970 filename_stream << "Unable to find SPIR-V OpString for file id " << reported_file_id << " from OpLine instruction.";
1971 }
1972 }
1973 filename_msg = filename_stream.str();
1974
1975 // Create message to display source code line containing error.
1976 if ((reported_file_id != 0)) {
1977 // Read the source code and split it up into separate lines.
1978 std::vector<std::string> opsource_lines;
1979 ReadOpSource(shader, reported_file_id, opsource_lines);
1980 // Find the line in the OpSource content that corresponds to the reported error file and line.
1981 if (!opsource_lines.empty()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001982 uint32_t saved_line_number = 0;
1983 std::string current_filename = reported_filename; // current "preprocessor" filename state.
1984 std::vector<std::string>::size_type saved_opsource_offset = 0;
1985 bool found_best_line = false;
1986 for (auto it = opsource_lines.begin(); it != opsource_lines.end(); ++it) {
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001987 uint32_t parsed_line_number;
1988 std::string parsed_filename;
1989 bool found_line = GetLineAndFilename(*it, &parsed_line_number, parsed_filename);
Karl Schultz7b024b42018-08-30 16:18:18 -06001990 if (!found_line) continue;
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001991
1992 bool found_filename = parsed_filename.size() > 0;
Karl Schultz7b024b42018-08-30 16:18:18 -06001993 if (found_filename) {
Tony-LunarG16f9b7e2019-02-19 13:02:03 -07001994 current_filename = parsed_filename;
Karl Schultz7b024b42018-08-30 16:18:18 -06001995 }
1996 if ((!found_filename) || (current_filename == reported_filename)) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001997 // Update the candidate best line directive, if the current one is prior and closer to the reported line
1998 if (reported_line_number >= parsed_line_number) {
1999 if (!found_best_line ||
2000 (reported_line_number - parsed_line_number <= reported_line_number - saved_line_number)) {
2001 saved_line_number = parsed_line_number;
2002 saved_opsource_offset = std::distance(opsource_lines.begin(), it);
2003 found_best_line = true;
2004 }
2005 }
2006 }
2007 }
2008 if (found_best_line) {
2009 assert(reported_line_number >= saved_line_number);
2010 std::vector<std::string>::size_type opsource_index =
2011 (reported_line_number - saved_line_number) + 1 + saved_opsource_offset;
2012 if (opsource_index < opsource_lines.size()) {
2013 source_stream << "\n" << reported_line_number << ": " << opsource_lines[opsource_index].c_str();
2014 } else {
2015 source_stream << "Internal error: calculated source line of " << opsource_index << " for source size of "
2016 << opsource_lines.size() << " lines.";
2017 }
2018 } else {
2019 source_stream << "Unable to find suitable #line directive in SPIR-V OpSource.";
2020 }
2021 } else {
2022 source_stream << "Unable to find SPIR-V OpSource.";
2023 }
2024 }
2025 source_msg = source_stream.str();
2026}
2027
2028// Pull together all the information from the debug record to build the error message strings,
2029// and then assemble them into a single message string.
2030// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
2031// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
2032// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
2033// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
2034//
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002035void GpuAssisted::AnalyzeAndReportError(CMD_BUFFER_STATE *cb_node, VkQueue queue, VkPipelineBindPoint pipeline_bind_point,
2036 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06002037 using namespace spvtools;
2038 const uint32_t total_words = debug_output_buffer[0];
2039 // A zero here means that the shader instrumentation didn't write anything.
2040 // If you have nothing to say, don't say it here.
2041 if (0 == total_words) {
2042 return;
2043 }
2044 // The first word in the debug output buffer is the number of words that would have
2045 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
2046 // The number of words actually written by the shaders is determined by the size of the buffer
2047 // we provide via the descriptor. So, we process only the number of words that can fit in the
2048 // buffer.
2049 // Each "report" written by the shader instrumentation is considered a "record". This function
2050 // is hard-coded to process only one record because it expects the buffer to be large enough to
2051 // hold only one record. If there is a desire to process more than one record, this function needs
2052 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06002053 std::string validation_message;
2054 std::string stage_message;
2055 std::string common_message;
2056 std::string filename_message;
2057 std::string source_message;
2058 std::string vuid_msg;
2059 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
2060 VkPipeline pipeline_handle = VK_NULL_HANDLE;
2061 std::vector<unsigned int> pgm;
2062 // The first record starts at this offset after the total_words.
2063 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
2064 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
2065 // by the instrumented shader.
Tony-LunarG99b880b2019-09-26 11:19:52 -06002066 auto it = shader_map.find(debug_record[kInstCommonOutShaderId]);
2067 if (it != shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06002068 shader_module_handle = it->second.shader_module;
2069 pipeline_handle = it->second.pipeline;
2070 pgm = it->second.pgm;
2071 }
2072 GenerateValidationMessage(debug_record, validation_message, vuid_msg);
2073 GenerateStageMessage(debug_record, stage_message);
Jason Macnak67407e72019-07-11 11:05:09 -07002074 GenerateCommonMessage(report_data, cb_node, debug_record, shader_module_handle, pipeline_handle, pipeline_bind_point,
2075 operation_index, common_message);
Karl Schultz7b024b42018-08-30 16:18:18 -06002076 GenerateSourceMessages(pgm, debug_record, filename_message, source_message);
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002077 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 -06002078 vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
2079 filename_message.c_str(), source_message.c_str());
2080 // The debug record at word kInstCommonOutSize is the number of words in the record
2081 // written by the shader. Clear the entire record plus the total_words word at the start.
Tony-LunarG751ebbe2019-07-24 16:41:36 -06002082 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], (uint32_t)kInst2MaxOutCnt);
Karl Schultz7b024b42018-08-30 16:18:18 -06002083 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
2084}
2085
Tony-LunarG5ad17272019-03-05 12:48:24 -07002086// For the given command buffer, map its debug data buffers and read their contents for analysis.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002087void GpuAssisted::ProcessInstrumentationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node) {
Petr Kraus6c4bdce2019-08-27 17:35:01 +02002088 if (cb_node && (cb_node->hasDrawCmd || cb_node->hasTraceRaysCmd || cb_node->hasDispatchCmd)) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002089 auto gpu_buffer_list = GetGpuAssistedBufferInfo(cb_node->commandBuffer);
Tony-LunarG5ad17272019-03-05 12:48:24 -07002090 uint32_t draw_index = 0;
Jason Macnak67407e72019-07-11 11:05:09 -07002091 uint32_t compute_index = 0;
2092 uint32_t ray_trace_index = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002093
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002094 for (auto &buffer_info : gpu_buffer_list) {
Petr Kraus6c4bdce2019-08-27 17:35:01 +02002095 char *pData;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002096 VkResult result = vmaMapMemory(vmaAllocator, buffer_info.output_mem_block.allocation, (void **)&pData);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002097 // Analyze debug output buffer
2098 if (result == VK_SUCCESS) {
Jason Macnak67407e72019-07-11 11:05:09 -07002099 uint32_t operation_index = 0;
2100 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
2101 operation_index = draw_index;
2102 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
2103 operation_index = compute_index;
2104 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
2105 operation_index = ray_trace_index;
2106 } else {
2107 assert(false);
2108 }
2109
2110 AnalyzeAndReportError(cb_node, queue, buffer_info.pipeline_bind_point, operation_index, (uint32_t *)pData);
Tony-LunarG99b880b2019-09-26 11:19:52 -06002111 vmaUnmapMemory(vmaAllocator, buffer_info.output_mem_block.allocation);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002112 }
Jason Macnak67407e72019-07-11 11:05:09 -07002113
2114 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
2115 draw_index++;
2116 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
2117 compute_index++;
2118 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
2119 ray_trace_index++;
2120 } else {
2121 assert(false);
2122 }
Karl Schultz7b024b42018-08-30 16:18:18 -06002123 }
2124 }
2125}
2126
Tony-LunarG81efe392019-03-07 15:43:27 -07002127// 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 -06002128void GpuAssisted::UpdateInstrumentationBuffer(CMD_BUFFER_STATE *cb_node) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002129 auto gpu_buffer_list = GetGpuAssistedBufferInfo(cb_node->commandBuffer);
Tony-LunarG81efe392019-03-07 15:43:27 -07002130 uint32_t *pData;
2131 for (auto &buffer_info : gpu_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002132 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002133 VkResult result = vmaMapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation, (void **)&pData);
Tony-LunarG81efe392019-03-07 15:43:27 -07002134 if (result == VK_SUCCESS) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002135 for (auto update : buffer_info.di_input_mem_block.update_at_submit) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002136 if (update.second->updated) pData[update.first] = 1;
2137 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06002138 vmaUnmapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07002139 }
2140 }
2141 }
2142}
2143
Karl Schultz58674242019-01-22 15:35:02 -07002144// Submit a memory barrier on graphics queues.
2145// Lazy-create and record the needed command buffer.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002146void GpuAssisted::SubmitBarrier(VkQueue queue) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002147 auto queue_barrier_command_info_it = queue_barrier_command_infos.emplace(queue, GpuAssistedQueueBarrierCommandInfo{});
Jason Macnak8eae5722019-07-17 15:17:45 -07002148 if (queue_barrier_command_info_it.second) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002149 GpuAssistedQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_it.first->second;
Karl Schultz58674242019-01-22 15:35:02 -07002150
Jason Macnak8eae5722019-07-17 15:17:45 -07002151 uint32_t queue_family_index = 0;
Karl Schultz58674242019-01-22 15:35:02 -07002152
Jason Macnak8eae5722019-07-17 15:17:45 -07002153 auto queue_state_it = queueMap.find(queue);
2154 if (queue_state_it != queueMap.end()) {
2155 queue_family_index = queue_state_it->second.queueFamilyIndex;
2156 }
Karl Schultz58674242019-01-22 15:35:02 -07002157
Jason Macnak8eae5722019-07-17 15:17:45 -07002158 VkResult result = VK_SUCCESS;
2159
Karl Schultz58674242019-01-22 15:35:02 -07002160 VkCommandPoolCreateInfo pool_create_info = {};
2161 pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
2162 pool_create_info.queueFamilyIndex = queue_family_index;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002163 result = DispatchCreateCommandPool(device, &pool_create_info, nullptr, &queue_barrier_command_info.barrier_command_pool);
Karl Schultz58674242019-01-22 15:35:02 -07002164 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002165 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz58674242019-01-22 15:35:02 -07002166 "Unable to create command pool for barrier CB.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002167 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
Karl Schultz58674242019-01-22 15:35:02 -07002168 return;
2169 }
2170
Jason Macnak8eae5722019-07-17 15:17:45 -07002171 VkCommandBufferAllocateInfo buffer_alloc_info = {};
2172 buffer_alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002173 buffer_alloc_info.commandPool = queue_barrier_command_info.barrier_command_pool;
Jason Macnak8eae5722019-07-17 15:17:45 -07002174 buffer_alloc_info.commandBufferCount = 1;
2175 buffer_alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002176 result = DispatchAllocateCommandBuffers(device, &buffer_alloc_info, &queue_barrier_command_info.barrier_command_buffer);
Karl Schultz58674242019-01-22 15:35:02 -07002177 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002178 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Karl Schultz58674242019-01-22 15:35:02 -07002179 "Unable to create barrier command buffer.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002180 DispatchDestroyCommandPool(device, queue_barrier_command_info.barrier_command_pool, nullptr);
2181 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
2182 queue_barrier_command_info.barrier_command_buffer = VK_NULL_HANDLE;
Karl Schultz58674242019-01-22 15:35:02 -07002183 return;
2184 }
2185
2186 // Hook up command buffer dispatch
Tony-LunarG99b880b2019-09-26 11:19:52 -06002187 vkSetDeviceLoaderData(device, queue_barrier_command_info.barrier_command_buffer);
Karl Schultz58674242019-01-22 15:35:02 -07002188
2189 // Record a global memory barrier to force availability of device memory operations to the host domain.
2190 VkCommandBufferBeginInfo command_buffer_begin_info = {};
2191 command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002192 result = DispatchBeginCommandBuffer(queue_barrier_command_info.barrier_command_buffer, &command_buffer_begin_info);
Karl Schultz58674242019-01-22 15:35:02 -07002193 if (result == VK_SUCCESS) {
2194 VkMemoryBarrier memory_barrier = {};
2195 memory_barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2196 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
2197 memory_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
2198
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002199 DispatchCmdPipelineBarrier(queue_barrier_command_info.barrier_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
Mark Lobodzinskie514d1a2019-03-12 08:47:45 -06002200 VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &memory_barrier, 0, nullptr, 0, nullptr);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002201 DispatchEndCommandBuffer(queue_barrier_command_info.barrier_command_buffer);
Karl Schultz58674242019-01-22 15:35:02 -07002202 }
2203 }
2204
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002205 GpuAssistedQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_it.first->second;
2206 if (queue_barrier_command_info.barrier_command_buffer != VK_NULL_HANDLE) {
Karl Schultz58674242019-01-22 15:35:02 -07002207 VkSubmitInfo submit_info = {};
2208 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2209 submit_info.commandBufferCount = 1;
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002210 submit_info.pCommandBuffers = &queue_barrier_command_info.barrier_command_buffer;
Tony-LunarG152a88b2019-03-20 15:42:24 -06002211 DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
Karl Schultz58674242019-01-22 15:35:02 -07002212 }
2213}
2214
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002215void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002216 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
2217 const VkSubmitInfo *submit = &pSubmits[submit_idx];
2218 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06002219 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07002220 UpdateInstrumentationBuffer(cb_node);
2221 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
2222 UpdateInstrumentationBuffer(secondaryCmdBuffer);
2223 }
2224 }
2225 }
2226}
2227
Karl Schultz58674242019-01-22 15:35:02 -07002228// Issue a memory barrier to make GPU-written data available to host.
2229// Wait for the queue to complete execution.
2230// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002231void GpuAssisted::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
2232 VkResult result) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002233 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002234
Tony-LunarG99b880b2019-09-26 11:19:52 -06002235 if (aborted) return;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06002236 bool buffers_present = false;
2237 // Don't QueueWaitIdle if there's nothing to process
2238 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
2239 const VkSubmitInfo *submit = &pSubmits[submit_idx];
2240 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
2241 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG99b880b2019-09-26 11:19:52 -06002242 if (GetGpuAssistedBufferInfo(cb_node->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd)
Jason Macnak83cfd582019-07-31 10:14:24 -07002243 buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06002244 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002245 if (GetGpuAssistedBufferInfo(secondaryCmdBuffer->commandBuffer).size() || cb_node->hasBuildAccelerationStructureCmd)
Jason Macnak83cfd582019-07-31 10:14:24 -07002246 buffers_present = true;
Tony-LunarG3cc795e2019-08-26 12:13:50 -06002247 }
2248 }
2249 }
2250 if (!buffers_present) return;
Karl Schultz58674242019-01-22 15:35:02 -07002251
Mark Lobodzinskie377ac32019-03-07 16:12:46 -07002252 SubmitBarrier(queue);
Karl Schultz58674242019-01-22 15:35:02 -07002253
Tony-LunarG152a88b2019-03-20 15:42:24 -06002254 DispatchQueueWaitIdle(queue);
Karl Schultz58674242019-01-22 15:35:02 -07002255
Karl Schultz7b024b42018-08-30 16:18:18 -06002256 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
2257 const VkSubmitInfo *submit = &pSubmits[submit_idx];
2258 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06002259 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Mark Lobodzinskie377ac32019-03-07 16:12:46 -07002260 ProcessInstrumentationBuffer(queue, cb_node);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002261 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06002262 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Mark Lobodzinskie377ac32019-03-07 16:12:46 -07002263 ProcessInstrumentationBuffer(queue, secondaryCmdBuffer);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002264 ProcessAccelerationStructureBuildValidationBuffer(queue, cb_node);
Karl Schultz7b024b42018-08-30 16:18:18 -06002265 }
2266 }
2267 }
2268}
Tony-LunarGb2501d22019-01-28 09:59:13 -07002269
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002270void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
2271 uint32_t firstVertex, uint32_t firstInstance) {
2272 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2273}
2274
2275void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
2276 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
2277 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2278}
2279
2280void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
2281 uint32_t stride) {
2282 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2283}
2284
2285void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
2286 uint32_t count, uint32_t stride) {
2287 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
2288}
2289
2290void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
2291 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
2292}
2293
2294void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
2295 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
2296}
2297
2298void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
2299 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
2300 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
2301 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
2302 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
2303 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
2304 uint32_t width, uint32_t height, uint32_t depth) {
2305 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
2306}
2307
2308void GpuAssisted::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
2309 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
2310 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
2311 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
2312 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
2313 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
2314 uint32_t width, uint32_t height, uint32_t depth) {
2315 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
2316 cb_state->hasTraceRaysCmd = true;
2317}
2318
2319void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Jason Macnak67407e72019-07-11 11:05:09 -07002320 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
2321 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
andreygca287f22019-04-10 00:15:33 +03002322 return;
2323 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002324 VkResult result;
2325
Tony-LunarG99b880b2019-09-26 11:19:52 -06002326 if (aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002327
2328 std::vector<VkDescriptorSet> desc_sets;
2329 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002330 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002331 assert(result == VK_SUCCESS);
2332 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002333 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Tony-LunarGb2501d22019-01-28 09:59:13 -07002334 "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002335 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002336 return;
2337 }
2338
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002339 VkDescriptorBufferInfo output_desc_buffer_info = {};
Tony-LunarG99b880b2019-09-26 11:19:52 -06002340 output_desc_buffer_info.range = output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002341
Mark Lobodzinskicefe42f2019-04-25 12:16:27 -06002342 auto cb_node = GetCBState(cmd_buffer);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002343 if (!cb_node) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002344 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device), "Unrecognized command buffer");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002345 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002346 return;
2347 }
2348
Tony-LunarG81efe392019-03-07 15:43:27 -07002349 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002350 GpuAssistedDeviceMemoryBlock output_block = {};
Tony-LunarG0e564722019-03-19 16:09:14 -06002351 VkBufferCreateInfo bufferInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
Tony-LunarG99b880b2019-09-26 11:19:52 -06002352 bufferInfo.size = output_buffer_size;
Tony-LunarG0e564722019-03-19 16:09:14 -06002353 bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
2354 VmaAllocationCreateInfo allocInfo = {};
2355 allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002356 result = vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002357 if (result != VK_SUCCESS) {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002358 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
Tony-LunarGb2501d22019-01-28 09:59:13 -07002359 "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002360 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002361 return;
2362 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002363
Tony-LunarG81efe392019-03-07 15:43:27 -07002364 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGa77cade2019-03-06 10:49:22 -07002365 uint32_t *pData;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002366 result = vmaMapMemory(vmaAllocator, output_block.allocation, (void **)&pData);
Tony-LunarG0e564722019-03-19 16:09:14 -06002367 if (result == VK_SUCCESS) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002368 memset(pData, 0, output_buffer_size);
2369 vmaUnmapMemory(vmaAllocator, output_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002370 }
Tony-LunarG81efe392019-03-07 15:43:27 -07002371
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06002372 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002373 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
2374 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
2375 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002376 uint32_t desc_count = 1;
2377 auto const &state = cb_node->lastBound[bind_point];
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002378 uint32_t number_of_sets = (uint32_t)state.per_set.size();
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002379
Tony-LunarG81efe392019-03-07 15:43:27 -07002380 // Figure out how much memory we need for the input block based on how many sets and bindings there are
2381 // and how big each of the bindings is
Mark Lobodzinskif45e45f2019-04-19 14:15:39 -06002382 if (number_of_sets > 0 && device_extensions.vk_ext_descriptor_indexing) {
Tony-LunarG81efe392019-03-07 15:43:27 -07002383 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
2384 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002385 for (auto s : state.per_set) {
2386 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06002387 if (desc && (desc->GetBindingCount() > 0)) {
2388 auto bindings = desc->GetLayout()->GetSortedBindingSet();
Tony-LunarGa77cade2019-03-06 10:49:22 -07002389 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
2390 for (auto binding : bindings) {
Tony-LunarG7564b382019-08-21 10:11:35 -06002391 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2392 // blocks
2393 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2394 descriptor_count++;
2395 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
2396 VK_NULL_HANDLE, "UNASSIGNED-GPU-Assisted Validation Warning",
2397 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
2398 "validation");
2399 } else if (binding == desc->GetLayout()->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002400 descriptor_count += desc->GetVariableDescriptorCount();
2401 } else {
2402 descriptor_count += desc->GetDescriptorCountFromBinding(binding);
2403 }
2404 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002405 }
2406 }
2407
Tony-LunarGa77cade2019-03-06 10:49:22 -07002408 // Note that the size of the input buffer is dependent on the maximum binding number, which
2409 // can be very large. This is because for (set = s, binding = b, index = i), the validation
2410 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
2411 // see if descriptors have been written. In gpu_validation.md, we note this and advise
2412 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
2413 uint32_t words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002414 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2415 bufferInfo.size = words_needed * 4;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002416 result =
2417 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &di_input_block.buffer, &di_input_block.allocation, nullptr);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002418 if (result != VK_SUCCESS) {
2419 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
2420 "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002421 aborted = true;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002422 return;
2423 }
2424
Tony-LunarGa77cade2019-03-06 10:49:22 -07002425 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
2426 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
2427 // outline of the input buffer format
Tony-LunarG99b880b2019-09-26 11:19:52 -06002428 result = vmaMapMemory(vmaAllocator, di_input_block.allocation, (void **)&pData);
Tony-LunarG76cdcac2019-05-22 16:13:12 -06002429 memset(pData, 0, static_cast<size_t>(bufferInfo.size));
Tony-LunarGa77cade2019-03-06 10:49:22 -07002430 // Pointer to a sets array that points into the sizes array
2431 uint32_t *sets_to_sizes = pData + 1;
2432 // Pointer to the sizes array that contains the array size of the descriptor at each binding
2433 uint32_t *sizes = sets_to_sizes + number_of_sets;
2434 // Pointer to another sets array that points into the bindings array that points into the written array
2435 uint32_t *sets_to_bindings = sizes + binding_count;
2436 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
2437 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
2438 // Index of the next entry in the written array to be updated
2439 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002440 uint32_t bindCounter = number_of_sets + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07002441 // Index of the start of the sets_to_bindings array
2442 pData[0] = number_of_sets + binding_count + 1;
2443
Jeff Bolzb1fc0732019-08-11 20:16:49 -05002444 for (auto s : state.per_set) {
2445 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06002446 if (desc && (desc->GetBindingCount() > 0)) {
2447 auto layout = desc->GetLayout();
2448 auto bindings = layout->GetSortedBindingSet();
Tony-LunarG81efe392019-03-07 15:43:27 -07002449 // For each set, fill in index of its bindings sizes in the sizes array
Tony-LunarGa77cade2019-03-06 10:49:22 -07002450 *sets_to_sizes++ = bindCounter;
Tony-LunarG81efe392019-03-07 15:43:27 -07002451 // For each set, fill in the index of its bindings in the bindings_to_written array
Tony-LunarGa77cade2019-03-06 10:49:22 -07002452 *sets_to_bindings++ = bindCounter + number_of_sets + binding_count;
Tony-LunarG81efe392019-03-07 15:43:27 -07002453 for (auto binding : bindings) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002454 // For each binding, fill in its size in the sizes array
Tony-LunarG7564b382019-08-21 10:11:35 -06002455 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2456 // blocks
2457 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2458 sizes[binding] = 1;
2459 } else if (binding == layout->GetMaxBinding() && desc->IsVariableDescriptorCount(binding)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07002460 sizes[binding] = desc->GetVariableDescriptorCount();
2461 } else {
2462 sizes[binding] = desc->GetDescriptorCountFromBinding(binding);
2463 }
2464 // Fill in the starting index for this binding in the written array in the bindings_to_written array
2465 bindings_to_written[binding] = written_index;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002466
Tony-LunarG7564b382019-08-21 10:11:35 -06002467 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
2468 // blocks
2469 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == desc->GetLayout()->GetTypeFromBinding(binding)) {
2470 pData[written_index++] = 1;
2471 continue;
2472 }
2473
Tony-LunarGa77cade2019-03-06 10:49:22 -07002474 auto index_range = desc->GetGlobalIndexRangeFromBinding(binding, true);
2475 // For each array element in the binding, update the written array with whether it has been written
2476 for (uint32_t i = index_range.start; i < index_range.end; ++i) {
2477 auto *descriptor = desc->GetDescriptorFromGlobalIndex(i);
Tony-LunarG81efe392019-03-07 15:43:27 -07002478 if (descriptor->updated) {
2479 pData[written_index] = 1;
2480 } else if (desc->IsUpdateAfterBind(binding)) {
2481 // 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 -06002482 di_input_block.update_at_submit[written_index] = descriptor;
Tony-LunarG81efe392019-03-07 15:43:27 -07002483 }
Tony-LunarGa77cade2019-03-06 10:49:22 -07002484 written_index++;
2485 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002486 }
Tony-LunarG81efe392019-03-07 15:43:27 -07002487 auto last = desc->GetLayout()->GetMaxBinding();
2488 bindings_to_written += last + 1;
2489 bindCounter += last + 1;
2490 sizes += last + 1;
Tony-LunarGa77cade2019-03-06 10:49:22 -07002491 } else {
2492 *sets_to_sizes++ = 0;
2493 *sets_to_bindings++ = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002494 }
2495 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06002496 vmaUnmapMemory(vmaAllocator, di_input_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002497
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002498 di_input_desc_buffer_info.range = (words_needed * 4);
2499 di_input_desc_buffer_info.buffer = di_input_block.buffer;
2500 di_input_desc_buffer_info.offset = 0;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002501
2502 desc_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2503 desc_writes[1].dstBinding = 1;
2504 desc_writes[1].descriptorCount = 1;
2505 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002506 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002507 desc_writes[1].dstSet = desc_sets[0];
2508
2509 desc_count = 2;
Tony-LunarG0e564722019-03-19 16:09:14 -06002510 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002511
Tony-LunarG99b880b2019-09-26 11:19:52 -06002512 if (number_of_sets > 0 && device_extensions.vk_ext_buffer_device_address && buffer_map.size() && shaderInt64) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002513 // Example BDA input buffer assuming 2 buffers using BDA:
2514 // Word 0 | Index of start of buffer sizes (in this case 5)
2515 // Word 1 | 0x0000000000000000
2516 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
2517 // Word 3 | Device Address of second buffer
2518 // Word 4 | 0xffffffffffffffff
2519 // Word 5 | 0 (size of pretend buffer at word 1)
2520 // Word 6 | Size in bytes of first buffer
2521 // Word 7 | Size in bytes of second buffer
2522 // Word 8 | 0 (size of pretend buffer in word 4)
2523
Tony-LunarG99b880b2019-09-26 11:19:52 -06002524 uint32_t num_buffers = static_cast<uint32_t>(buffer_map.size());
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002525 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
2526 allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
2527 bufferInfo.size = words_needed * 8; // 64 bit words
Tony-LunarG99b880b2019-09-26 11:19:52 -06002528 result =
2529 vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &bda_input_block.buffer, &bda_input_block.allocation, nullptr);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002530 if (result != VK_SUCCESS) {
2531 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device),
2532 "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002533 aborted = true;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002534 return;
2535 }
2536 uint64_t *bda_data;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002537 result = vmaMapMemory(vmaAllocator, bda_input_block.allocation, (void **)&bda_data);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002538 uint32_t address_index = 1;
2539 uint32_t size_index = 3 + num_buffers;
2540 memset(bda_data, 0, static_cast<size_t>(bufferInfo.size));
2541 bda_data[0] = size_index; // Start of buffer sizes
2542 bda_data[address_index++] = 0; // NULL address
2543 bda_data[size_index++] = 0;
2544
Tony-LunarG99b880b2019-09-26 11:19:52 -06002545 for (auto const &value : buffer_map) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002546 bda_data[address_index++] = value.first;
2547 bda_data[size_index++] = value.second;
2548 }
2549 bda_data[address_index] = UINTPTR_MAX;
2550 bda_data[size_index] = 0;
Tony-LunarG99b880b2019-09-26 11:19:52 -06002551 vmaUnmapMemory(vmaAllocator, bda_input_block.allocation);
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002552
2553 bda_input_desc_buffer_info.range = (words_needed * 8);
2554 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
2555 bda_input_desc_buffer_info.offset = 0;
2556
2557 desc_writes[desc_count].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2558 desc_writes[desc_count].dstBinding = 2;
2559 desc_writes[desc_count].descriptorCount = 1;
2560 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2561 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
2562 desc_writes[desc_count].dstSet = desc_sets[0];
2563 desc_count++;
2564 }
2565
Tony-LunarGb2501d22019-01-28 09:59:13 -07002566 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002567 output_desc_buffer_info.buffer = output_block.buffer;
2568 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002569
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002570 desc_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2571 desc_writes[0].descriptorCount = 1;
2572 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2573 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
2574 desc_writes[0].dstSet = desc_sets[0];
2575 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002576
andreyg25ce2622019-04-05 23:07:59 +03002577 auto iter = cb_node->lastBound.find(bind_point); // find() allows read-only access to cb_state
Tony-LunarGb2501d22019-01-28 09:59:13 -07002578 if (iter != cb_node->lastBound.end()) {
2579 auto pipeline_state = iter->second.pipeline_state;
Jeff Bolze7fc67b2019-10-04 12:29:31 -05002580 if (pipeline_state && (pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index)) {
2581 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout, desc_set_bind_index, 1,
Tony-LunarG99b880b2019-09-26 11:19:52 -06002582 desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002583 }
Tony-LunarG0e564722019-03-19 16:09:14 -06002584 // Record buffer and memory info in CB state tracking
Tony-LunarG99b880b2019-09-26 11:19:52 -06002585 GetGpuAssistedBufferInfo(cmd_buffer)
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002586 .emplace_back(output_block, di_input_block, bda_input_block, desc_sets[0], desc_pool, bind_point);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002587 } else {
Mark Lobodzinski2a3ee4a2019-03-13 13:11:39 -06002588 ReportSetupProblem(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, HandleToUint64(device), "Unable to find pipeline state");
Tony-LunarG99b880b2019-09-26 11:19:52 -06002589 vmaDestroyBuffer(vmaAllocator, di_input_block.buffer, di_input_block.allocation);
2590 vmaDestroyBuffer(vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
2591 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
2592 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002593 return;
2594 }
2595}