blob: 0ae6a8791cc70fc05162b3fed0c076768045434e [file] [log] [blame]
Jeremy Gebben4d51c552022-01-06 21:27:15 -07001/* Copyright (c) 2018-2022 The Khronos Group Inc.
2 * Copyright (c) 2018-2022 Valve Corporation
3 * Copyright (c) 2018-2022 LunarG, Inc.
Karl Schultz7b024b42018-08-30 16:18:18 -06004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060017 * Author: Karl Schultz <karl@lunarg.com>
18 * Author: Tony Barbour <tony@lunarg.com>
Karl Schultz7b024b42018-08-30 16:18:18 -060019 */
20
Tony-LunarGc28e28a2020-08-14 10:37:48 -060021#include <climits>
Tony-LunarGa3ec16c2021-04-06 12:19:57 -060022#include <cmath>
Mark Lobodzinskib56bbb92019-02-18 11:49:59 -070023#include "gpu_validation.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060024#include "spirv-tools/optimizer.hpp"
25#include "spirv-tools/instrument.hpp"
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060026#include "layer_chassis_dispatch.h"
Tony-LunarG7de10e82020-11-24 11:31:55 -070027#include "gpu_vuids.h"
Jeremy Gebben159b3cc2021-06-03 09:09:03 -060028#include "buffer_state.h"
29#include "cmd_buffer_state.h"
30#include "render_pass_state.h"
sjfrickebecf0722022-08-05 16:15:46 +090031// Generated shaders
32#include "gpu_shaders/gpu_shaders_constants.h"
33#include "gpu_pre_draw_vert.h"
sjfrickeca9a4802022-08-10 14:27:51 +090034#include "gpu_pre_dispatch_comp.h"
sjfrickebecf0722022-08-05 16:15:46 +090035#include "gpu_as_inspection_comp.h"
Karl Schultz7b024b42018-08-30 16:18:18 -060036
Jason Macnak83cfd582019-07-31 10:14:24 -070037// Keep in sync with the GLSL shader below.
38struct GpuAccelerationStructureBuildValidationBuffer {
39 uint32_t instances_to_validate;
40 uint32_t replacement_handle_bits_0;
41 uint32_t replacement_handle_bits_1;
42 uint32_t invalid_handle_found;
43 uint32_t invalid_handle_bits_0;
44 uint32_t invalid_handle_bits_1;
45 uint32_t valid_handles_count;
46};
47
Tony-LunarG5c38b182020-06-10 16:15:32 -060048bool GpuAssisted::CheckForDescriptorIndexing(DeviceFeatures enabled_features) const {
49 bool result =
50 (IsExtEnabled(device_extensions.vk_ext_descriptor_indexing) &&
51 (enabled_features.core12.descriptorIndexing || enabled_features.core12.shaderInputAttachmentArrayDynamicIndexing ||
52 enabled_features.core12.shaderUniformTexelBufferArrayDynamicIndexing ||
53 enabled_features.core12.shaderStorageTexelBufferArrayDynamicIndexing ||
54 enabled_features.core12.shaderUniformBufferArrayNonUniformIndexing ||
55 enabled_features.core12.shaderSampledImageArrayNonUniformIndexing ||
56 enabled_features.core12.shaderStorageBufferArrayNonUniformIndexing ||
57 enabled_features.core12.shaderStorageImageArrayNonUniformIndexing ||
58 enabled_features.core12.shaderInputAttachmentArrayNonUniformIndexing ||
59 enabled_features.core12.shaderUniformTexelBufferArrayNonUniformIndexing ||
60 enabled_features.core12.shaderStorageTexelBufferArrayNonUniformIndexing ||
61 enabled_features.core12.descriptorBindingUniformBufferUpdateAfterBind ||
62 enabled_features.core12.descriptorBindingSampledImageUpdateAfterBind ||
63 enabled_features.core12.descriptorBindingStorageImageUpdateAfterBind ||
64 enabled_features.core12.descriptorBindingStorageBufferUpdateAfterBind ||
65 enabled_features.core12.descriptorBindingUniformTexelBufferUpdateAfterBind ||
66 enabled_features.core12.descriptorBindingStorageTexelBufferUpdateAfterBind ||
67 enabled_features.core12.descriptorBindingUpdateUnusedWhilePending ||
68 enabled_features.core12.descriptorBindingPartiallyBound ||
69 enabled_features.core12.descriptorBindingVariableDescriptorCount || enabled_features.core12.runtimeDescriptorArray));
70 return result;
71}
72
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060073void GpuAssisted::PreCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
74 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer, void *cb_state_data) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -060075 create_buffer_api_state *cb_state = reinterpret_cast<create_buffer_api_state *>(cb_state_data);
sjfrickeca9a4802022-08-10 14:27:51 +090076 if (cb_state) {
77 // Ray tracing acceleration structure instance buffers also need the storage buffer usage as
78 // acceleration structure build validation will find and replace invalid acceleration structure
79 // handles inside of a compute shader.
80 if (cb_state->modified_create_info.usage & VK_BUFFER_USAGE_RAY_TRACING_BIT_NV) {
81 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
82 }
83
84 // Indirect buffers will require validation shader to bind the indirect buffers as a storage buffer.
85 if ((validate_draw_indirect || validate_dispatch_indirect) &&
86 cb_state->modified_create_info.usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) {
87 cb_state->modified_create_info.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
88 }
Jason Macnak83cfd582019-07-31 10:14:24 -070089 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -060090
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -060091 ValidationStateTracker::PreCallRecordCreateBuffer(device, pCreateInfo, pAllocator, pBuffer, cb_state_data);
Jason Macnak83cfd582019-07-31 10:14:24 -070092}
Karl Schultz7b024b42018-08-30 16:18:18 -060093// Perform initializations that can be done at Create Device time.
Jeremy Gebben36a3b832022-03-23 10:54:18 -060094void GpuAssisted::CreateDevice(const VkDeviceCreateInfo *pCreateInfo) {
Jeremy Gebben33717862022-03-28 15:53:56 -060095 // GpuAssistedBase::CreateDevice will set up bindings
96 VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
97 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT |
98 VK_SHADER_STAGE_MESH_BIT_NV | VK_SHADER_STAGE_TASK_BIT_NV |
99 kShaderStageAllRayTracing,
100 NULL};
101 bindings_.push_back(binding);
102 for (auto i = 1; i < 3; i++) {
103 binding.binding = i;
104 bindings_.push_back(binding);
105 }
106 GpuAssistedBase::CreateDevice(pCreateInfo);
Mark Lobodzinski5dc3dcd2019-04-23 14:26:28 -0600107
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600108 if (enabled_features.core.robustBufferAccess || enabled_features.robustness2_features.robustBufferAccess2) {
109 buffer_oob_enabled = false;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700110 } else {
Tony-LunarGbcfeccf2022-04-19 09:14:35 -0600111 buffer_oob_enabled = GpuGetOption("khronos_validation.gpuav_buffer_oob", true);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700112 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600113
Tony-LunarGbcfeccf2022-04-19 09:14:35 -0600114 bool validate_descriptor_indexing = GpuGetOption("khronos_validation.gpuav_descriptor_indexing", true);
115 validate_draw_indirect = GpuGetOption("khronos_validation.validate_draw_indirect", true);
sjfrickeca9a4802022-08-10 14:27:51 +0900116 validate_dispatch_indirect = GpuGetOption("khronos_validation.validate_dispatch_indirect", true);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600117
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600118 if (phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700119 ReportSetupProblem(device, "GPU-Assisted validation requires Vulkan 1.1 or later. GPU-Assisted Validation disabled.");
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600120 aborted = true;
Karl Schultz7b024b42018-08-30 16:18:18 -0600121 return;
122 }
Tony-LunarG2ab9ede2019-05-10 14:34:31 -0600123
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600124 DispatchGetPhysicalDeviceFeatures(physical_device, &supported_features);
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600125 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700126 ReportSetupProblem(device,
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600127 "GPU-Assisted validation requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
128 "GPU-Assisted Validation disabled.");
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600129 aborted = true;
Tony-LunarG7c668ab2019-08-28 16:13:01 -0600130 return;
131 }
132
sfricke-samsung45996a42021-09-16 13:45:27 -0700133 if ((IsExtEnabled(device_extensions.vk_ext_buffer_device_address) ||
134 IsExtEnabled(device_extensions.vk_khr_buffer_device_address)) &&
Tony-LunarG04dc83c2020-07-07 13:53:02 -0600135 !supported_features.shaderInt64) {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700136 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
137 "shaderInt64 feature is not available. No buffer device address checking will be attempted");
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600138 }
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600139 shaderInt64 = supported_features.shaderInt64;
140 output_buffer_size = sizeof(uint32_t) * (spvtools::kInstMaxOutCnt + 1);
Tony-LunarGaef435b2021-10-14 14:49:06 -0600141 if (validate_descriptor_indexing) {
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600142 descriptor_indexing = CheckForDescriptorIndexing(enabled_features);
Tony-LunarGaef435b2021-10-14 14:49:06 -0600143 }
Tony-LunarG3b1c19f2022-05-02 14:11:06 -0600144 bool use_linear_output_pool = GpuGetOption("khronos_validation.vma_linear_output", true);
Tony-LunarG20d18a72022-04-19 11:01:47 -0600145 if (use_linear_output_pool) {
146 auto output_buffer_create_info = LvlInitStruct<VkBufferCreateInfo>();
147 output_buffer_create_info.size = output_buffer_size;
148 output_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
149 VmaAllocationCreateInfo alloc_create_info = {};
150 alloc_create_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
151 uint32_t mem_type_index;
152 vmaFindMemoryTypeIndexForBufferInfo(vmaAllocator, &output_buffer_create_info, &alloc_create_info, &mem_type_index);
153 VmaPoolCreateInfo pool_create_info = {};
154 pool_create_info.memoryTypeIndex = mem_type_index;
155 pool_create_info.blockSize = 0;
156 pool_create_info.maxBlockCount = 0;
157 pool_create_info.flags = VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT;
158 VkResult result = vmaCreatePool(vmaAllocator, &pool_create_info, &output_buffer_pool);
159 if (result != VK_SUCCESS) {
160 ReportSetupProblem(device, "Unable to create VMA memory pool");
161 }
162 }
163
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600164 CreateAccelerationStructureBuildValidationState();
Karl Schultz7b024b42018-08-30 16:18:18 -0600165}
166
sjfricke43b340c2022-08-04 22:18:38 +0900167void GpuAssistedPreDrawValidationState::Destroy(VkDevice device) {
sjfrickeca9a4802022-08-10 14:27:51 +0900168 if (shader_module != VK_NULL_HANDLE) {
sjfricke43b340c2022-08-04 22:18:38 +0900169 DispatchDestroyShaderModule(device, shader_module, nullptr);
sjfrickeca9a4802022-08-10 14:27:51 +0900170 shader_module = VK_NULL_HANDLE;
sjfricke43b340c2022-08-04 22:18:38 +0900171 }
sjfrickeca9a4802022-08-10 14:27:51 +0900172 if (ds_layout != VK_NULL_HANDLE) {
173 DispatchDestroyDescriptorSetLayout(device, ds_layout, nullptr);
174 ds_layout = VK_NULL_HANDLE;
175 }
176 if (pipeline_layout != VK_NULL_HANDLE) {
177 DispatchDestroyPipelineLayout(device, pipeline_layout, nullptr);
178 pipeline_layout = VK_NULL_HANDLE;
179 }
180 auto to_destroy = renderpass_to_pipeline.snapshot();
181 for (auto &entry : to_destroy) {
182 DispatchDestroyPipeline(device, entry.second, nullptr);
183 renderpass_to_pipeline.erase(entry.first);
184 }
185 initialized = false;
186}
187
188void GpuAssistedPreDispatchValidationState::Destroy(VkDevice device) {
189 if (shader_module != VK_NULL_HANDLE) {
190 DispatchDestroyShaderModule(device, shader_module, nullptr);
191 shader_module = VK_NULL_HANDLE;
192 }
193 if (ds_layout != VK_NULL_HANDLE) {
194 DispatchDestroyDescriptorSetLayout(device, ds_layout, nullptr);
195 ds_layout = VK_NULL_HANDLE;
196 }
197 if (pipeline_layout != VK_NULL_HANDLE) {
198 DispatchDestroyPipelineLayout(device, pipeline_layout, nullptr);
199 pipeline_layout = VK_NULL_HANDLE;
200 }
201 if (pipeline != VK_NULL_HANDLE) {
202 DispatchDestroyPipeline(device, pipeline, nullptr);
203 pipeline = VK_NULL_HANDLE;
204 }
205 initialized = false;
sjfricke43b340c2022-08-04 22:18:38 +0900206}
207
Karl Schultz7b024b42018-08-30 16:18:18 -0600208// Clean up device-related resources
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600209void GpuAssisted::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
sjfrickeca9a4802022-08-10 14:27:51 +0900210 acceleration_structure_validation_state.Destroy(device, vmaAllocator);
sjfricke43b340c2022-08-04 22:18:38 +0900211 pre_draw_validation_state.Destroy(device);
sjfrickeca9a4802022-08-10 14:27:51 +0900212 pre_dispatch_validation_state.Destroy(device);
Tony-LunarG20d18a72022-04-19 11:01:47 -0600213 if (output_buffer_pool) {
214 vmaDestroyPool(vmaAllocator, output_buffer_pool);
215 }
Jeremy Gebben33717862022-03-28 15:53:56 -0600216 GpuAssistedBase::PreCallRecordDestroyDevice(device, pAllocator);
Karl Schultz7b024b42018-08-30 16:18:18 -0600217}
Tony-LunarG1dce2392019-10-23 16:49:29 -0600218
Jeremy Gebben21782012022-03-15 16:23:27 -0600219void GpuAssisted::CreateAccelerationStructureBuildValidationState() {
220 if (aborted) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700221 return;
222 }
223
Jeremy Gebben21782012022-03-15 16:23:27 -0600224 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700225 if (as_validation_state.initialized) {
226 return;
227 }
228
sfricke-samsung45996a42021-09-16 13:45:27 -0700229 if (!IsExtEnabled(device_extensions.vk_nv_ray_tracing)) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700230 return;
231 }
232
233 // Outline:
234 // - Create valid bottom level acceleration structure which acts as replacement
235 // - Create and load vertex buffer
236 // - Create and load index buffer
237 // - Create, allocate memory for, and bind memory for acceleration structure
238 // - Query acceleration structure handle
239 // - Create command pool and command buffer
240 // - Record build acceleration structure command
241 // - Submit command buffer and wait for completion
242 // - Cleanup
243 // - Create compute pipeline for validating instance buffers
244 // - Create descriptor set layout
245 // - Create pipeline layout
246 // - Create pipeline
247 // - Cleanup
248
249 VkResult result = VK_SUCCESS;
250
251 VkBuffer vbo = VK_NULL_HANDLE;
252 VmaAllocation vbo_allocation = VK_NULL_HANDLE;
253 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600254 auto vbo_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700255 vbo_ci.size = sizeof(float) * 9;
256 vbo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
257
258 VmaAllocationCreateInfo vbo_ai = {};
259 vbo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
260 vbo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
261
Jeremy Gebben21782012022-03-15 16:23:27 -0600262 result = vmaCreateBuffer(vmaAllocator, &vbo_ci, &vbo_ai, &vbo, &vbo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700263 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700264 ReportSetupProblem(device, "Failed to create vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700265 }
266 }
267
268 if (result == VK_SUCCESS) {
269 uint8_t *mapped_vbo_buffer = nullptr;
Jeremy Gebben21782012022-03-15 16:23:27 -0600270 result = vmaMapMemory(vmaAllocator, vbo_allocation, reinterpret_cast<void **>(&mapped_vbo_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700271 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700272 ReportSetupProblem(device, "Failed to map vertex buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700273 } else {
274 const std::vector<float> vertices = {1.0f, 0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
275 std::memcpy(mapped_vbo_buffer, (uint8_t *)vertices.data(), sizeof(float) * vertices.size());
Jeremy Gebben21782012022-03-15 16:23:27 -0600276 vmaUnmapMemory(vmaAllocator, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700277 }
278 }
279
280 VkBuffer ibo = VK_NULL_HANDLE;
281 VmaAllocation ibo_allocation = VK_NULL_HANDLE;
282 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600283 auto ibo_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700284 ibo_ci.size = sizeof(uint32_t) * 3;
285 ibo_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
286
287 VmaAllocationCreateInfo ibo_ai = {};
288 ibo_ai.usage = VMA_MEMORY_USAGE_CPU_TO_GPU;
289 ibo_ai.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
290
Jeremy Gebben21782012022-03-15 16:23:27 -0600291 result = vmaCreateBuffer(vmaAllocator, &ibo_ci, &ibo_ai, &ibo, &ibo_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700292 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700293 ReportSetupProblem(device, "Failed to create index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700294 }
295 }
296
297 if (result == VK_SUCCESS) {
298 uint8_t *mapped_ibo_buffer = nullptr;
Jeremy Gebben21782012022-03-15 16:23:27 -0600299 result = vmaMapMemory(vmaAllocator, ibo_allocation, reinterpret_cast<void **>(&mapped_ibo_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700300 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700301 ReportSetupProblem(device, "Failed to map index buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700302 } else {
303 const std::vector<uint32_t> indicies = {0, 1, 2};
304 std::memcpy(mapped_ibo_buffer, (uint8_t *)indicies.data(), sizeof(uint32_t) * indicies.size());
Jeremy Gebben21782012022-03-15 16:23:27 -0600305 vmaUnmapMemory(vmaAllocator, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700306 }
307 }
308
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600309 auto geometry = LvlInitStruct<VkGeometryNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700310 geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV;
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600311 geometry.geometry.triangles = LvlInitStruct<VkGeometryTrianglesNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700312 geometry.geometry.triangles.vertexData = vbo;
313 geometry.geometry.triangles.vertexOffset = 0;
314 geometry.geometry.triangles.vertexCount = 3;
315 geometry.geometry.triangles.vertexStride = 12;
316 geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT;
317 geometry.geometry.triangles.indexData = ibo;
318 geometry.geometry.triangles.indexOffset = 0;
319 geometry.geometry.triangles.indexCount = 3;
320 geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32;
321 geometry.geometry.triangles.transformData = VK_NULL_HANDLE;
322 geometry.geometry.triangles.transformOffset = 0;
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600323 geometry.geometry.aabbs = LvlInitStruct<VkGeometryAABBNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700324
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600325 auto as_ci = LvlInitStruct<VkAccelerationStructureCreateInfoNV>();
326 as_ci.info = LvlInitStruct<VkAccelerationStructureInfoNV>();
Tony-LunarG80fecea2022-06-28 10:05:21 -0600327 as_ci.info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV;
Jason Macnak83cfd582019-07-31 10:14:24 -0700328 as_ci.info.instanceCount = 0;
329 as_ci.info.geometryCount = 1;
330 as_ci.info.pGeometries = &geometry;
331 if (result == VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600332 result = DispatchCreateAccelerationStructureNV(device, &as_ci, nullptr, &as_validation_state.replacement_as);
Jason Macnak83cfd582019-07-31 10:14:24 -0700333 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600334 ReportSetupProblem(device, "Failed to create acceleration structure for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700335 }
336 }
337
338 VkMemoryRequirements2 as_mem_requirements = {};
339 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600340 auto as_mem_requirements_info = LvlInitStruct<VkAccelerationStructureMemoryRequirementsInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700341 as_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
342 as_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
343
Jeremy Gebben21782012022-03-15 16:23:27 -0600344 DispatchGetAccelerationStructureMemoryRequirementsNV(device, &as_mem_requirements_info, &as_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700345 }
346
347 VmaAllocationInfo as_memory_ai = {};
348 if (result == VK_SUCCESS) {
349 VmaAllocationCreateInfo as_memory_aci = {};
350 as_memory_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
351
Jeremy Gebben21782012022-03-15 16:23:27 -0600352 result = vmaAllocateMemory(vmaAllocator, &as_mem_requirements.memoryRequirements, &as_memory_aci,
Tony-LunarG99b880b2019-09-26 11:19:52 -0600353 &as_validation_state.replacement_as_allocation, &as_memory_ai);
Jason Macnak83cfd582019-07-31 10:14:24 -0700354 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600355 ReportSetupProblem(device,
Jason Macnak83cfd582019-07-31 10:14:24 -0700356 "Failed to alloc acceleration structure memory for acceleration structure build validation.");
357 }
358 }
359
360 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600361 auto as_bind_info = LvlInitStruct<VkBindAccelerationStructureMemoryInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700362 as_bind_info.accelerationStructure = as_validation_state.replacement_as;
363 as_bind_info.memory = as_memory_ai.deviceMemory;
364 as_bind_info.memoryOffset = as_memory_ai.offset;
365
Jeremy Gebben21782012022-03-15 16:23:27 -0600366 result = DispatchBindAccelerationStructureMemoryNV(device, 1, &as_bind_info);
Jason Macnak83cfd582019-07-31 10:14:24 -0700367 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600368 ReportSetupProblem(device, "Failed to bind acceleration structure memory for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700369 }
370 }
371
372 if (result == VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600373 result = DispatchGetAccelerationStructureHandleNV(device, as_validation_state.replacement_as, sizeof(uint64_t),
374 &as_validation_state.replacement_as_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700375 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600376 ReportSetupProblem(device, "Failed to get acceleration structure handle for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700377 }
378 }
379
380 VkMemoryRequirements2 scratch_mem_requirements = {};
381 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600382 auto scratch_mem_requirements_info = LvlInitStruct<VkAccelerationStructureMemoryRequirementsInfoNV>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700383 scratch_mem_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
384 scratch_mem_requirements_info.accelerationStructure = as_validation_state.replacement_as;
385
Jeremy Gebben21782012022-03-15 16:23:27 -0600386 DispatchGetAccelerationStructureMemoryRequirementsNV(device, &scratch_mem_requirements_info, &scratch_mem_requirements);
Jason Macnak83cfd582019-07-31 10:14:24 -0700387 }
388
389 VkBuffer scratch = VK_NULL_HANDLE;
Tony-LunarG18900282020-05-20 12:34:33 -0600390 VmaAllocation scratch_allocation = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700391 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600392 auto scratch_ci = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700393 scratch_ci.size = scratch_mem_requirements.memoryRequirements.size;
394 scratch_ci.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
Jason Macnak83cfd582019-07-31 10:14:24 -0700395 VmaAllocationCreateInfo scratch_aci = {};
396 scratch_aci.usage = VMA_MEMORY_USAGE_GPU_ONLY;
397
Jeremy Gebben21782012022-03-15 16:23:27 -0600398 result = vmaCreateBuffer(vmaAllocator, &scratch_ci, &scratch_aci, &scratch, &scratch_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700399 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600400 ReportSetupProblem(device, "Failed to create scratch buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700401 }
402 }
403
404 VkCommandPool command_pool = VK_NULL_HANDLE;
405 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600406 auto command_pool_ci = LvlInitStruct<VkCommandPoolCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700407 command_pool_ci.queueFamilyIndex = 0;
408
Jeremy Gebben21782012022-03-15 16:23:27 -0600409 result = DispatchCreateCommandPool(device, &command_pool_ci, nullptr, &command_pool);
Jason Macnak83cfd582019-07-31 10:14:24 -0700410 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600411 ReportSetupProblem(device, "Failed to create command pool for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700412 }
413 }
414
415 VkCommandBuffer command_buffer = VK_NULL_HANDLE;
416
417 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600418 auto command_buffer_ai = LvlInitStruct<VkCommandBufferAllocateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700419 command_buffer_ai.commandPool = command_pool;
420 command_buffer_ai.commandBufferCount = 1;
421 command_buffer_ai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
422
Jeremy Gebben21782012022-03-15 16:23:27 -0600423 result = DispatchAllocateCommandBuffers(device, &command_buffer_ai, &command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700424 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600425 ReportSetupProblem(device, "Failed to create command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700426 }
427
428 // Hook up command buffer dispatch
Jeremy Gebben21782012022-03-15 16:23:27 -0600429 vkSetDeviceLoaderData(device, command_buffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700430 }
431
432 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600433 auto command_buffer_bi = LvlInitStruct<VkCommandBufferBeginInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700434
435 result = DispatchBeginCommandBuffer(command_buffer, &command_buffer_bi);
436 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600437 ReportSetupProblem(device, "Failed to begin command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700438 }
439 }
440
441 if (result == VK_SUCCESS) {
442 DispatchCmdBuildAccelerationStructureNV(command_buffer, &as_ci.info, VK_NULL_HANDLE, 0, VK_FALSE,
443 as_validation_state.replacement_as, VK_NULL_HANDLE, scratch, 0);
444 DispatchEndCommandBuffer(command_buffer);
445 }
446
447 VkQueue queue = VK_NULL_HANDLE;
448 if (result == VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600449 DispatchGetDeviceQueue(device, 0, 0, &queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700450
451 // Hook up queue dispatch
Jeremy Gebben21782012022-03-15 16:23:27 -0600452 vkSetDeviceLoaderData(device, queue);
Jason Macnak83cfd582019-07-31 10:14:24 -0700453
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600454 auto submit_info = LvlInitStruct<VkSubmitInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700455 submit_info.commandBufferCount = 1;
456 submit_info.pCommandBuffers = &command_buffer;
457 result = DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
458 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600459 ReportSetupProblem(device, "Failed to submit command buffer for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700460 }
461 }
462
463 if (result == VK_SUCCESS) {
464 result = DispatchQueueWaitIdle(queue);
465 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600466 ReportSetupProblem(device, "Failed to wait for queue idle for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700467 }
468 }
469
470 if (vbo != VK_NULL_HANDLE) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600471 vmaDestroyBuffer(vmaAllocator, vbo, vbo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700472 }
473 if (ibo != VK_NULL_HANDLE) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600474 vmaDestroyBuffer(vmaAllocator, ibo, ibo_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700475 }
476 if (scratch != VK_NULL_HANDLE) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600477 vmaDestroyBuffer(vmaAllocator, scratch, scratch_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700478 }
479 if (command_pool != VK_NULL_HANDLE) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600480 DispatchDestroyCommandPool(device, command_pool, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700481 }
482
Jeremy Gebben21782012022-03-15 16:23:27 -0600483 if (debug_desc_layout == VK_NULL_HANDLE) {
484 ReportSetupProblem(device, "Failed to find descriptor set layout for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700485 result = VK_INCOMPLETE;
486 }
487
488 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600489 auto pipeline_layout_ci = LvlInitStruct<VkPipelineLayoutCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700490 pipeline_layout_ci.setLayoutCount = 1;
Jeremy Gebben21782012022-03-15 16:23:27 -0600491 pipeline_layout_ci.pSetLayouts = &debug_desc_layout;
492 result = DispatchCreatePipelineLayout(device, &pipeline_layout_ci, 0, &as_validation_state.pipeline_layout);
Jason Macnak83cfd582019-07-31 10:14:24 -0700493 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600494 ReportSetupProblem(device, "Failed to create pipeline layout for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700495 }
496 }
497
498 VkShaderModule shader_module = VK_NULL_HANDLE;
499 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600500 auto shader_module_ci = LvlInitStruct<VkShaderModuleCreateInfo>();
sjfrickebecf0722022-08-05 16:15:46 +0900501 shader_module_ci.codeSize = sizeof(gpu_as_inspection_comp);
502 shader_module_ci.pCode = gpu_as_inspection_comp;
Jason Macnak83cfd582019-07-31 10:14:24 -0700503
Jeremy Gebben21782012022-03-15 16:23:27 -0600504 result = DispatchCreateShaderModule(device, &shader_module_ci, nullptr, &shader_module);
Jason Macnak83cfd582019-07-31 10:14:24 -0700505 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600506 ReportSetupProblem(device, "Failed to create compute shader module for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700507 }
508 }
509
510 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600511 auto pipeline_stage_ci = LvlInitStruct<VkPipelineShaderStageCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700512 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
513 pipeline_stage_ci.module = shader_module;
514 pipeline_stage_ci.pName = "main";
515
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600516 auto pipeline_ci = LvlInitStruct<VkComputePipelineCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700517 pipeline_ci.stage = pipeline_stage_ci;
518 pipeline_ci.layout = as_validation_state.pipeline_layout;
519
Jeremy Gebben21782012022-03-15 16:23:27 -0600520 result = DispatchCreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr, &as_validation_state.pipeline);
Jason Macnak83cfd582019-07-31 10:14:24 -0700521 if (result != VK_SUCCESS) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600522 ReportSetupProblem(device, "Failed to create compute pipeline for acceleration structure build validation.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700523 }
524 }
525
526 if (shader_module != VK_NULL_HANDLE) {
Jeremy Gebben21782012022-03-15 16:23:27 -0600527 DispatchDestroyShaderModule(device, shader_module, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700528 }
529
530 if (result == VK_SUCCESS) {
531 as_validation_state.initialized = true;
Jeremy Gebben21782012022-03-15 16:23:27 -0600532 LogInfo(device, "UNASSIGNED-GPU-Assisted Validation.", "Acceleration Structure Building GPU Validation Enabled.");
Jason Macnak83cfd582019-07-31 10:14:24 -0700533 } else {
Jeremy Gebben21782012022-03-15 16:23:27 -0600534 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700535 }
536}
537
sjfrickeca9a4802022-08-10 14:27:51 +0900538void GpuAssistedAccelerationStructureBuildValidationState::Destroy(VkDevice device, VmaAllocator &vmaAllocator) {
539 if (pipeline != VK_NULL_HANDLE) {
540 DispatchDestroyPipeline(device, pipeline, nullptr);
541 pipeline = VK_NULL_HANDLE;
Jason Macnak83cfd582019-07-31 10:14:24 -0700542 }
sjfrickeca9a4802022-08-10 14:27:51 +0900543 if (pipeline_layout != VK_NULL_HANDLE) {
544 DispatchDestroyPipelineLayout(device, pipeline_layout, nullptr);
545 pipeline_layout = VK_NULL_HANDLE;
Jason Macnak83cfd582019-07-31 10:14:24 -0700546 }
sjfrickeca9a4802022-08-10 14:27:51 +0900547 if (replacement_as != VK_NULL_HANDLE) {
548 DispatchDestroyAccelerationStructureNV(device, replacement_as, nullptr);
549 replacement_as = VK_NULL_HANDLE;
Jason Macnak83cfd582019-07-31 10:14:24 -0700550 }
sjfrickeca9a4802022-08-10 14:27:51 +0900551 if (replacement_as_allocation != VK_NULL_HANDLE) {
552 vmaFreeMemory(vmaAllocator, replacement_as_allocation);
553 replacement_as_allocation = VK_NULL_HANDLE;
Jason Macnak83cfd582019-07-31 10:14:24 -0700554 }
sjfrickeca9a4802022-08-10 14:27:51 +0900555 initialized = false;
Jason Macnak83cfd582019-07-31 10:14:24 -0700556}
557
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600558struct GPUAV_RESTORABLE_PIPELINE_STATE {
Jason Macnak83cfd582019-07-31 10:14:24 -0700559 VkPipelineBindPoint pipeline_bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM;
560 VkPipeline pipeline = VK_NULL_HANDLE;
561 VkPipelineLayout pipeline_layout = VK_NULL_HANDLE;
Tony-LunarG25c1a732022-09-02 13:13:14 -0600562 std::vector<std::pair<VkDescriptorSet, uint32_t>> descriptor_sets;
Jason Macnak83cfd582019-07-31 10:14:24 -0700563 std::vector<std::vector<uint32_t>> dynamic_offsets;
564 uint32_t push_descriptor_set_index = 0;
565 std::vector<safe_VkWriteDescriptorSet> push_descriptor_set_writes;
566 std::vector<uint8_t> push_constants_data;
567 PushConstantRangesId push_constants_ranges;
568
569 void Create(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
570 pipeline_bind_point = bind_point;
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600571 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
Jason Macnak83cfd582019-07-31 10:14:24 -0700572
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600573 LAST_BOUND_STATE &last_bound = cb_state->lastBound[lv_bind_point];
Jason Macnak83cfd582019-07-31 10:14:24 -0700574 if (last_bound.pipeline_state) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600575 pipeline = last_bound.pipeline_state->pipeline();
Jason Macnak83cfd582019-07-31 10:14:24 -0700576 pipeline_layout = last_bound.pipeline_layout;
577 descriptor_sets.reserve(last_bound.per_set.size());
578 for (std::size_t i = 0; i < last_bound.per_set.size(); i++) {
Jeremy Gebben4d51c552022-01-06 21:27:15 -0700579 const auto &bound_descriptor_set = last_bound.per_set[i].bound_descriptor_set;
ziga-lunarge0b552b2021-09-05 21:39:57 +0200580 if (bound_descriptor_set) {
Tony-LunarG25c1a732022-09-02 13:13:14 -0600581 descriptor_sets.push_back(std::make_pair(bound_descriptor_set->GetSet(), static_cast<uint32_t>(i)));
ziga-lunarge0b552b2021-09-05 21:39:57 +0200582 if (bound_descriptor_set->IsPushDescriptor()) {
583 push_descriptor_set_index = static_cast<uint32_t>(i);
584 }
585 dynamic_offsets.push_back(last_bound.per_set[i].dynamicOffsets);
Jason Macnak83cfd582019-07-31 10:14:24 -0700586 }
Jason Macnak83cfd582019-07-31 10:14:24 -0700587 }
588
589 if (last_bound.push_descriptor_set) {
590 push_descriptor_set_writes = last_bound.push_descriptor_set->GetWrites();
591 }
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700592 const auto &pipeline_layout = last_bound.pipeline_state->PipelineLayoutState();
593 if (pipeline_layout->push_constant_ranges == cb_state->push_constant_data_ranges) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700594 push_constants_data = cb_state->push_constant_data;
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700595 push_constants_ranges = pipeline_layout->push_constant_ranges;
Jason Macnak83cfd582019-07-31 10:14:24 -0700596 }
597 }
598 }
599
600 void Restore(VkCommandBuffer command_buffer) const {
601 if (pipeline != VK_NULL_HANDLE) {
602 DispatchCmdBindPipeline(command_buffer, pipeline_bind_point, pipeline);
603 if (!descriptor_sets.empty()) {
604 for (std::size_t i = 0; i < descriptor_sets.size(); i++) {
Tony-LunarG25c1a732022-09-02 13:13:14 -0600605 VkDescriptorSet descriptor_set = descriptor_sets[i].first;
Jason Macnak83cfd582019-07-31 10:14:24 -0700606 if (descriptor_set != VK_NULL_HANDLE) {
607 DispatchCmdBindDescriptorSets(command_buffer, pipeline_bind_point, pipeline_layout,
Tony-LunarG25c1a732022-09-02 13:13:14 -0600608 descriptor_sets[i].second, 1, &descriptor_set,
Jason Macnak83cfd582019-07-31 10:14:24 -0700609 static_cast<uint32_t>(dynamic_offsets[i].size()), dynamic_offsets[i].data());
610 }
611 }
612 }
613 if (!push_descriptor_set_writes.empty()) {
614 DispatchCmdPushDescriptorSetKHR(command_buffer, pipeline_bind_point, pipeline_layout, push_descriptor_set_index,
615 static_cast<uint32_t>(push_descriptor_set_writes.size()),
616 reinterpret_cast<const VkWriteDescriptorSet *>(push_descriptor_set_writes.data()));
617 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600618 if (!push_constants_data.empty()) {
619 for (const auto &push_constant_range : *push_constants_ranges) {
620 if (push_constant_range.size == 0) continue;
621 DispatchCmdPushConstants(command_buffer, pipeline_layout, push_constant_range.stageFlags,
622 push_constant_range.offset, push_constant_range.size, push_constants_data.data());
623 }
Jason Macnak83cfd582019-07-31 10:14:24 -0700624 }
625 }
626 }
627};
628
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600629void GpuAssisted::PreCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
630 const VkAccelerationStructureInfoNV *pInfo, VkBuffer instanceData,
631 VkDeviceSize instanceOffset, VkBool32 update,
632 VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
633 VkBuffer scratch, VkDeviceSize scratchOffset) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -0600634 ValidationStateTracker::PreCallRecordCmdBuildAccelerationStructureNV(commandBuffer, pInfo, instanceData, instanceOffset, update,
635 dst, src, scratch, scratchOffset);
Jason Macnak83cfd582019-07-31 10:14:24 -0700636 if (pInfo == nullptr || pInfo->type != VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_NV) {
637 return;
638 }
639
Tony-LunarG99b880b2019-09-26 11:19:52 -0600640 auto &as_validation_state = acceleration_structure_validation_state;
Jason Macnak83cfd582019-07-31 10:14:24 -0700641 if (!as_validation_state.initialized) {
642 return;
643 }
644
645 // Empty acceleration structure is valid according to the spec.
646 if (pInfo->instanceCount == 0 || instanceData == VK_NULL_HANDLE) {
647 return;
648 }
649
Jeremy Gebben04697b02022-03-23 16:18:12 -0600650 auto cb_state = GetWrite<gpuav_state::CommandBuffer>(commandBuffer);
Jason Macnak83cfd582019-07-31 10:14:24 -0700651 assert(cb_state != nullptr);
652
653 std::vector<uint64_t> current_valid_handles;
Jeremy Gebbenb7bfbd02021-11-01 15:17:50 -0600654 ForEach<ACCELERATION_STRUCTURE_STATE>([&current_valid_handles](const ACCELERATION_STRUCTURE_STATE &as_state) {
Jeff Bolz95176d02020-04-01 00:36:16 -0500655 if (as_state.built && as_state.create_infoNV.info.type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700656 current_valid_handles.push_back(as_state.opaque_handle);
657 }
Jeremy Gebbenb7bfbd02021-11-01 15:17:50 -0600658 });
Jason Macnak83cfd582019-07-31 10:14:24 -0700659
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600660 GpuAssistedAccelerationStructureBuildValidationBufferInfo as_validation_buffer_info = {};
Jason Macnak83cfd582019-07-31 10:14:24 -0700661 as_validation_buffer_info.acceleration_structure = dst;
662
663 const VkDeviceSize validation_buffer_size =
664 // One uint for number of instances to validate
665 4 +
666 // Two uint for the replacement acceleration structure handle
667 8 +
668 // One uint for number of invalid handles found
669 4 +
670 // Two uint for the first invalid handle found
671 8 +
672 // One uint for the number of current valid handles
673 4 +
674 // Two uint for each current valid handle
675 (8 * current_valid_handles.size());
676
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600677 auto validation_buffer_create_info = LvlInitStruct<VkBufferCreateInfo>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700678 validation_buffer_create_info.size = validation_buffer_size;
679 validation_buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
680
681 VmaAllocationCreateInfo validation_buffer_alloc_info = {};
682 validation_buffer_alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
683
Tony-LunarG99b880b2019-09-26 11:19:52 -0600684 VkResult result = vmaCreateBuffer(vmaAllocator, &validation_buffer_create_info, &validation_buffer_alloc_info,
sjfricke43b340c2022-08-04 22:18:38 +0900685 &as_validation_buffer_info.buffer, &as_validation_buffer_info.buffer_allocation, nullptr);
Jason Macnak83cfd582019-07-31 10:14:24 -0700686 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700687 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600688 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700689 return;
690 }
691
692 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
sjfricke43b340c2022-08-04 22:18:38 +0900693 result = vmaMapMemory(vmaAllocator, as_validation_buffer_info.buffer_allocation,
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700694 reinterpret_cast<void **>(&mapped_validation_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700695 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700696 ReportSetupProblem(device, "Unable to allocate device memory for acceleration structure build val buffer.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600697 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700698 return;
699 }
700
701 mapped_validation_buffer->instances_to_validate = pInfo->instanceCount;
702 mapped_validation_buffer->replacement_handle_bits_0 =
703 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[0];
704 mapped_validation_buffer->replacement_handle_bits_1 =
705 reinterpret_cast<const uint32_t *>(&as_validation_state.replacement_as_handle)[1];
706 mapped_validation_buffer->invalid_handle_found = 0;
707 mapped_validation_buffer->invalid_handle_bits_0 = 0;
708 mapped_validation_buffer->invalid_handle_bits_1 = 0;
709 mapped_validation_buffer->valid_handles_count = static_cast<uint32_t>(current_valid_handles.size());
710
711 uint32_t *mapped_valid_handles = reinterpret_cast<uint32_t *>(&mapped_validation_buffer[1]);
712 for (std::size_t i = 0; i < current_valid_handles.size(); i++) {
713 const uint64_t current_valid_handle = current_valid_handles[i];
714
715 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[0];
716 ++mapped_valid_handles;
717 *mapped_valid_handles = reinterpret_cast<const uint32_t *>(&current_valid_handle)[1];
718 ++mapped_valid_handles;
719 }
720
sjfricke43b340c2022-08-04 22:18:38 +0900721 vmaUnmapMemory(vmaAllocator, as_validation_buffer_info.buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700722
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700723 static constexpr const VkDeviceSize k_instance_size = 64;
724 const VkDeviceSize instance_buffer_size = k_instance_size * pInfo->instanceCount;
Jason Macnak83cfd582019-07-31 10:14:24 -0700725
Tony-LunarG1dce2392019-10-23 16:49:29 -0600726 result = desc_set_manager->GetDescriptorSet(&as_validation_buffer_info.descriptor_pool, debug_desc_layout,
727 &as_validation_buffer_info.descriptor_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700728 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700729 ReportSetupProblem(device, "Unable to get descriptor set for acceleration structure build.");
Tony-LunarG99b880b2019-09-26 11:19:52 -0600730 aborted = true;
Jason Macnak83cfd582019-07-31 10:14:24 -0700731 return;
732 }
733
734 VkDescriptorBufferInfo descriptor_buffer_infos[2] = {};
735 descriptor_buffer_infos[0].buffer = instanceData;
736 descriptor_buffer_infos[0].offset = instanceOffset;
737 descriptor_buffer_infos[0].range = instance_buffer_size;
sjfricke43b340c2022-08-04 22:18:38 +0900738 descriptor_buffer_infos[1].buffer = as_validation_buffer_info.buffer;
Jason Macnak83cfd582019-07-31 10:14:24 -0700739 descriptor_buffer_infos[1].offset = 0;
740 descriptor_buffer_infos[1].range = validation_buffer_size;
741
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600742 VkWriteDescriptorSet descriptor_set_writes[2] = {
743 LvlInitStruct<VkWriteDescriptorSet>(),
744 LvlInitStruct<VkWriteDescriptorSet>(),
745 };
Jason Macnak83cfd582019-07-31 10:14:24 -0700746 descriptor_set_writes[0].dstSet = as_validation_buffer_info.descriptor_set;
747 descriptor_set_writes[0].dstBinding = 0;
748 descriptor_set_writes[0].descriptorCount = 1;
749 descriptor_set_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
750 descriptor_set_writes[0].pBufferInfo = &descriptor_buffer_infos[0];
Jason Macnak83cfd582019-07-31 10:14:24 -0700751 descriptor_set_writes[1].dstSet = as_validation_buffer_info.descriptor_set;
752 descriptor_set_writes[1].dstBinding = 1;
753 descriptor_set_writes[1].descriptorCount = 1;
754 descriptor_set_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
755 descriptor_set_writes[1].pBufferInfo = &descriptor_buffer_infos[1];
756
757 DispatchUpdateDescriptorSets(device, 2, descriptor_set_writes, 0, nullptr);
758
759 // Issue a memory barrier to make sure anything writing to the instance buffer has finished.
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600760 auto memory_barrier = LvlInitStruct<VkMemoryBarrier>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700761 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
762 memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
763 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1,
764 &memory_barrier, 0, nullptr, 0, nullptr);
765
766 // Save a copy of the compute pipeline state that needs to be restored.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600767 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jeremy Gebben9f537102021-10-05 16:37:12 -0600768 restorable_state.Create(cb_state.get(), VK_PIPELINE_BIND_POINT_COMPUTE);
Jason Macnak83cfd582019-07-31 10:14:24 -0700769
770 // Switch to and launch the validation compute shader to find, replace, and report invalid acceleration structure handles.
771 DispatchCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline);
772 DispatchCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, as_validation_state.pipeline_layout, 0, 1,
773 &as_validation_buffer_info.descriptor_set, 0, nullptr);
774 DispatchCmdDispatch(commandBuffer, 1, 1, 1);
775
776 // Issue a buffer memory barrier to make sure that any invalid bottom level acceleration structure handles
777 // have been replaced by the validation compute shader before any builds take place.
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600778 auto instance_buffer_barrier = LvlInitStruct<VkBufferMemoryBarrier>();
Jason Macnak83cfd582019-07-31 10:14:24 -0700779 instance_buffer_barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
780 instance_buffer_barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_NV;
781 instance_buffer_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
782 instance_buffer_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
783 instance_buffer_barrier.buffer = instanceData;
784 instance_buffer_barrier.offset = instanceOffset;
785 instance_buffer_barrier.size = instance_buffer_size;
786 DispatchCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
787 VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_NV, 0, 0, nullptr, 1, &instance_buffer_barrier, 0,
788 nullptr);
789
790 // Restore the previous compute pipeline state.
791 restorable_state.Restore(commandBuffer);
792
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600793 cb_state->as_validation_buffers.emplace_back(std::move(as_validation_buffer_info));
Jason Macnak83cfd582019-07-31 10:14:24 -0700794}
795
Jeremy Gebben5ca80b32022-04-11 10:58:39 -0600796void gpuav_state::CommandBuffer::ProcessAccelerationStructure(VkQueue queue) {
sjfricke52defd42022-08-08 16:37:46 +0900797 if (!has_build_as_cmd) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700798 return;
799 }
Jeremy Gebben5ca80b32022-04-11 10:58:39 -0600800 auto *device_state = static_cast<GpuAssisted *>(dev_data);
801 for (const auto &as_validation_buffer_info : as_validation_buffers) {
Jason Macnak83cfd582019-07-31 10:14:24 -0700802 GpuAccelerationStructureBuildValidationBuffer *mapped_validation_buffer = nullptr;
803
sjfricke43b340c2022-08-04 22:18:38 +0900804 VkResult result = vmaMapMemory(device_state->vmaAllocator, as_validation_buffer_info.buffer_allocation,
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700805 reinterpret_cast<void **>(&mapped_validation_buffer));
Jason Macnak83cfd582019-07-31 10:14:24 -0700806 if (result == VK_SUCCESS) {
807 if (mapped_validation_buffer->invalid_handle_found > 0) {
808 uint64_t invalid_handle = 0;
809 reinterpret_cast<uint32_t *>(&invalid_handle)[0] = mapped_validation_buffer->invalid_handle_bits_0;
810 reinterpret_cast<uint32_t *>(&invalid_handle)[1] = mapped_validation_buffer->invalid_handle_bits_1;
811
Jeremy Gebben5ca80b32022-04-11 10:58:39 -0600812 device_state->LogError(
813 as_validation_buffer_info.acceleration_structure, "UNASSIGNED-AccelerationStructure",
814 "Attempted to build top level acceleration structure using invalid bottom level acceleration structure "
815 "handle (%" PRIu64 ")",
816 invalid_handle);
Jason Macnak83cfd582019-07-31 10:14:24 -0700817 }
sjfricke43b340c2022-08-04 22:18:38 +0900818 vmaUnmapMemory(device_state->vmaAllocator, as_validation_buffer_info.buffer_allocation);
Jason Macnak83cfd582019-07-31 10:14:24 -0700819 }
820 }
821}
822
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600823void GpuAssisted::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
824 const VkBindAccelerationStructureMemoryInfoNV *pBindInfos,
825 VkResult result) {
826 if (VK_SUCCESS != result) return;
Tony-LunarG99b880b2019-09-26 11:19:52 -0600827 ValidationStateTracker::PostCallRecordBindAccelerationStructureMemoryNV(device, bindInfoCount, pBindInfos, result);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600828 for (uint32_t i = 0; i < bindInfoCount; i++) {
829 const VkBindAccelerationStructureMemoryInfoNV &info = pBindInfos[i];
Jeremy Gebbenb20a8242021-11-05 15:14:43 -0600830 auto as_state = Get<ACCELERATION_STRUCTURE_STATE>(info.accelerationStructure);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600831 if (as_state) {
832 DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
833 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600834 }
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600835}
Mark Lobodzinskiff7d8002019-02-13 13:01:26 -0700836
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600837// Free the device memory and descriptor set(s) associated with a command buffer.
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600838void GpuAssisted::DestroyBuffer(GpuAssistedBufferInfo &buffer_info) {
839 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
840 if (buffer_info.di_input_mem_block.buffer) {
841 vmaDestroyBuffer(vmaAllocator, buffer_info.di_input_mem_block.buffer, buffer_info.di_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -0600842 }
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600843 if (buffer_info.bda_input_mem_block.buffer) {
844 vmaDestroyBuffer(vmaAllocator, buffer_info.bda_input_mem_block.buffer, buffer_info.bda_input_mem_block.allocation);
Karl Schultz7b024b42018-08-30 16:18:18 -0600845 }
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600846 if (buffer_info.desc_set != VK_NULL_HANDLE) {
847 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Jason Macnak83cfd582019-07-31 10:14:24 -0700848 }
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600849 if (buffer_info.pre_draw_resources.desc_set != VK_NULL_HANDLE) {
850 desc_set_manager->PutBackDescriptorSet(buffer_info.pre_draw_resources.desc_pool, buffer_info.pre_draw_resources.desc_set);
851 }
sjfrickeca9a4802022-08-10 14:27:51 +0900852 if (buffer_info.pre_dispatch_resources.desc_set != VK_NULL_HANDLE) {
853 desc_set_manager->PutBackDescriptorSet(buffer_info.pre_dispatch_resources.desc_pool,
854 buffer_info.pre_dispatch_resources.desc_set);
855 }
Karl Schultz7b024b42018-08-30 16:18:18 -0600856}
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600857
858void GpuAssisted::DestroyBuffer(GpuAssistedAccelerationStructureBuildValidationBufferInfo &as_validation_buffer_info) {
sjfricke43b340c2022-08-04 22:18:38 +0900859 vmaDestroyBuffer(vmaAllocator, as_validation_buffer_info.buffer, as_validation_buffer_info.buffer_allocation);
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600860
861 if (as_validation_buffer_info.descriptor_set != VK_NULL_HANDLE) {
862 desc_set_manager->PutBackDescriptorSet(as_validation_buffer_info.descriptor_pool, as_validation_buffer_info.descriptor_set);
863 }
864}
865
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600866void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
867 VkPhysicalDeviceProperties *pPhysicalDeviceProperties) {
868 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -0600869 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600870 if (pPhysicalDeviceProperties->limits.maxBoundDescriptorSets > 1) {
871 pPhysicalDeviceProperties->limits.maxBoundDescriptorSets -= 1;
872 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700873 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
874 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600875 }
876 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -0600877 ValidationStateTracker::PostCallRecordGetPhysicalDeviceProperties(physicalDevice, pPhysicalDeviceProperties);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600878}
879
880void GpuAssisted::PostCallRecordGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
881 VkPhysicalDeviceProperties2 *pPhysicalDeviceProperties2) {
882 // There is an implicit layer that can cause this call to return 0 for maxBoundDescriptorSets - Ignore such calls
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -0600883 if (enabled[gpu_validation_reserve_binding_slot] && pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 0) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600884 if (pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets > 1) {
885 pPhysicalDeviceProperties2->properties.limits.maxBoundDescriptorSets -= 1;
886 } else {
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -0700887 LogWarning(physicalDevice, "UNASSIGNED-GPU-Assisted Validation Setup Error.",
888 "Unable to reserve descriptor binding slot on a device with only one slot.");
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600889 }
890 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -0600891 ValidationStateTracker::PostCallRecordGetPhysicalDeviceProperties2(physicalDevice, pPhysicalDeviceProperties2);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600892}
893
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600894void GpuAssisted::PreCallRecordDestroyRenderPass(VkDevice device, VkRenderPass renderPass,
895 const VkAllocationCallbacks *pAllocator) {
Jeremy Gebbenbba39212022-03-29 16:39:06 -0600896 auto pipeline = pre_draw_validation_state.renderpass_to_pipeline.pop(renderPass);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600897 if (pipeline != pre_draw_validation_state.renderpass_to_pipeline.end()) {
898 DispatchDestroyPipeline(device, pipeline->second, nullptr);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600899 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -0600900 ValidationStateTracker::PreCallRecordDestroyRenderPass(device, renderPass, pAllocator);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -0600901}
902
Karl Schultz7b024b42018-08-30 16:18:18 -0600903// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
sfricke-samsung7fac88a2022-01-26 11:44:22 -0800904bool GpuAssisted::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<uint32_t> &new_pgm,
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600905 uint32_t *unique_shader_id) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600906 if (aborted) return false;
Karl Schultz7b024b42018-08-30 16:18:18 -0600907 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
908
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700909 const spvtools::MessageConsumer gpu_console_message_consumer =
Tony-LunarG79641702020-07-13 15:43:05 -0600910 [this](spv_message_level_t level, const char *, const spv_position_t &position, const char *message) -> void {
911 switch (level) {
912 case SPV_MSG_FATAL:
913 case SPV_MSG_INTERNAL_ERROR:
914 case SPV_MSG_ERROR:
915 this->LogError(this->device, "UNASSIGNED-GPU-Assisted", "Error during shader instrumentation: line %zu: %s",
916 position.index, message);
917 break;
918 default:
919 break;
920 }
921 };
922
Karl Schultz7b024b42018-08-30 16:18:18 -0600923 // Load original shader SPIR-V
924 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
925 new_pgm.clear();
926 new_pgm.reserve(num_words);
927 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
928
929 // Call the optimizer to instrument the shader.
930 // 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 -0700931 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
Karl Schultz7b024b42018-08-30 16:18:18 -0600932 using namespace spvtools;
sfricke-samsung45996a42021-09-16 13:45:27 -0700933 spv_target_env target_env = PickSpirvEnv(api_version, IsExtEnabled(device_extensions.vk_khr_spirv_1_4));
Tony-LunarGf29f77f2020-08-26 15:48:00 -0600934 spvtools::ValidatorOptions val_options;
935 AdjustValidatorOptions(device_extensions, enabled_features, val_options);
936 spvtools::OptimizerOptions opt_options;
937 opt_options.set_run_validator(true);
938 opt_options.set_validator_options(val_options);
Karl Schultz7b024b42018-08-30 16:18:18 -0600939 Optimizer optimizer(target_env);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700940 optimizer.SetMessageConsumer(gpu_console_message_consumer);
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600941 optimizer.RegisterPass(CreateInstBindlessCheckPass(desc_set_bind_index, unique_shader_module_id, descriptor_indexing,
Tony-LunarGe8632e42020-11-18 17:03:12 -0700942 descriptor_indexing, buffer_oob_enabled, buffer_oob_enabled));
Tony-LunarG57400d42021-10-14 11:18:43 -0600943 // Call CreateAggressiveDCEPass with preserve_interface == true
944 optimizer.RegisterPass(CreateAggressiveDCEPass(true));
sfricke-samsung45996a42021-09-16 13:45:27 -0700945 if ((IsExtEnabled(device_extensions.vk_ext_buffer_device_address) ||
946 IsExtEnabled(device_extensions.vk_khr_buffer_device_address)) &&
947 shaderInt64 && enabled_features.core12.bufferDeviceAddress) {
Tony-LunarG99b880b2019-09-26 11:19:52 -0600948 optimizer.RegisterPass(CreateInstBuffAddrCheckPass(desc_set_bind_index, unique_shader_module_id));
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700949 }
Tony-LunarGf29f77f2020-08-26 15:48:00 -0600950 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm, opt_options);
Karl Schultz7b024b42018-08-30 16:18:18 -0600951 if (!pass) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -0700952 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Karl Schultz7b024b42018-08-30 16:18:18 -0600953 }
Tony-LunarG99b880b2019-09-26 11:19:52 -0600954 *unique_shader_id = unique_shader_module_id++;
Karl Schultz7b024b42018-08-30 16:18:18 -0600955 return pass;
956}
Mark Lobodzinski01734072019-02-13 17:39:15 -0700957// Create the instrumented shader data to provide to the driver.
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600958void GpuAssisted::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
959 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
960 void *csm_state_data) {
961 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
962 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
Karl Schultz7b024b42018-08-30 16:18:18 -0600963 if (pass) {
Tony-LunarG2ba1cb32019-09-25 15:16:11 -0600964 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
sfricke-samsung7fac88a2022-01-26 11:44:22 -0800965 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(uint32_t);
Karl Schultz7b024b42018-08-30 16:18:18 -0600966 }
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -0600967 ValidationStateTracker::PreCallRecordCreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule, csm_state_data);
Karl Schultz7b024b42018-08-30 16:18:18 -0600968}
Tony-LunarG20678ff2021-05-07 14:56:26 -0600969
Karl Schultz7b024b42018-08-30 16:18:18 -0600970// Generate the part of the message describing the violation.
Tony-LunarG1a7c9f92021-04-29 16:04:42 -0600971bool GenerateValidationMessage(const uint32_t *debug_record, std::string &msg, std::string &vuid_msg, GpuAssistedBufferInfo buf_info, GpuAssisted *gpu_assisted) {
Karl Schultz7b024b42018-08-30 16:18:18 -0600972 using namespace spvtools;
973 std::ostringstream strm;
Tony-LunarG63f82e02021-04-12 16:13:48 -0600974 bool return_code = true;
sjfricke125f74d2022-08-08 18:27:25 +0900975 static_assert(
976 spvtools::kInstErrorMax == _kInstErrorMax,
977 "If this asserts then SPIRV-Tools was updated with a new instrument.hpp and kInstErrorMax was updated. This needs to be "
978 "changed in GPU-AV so that the GLSL gpu_shaders can read the constants.");
979 static_assert(spvtools::kInstValidationOutError == _kInstValidationOutError,
980 "If this asserts then SPIRV-Tools was updated with a new instrument.hpp and kInstValidationOutError was updated. "
981 "This needs to be changed in GPU-AV so that the GLSL gpu_shaders can read the constants.");
sjfrickeca9a4802022-08-10 14:27:51 +0900982 const GpuVuid vuid = GetGpuVuid(buf_info.cmd_type);
Tony-LunarGab47cac2019-12-20 15:28:01 -0700983 switch (debug_record[kInstValidationOutError]) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600984 case kInstErrorBindlessBounds: {
Tony-LunarGab47cac2019-12-20 15:28:01 -0700985 strm << "Index of " << debug_record[kInstBindlessBoundsOutDescIndex] << " used to index descriptor array of length "
986 << debug_record[kInstBindlessBoundsOutDescBound] << ". ";
Tony-LunarGc1d657d2019-02-22 14:55:19 -0700987 vuid_msg = "UNASSIGNED-Descriptor index out of bounds";
Karl Schultz7b024b42018-08-30 16:18:18 -0600988 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600989 case kInstErrorBindlessUninit: {
Tony-LunarGc28e28a2020-08-14 10:37:48 -0600990 strm << "Descriptor index " << debug_record[kInstBindlessUninitOutDescIndex] << " is uninitialized.";
Tony-LunarGc1d657d2019-02-22 14:55:19 -0700991 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Karl Schultz7b024b42018-08-30 16:18:18 -0600992 } break;
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600993 case kInstErrorBuffAddrUnallocRef: {
Tony-LunarGab47cac2019-12-20 15:28:01 -0700994 uint64_t *ptr = (uint64_t *)&debug_record[kInstBuffAddrUnallocOutDescPtrLo];
Tony-LunarG8eb5a002019-07-25 16:49:00 -0600995 strm << "Device address 0x" << std::hex << *ptr << " access out of bounds. ";
996 vuid_msg = "UNASSIGNED-Device address out of bounds";
997 } break;
Tony-LunarG7de10e82020-11-24 11:31:55 -0700998 case kInstErrorBuffOOBUniform:
999 case kInstErrorBuffOOBStorage: {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001000 auto size = debug_record[kInstBindlessBuffOOBOutBuffSize];
1001 if (size == 0) {
1002 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex] << " is uninitialized.";
1003 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
1004 } else {
1005 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex]
1006 << " access out of bounds. Descriptor size is " << debug_record[kInstBindlessBuffOOBOutBuffSize]
Tony-LunarG7de10e82020-11-24 11:31:55 -07001007 << " and highest byte accessed was " << debug_record[kInstBindlessBuffOOBOutBuffOff];
Tony-LunarG7de10e82020-11-24 11:31:55 -07001008 if (debug_record[kInstValidationOutError] == kInstErrorBuffOOBUniform)
1009 vuid_msg = vuid.uniform_access_oob;
1010 else
1011 vuid_msg = vuid.storage_access_oob;
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001012 }
1013 } break;
Tony-LunarG7de10e82020-11-24 11:31:55 -07001014 case kInstErrorBuffOOBUniformTexel:
1015 case kInstErrorBuffOOBStorageTexel: {
1016 auto size = debug_record[kInstBindlessBuffOOBOutBuffSize];
1017 if (size == 0) {
1018 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex] << " is uninitialized.";
1019 vuid_msg = "UNASSIGNED-Descriptor uninitialized";
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001020 } else {
Tony-LunarG7de10e82020-11-24 11:31:55 -07001021 strm << "Descriptor index " << debug_record[kInstBindlessBuffOOBOutDescIndex]
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001022 << " access out of bounds. Descriptor size is " << debug_record[kInstBindlessBuffOOBOutBuffSize]
1023 << " texels and highest texel accessed was " << debug_record[kInstBindlessBuffOOBOutBuffOff];
Tony-LunarG7de10e82020-11-24 11:31:55 -07001024 if (debug_record[kInstValidationOutError] == kInstErrorBuffOOBUniformTexel)
1025 vuid_msg = vuid.uniform_access_oob;
1026 else
1027 vuid_msg = vuid.storage_access_oob;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001028 }
Tony-LunarG63f82e02021-04-12 16:13:48 -06001029 } break;
sjfricke125f74d2022-08-08 18:27:25 +09001030 case _kInstErrorPreDrawValidate: {
Tim Van Patten38bdcdd2021-05-14 16:41:00 -06001031 // Buffer size must be >= (stride * (drawCount - 1) + offset + sizeof(VkDrawIndexedIndirectCommand))
sjfrickeca9a4802022-08-10 14:27:51 +09001032 if (debug_record[_kPreValidateSubError] == pre_draw_count_exceeds_bufsize_error) {
1033 uint32_t count = debug_record[_kPreValidateSubError + 1];
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001034 uint32_t stride = buf_info.pre_draw_resources.stride;
1035 uint32_t offset = static_cast<uint32_t>(buf_info.pre_draw_resources.offset);
1036 uint32_t draw_size = (stride * (count - 1) + offset + sizeof(VkDrawIndexedIndirectCommand));
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001037 strm << "Indirect draw count of " << count << " would exceed buffer size " << buf_info.pre_draw_resources.buf_size
1038 << " of buffer " << buf_info.pre_draw_resources.buffer << " stride = " << stride << " offset = " << offset
1039 << " (stride * (drawCount - 1) + offset + sizeof(VkDrawIndexedIndirectCommand)) = " << draw_size;
Tony-LunarG64aeaf72021-04-14 11:13:35 -06001040 if (count == 1) {
1041 vuid_msg = vuid.count_exceeds_bufsize_1;
1042 } else {
1043 vuid_msg = vuid.count_exceeds_bufsize;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001044 }
sjfrickeca9a4802022-08-10 14:27:51 +09001045 } else if (debug_record[_kPreValidateSubError] == pre_draw_count_exceeds_limit_error) {
1046 uint32_t count = debug_record[_kPreValidateSubError + 1];
Tony-LunarG1a7c9f92021-04-29 16:04:42 -06001047 strm << "Indirect draw count of " << count << " would exceed maxDrawIndirectCount limit of "
1048 << gpu_assisted->phys_dev_props.limits.maxDrawIndirectCount;
1049 vuid_msg = vuid.count_exceeds_device_limit;
sjfrickeca9a4802022-08-10 14:27:51 +09001050 } else if (debug_record[_kPreValidateSubError] == pre_draw_first_instance_error) {
1051 uint32_t index = debug_record[_kPreValidateSubError + 1];
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001052 strm << "The drawIndirectFirstInstance feature is not enabled, but the firstInstance member of the "
sjfricke49314e02022-08-12 13:55:41 +09001053 << ((buf_info.cmd_type == CMD_DRAWINDIRECT) ? "VkDrawIndirectCommand" : "VkDrawIndexedIndirectCommand")
1054 << " structure at index " << index << " is not zero";
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001055 vuid_msg = vuid.first_instance_not_zero;
Tony-LunarG63f82e02021-04-12 16:13:48 -06001056 }
1057 return_code = false;
1058 } break;
sjfrickeca9a4802022-08-10 14:27:51 +09001059 case _kInstErrorPreDispatchValidate: {
1060 if (debug_record[_kPreValidateSubError] == pre_dispatch_count_exceeds_limit_x_error) {
1061 uint32_t count = debug_record[_kPreValidateSubError + 1];
1062 strm << "Indirect dispatch VkDispatchIndirectCommand::x of " << count
1063 << " would exceed maxComputeWorkGroupCount[0] limit of "
1064 << gpu_assisted->phys_dev_props.limits.maxComputeWorkGroupCount[0];
1065 vuid_msg = vuid.group_exceeds_device_limit_x;
1066 } else if (debug_record[_kPreValidateSubError] == pre_dispatch_count_exceeds_limit_y_error) {
1067 uint32_t count = debug_record[_kPreValidateSubError + 1];
1068 strm << "Indirect dispatch VkDispatchIndirectCommand:y of " << count
1069 << " would exceed maxComputeWorkGroupCount[1] limit of "
1070 << gpu_assisted->phys_dev_props.limits.maxComputeWorkGroupCount[1];
1071 vuid_msg = vuid.group_exceeds_device_limit_y;
1072 } else if (debug_record[_kPreValidateSubError] == pre_dispatch_count_exceeds_limit_z_error) {
1073 uint32_t count = debug_record[_kPreValidateSubError + 1];
1074 strm << "Indirect dispatch VkDispatchIndirectCommand::z of " << count
1075 << " would exceed maxComputeWorkGroupCount[2] limit of "
1076 << gpu_assisted->phys_dev_props.limits.maxComputeWorkGroupCount[2];
1077 vuid_msg = vuid.group_exceeds_device_limit_z;
1078 }
1079 return_code = false;
1080 } break;
Karl Schultz7b024b42018-08-30 16:18:18 -06001081 default: {
Tony-LunarGab47cac2019-12-20 15:28:01 -07001082 strm << "Internal Error (unexpected error type = " << debug_record[kInstValidationOutError] << "). ";
Karl Schultz7b024b42018-08-30 16:18:18 -06001083 vuid_msg = "UNASSIGNED-Internal Error";
1084 assert(false);
1085 } break;
1086 }
1087 msg = strm.str();
Tony-LunarG63f82e02021-04-12 16:13:48 -06001088 return return_code;
Karl Schultz7b024b42018-08-30 16:18:18 -06001089}
1090
Karl Schultz7b024b42018-08-30 16:18:18 -06001091// Pull together all the information from the debug record to build the error message strings,
1092// and then assemble them into a single message string.
1093// Retrieve the shader program referenced by the unique shader ID provided in the debug record.
1094// We had to keep a copy of the shader program with the same lifecycle as the pipeline to make
1095// sure it is available when the pipeline is submitted. (The ShaderModule tracking object also
1096// keeps a copy, but it can be destroyed after the pipeline is created and before it is submitted.)
1097//
Tony-LunarG7de10e82020-11-24 11:31:55 -07001098void GpuAssisted::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, GpuAssistedBufferInfo &buffer_info,
Tony-LunarG1dce2392019-10-23 16:49:29 -06001099 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001100 using namespace spvtools;
1101 const uint32_t total_words = debug_output_buffer[0];
1102 // A zero here means that the shader instrumentation didn't write anything.
1103 // If you have nothing to say, don't say it here.
1104 if (0 == total_words) {
1105 return;
1106 }
1107 // The first word in the debug output buffer is the number of words that would have
1108 // been written by the shader instrumentation, if there was enough room in the buffer we provided.
1109 // The number of words actually written by the shaders is determined by the size of the buffer
1110 // we provide via the descriptor. So, we process only the number of words that can fit in the
1111 // buffer.
1112 // Each "report" written by the shader instrumentation is considered a "record". This function
1113 // is hard-coded to process only one record because it expects the buffer to be large enough to
1114 // hold only one record. If there is a desire to process more than one record, this function needs
1115 // to be modified to loop over records and the buffer size increased.
Karl Schultz7b024b42018-08-30 16:18:18 -06001116 std::string validation_message;
1117 std::string stage_message;
1118 std::string common_message;
1119 std::string filename_message;
1120 std::string source_message;
1121 std::string vuid_msg;
1122 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
1123 VkPipeline pipeline_handle = VK_NULL_HANDLE;
sfricke-samsung7fac88a2022-01-26 11:44:22 -08001124 std::vector<uint32_t> pgm;
Karl Schultz7b024b42018-08-30 16:18:18 -06001125 // The first record starts at this offset after the total_words.
1126 const uint32_t *debug_record = &debug_output_buffer[kDebugOutputDataOffset];
1127 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
1128 // by the instrumented shader.
Tony-LunarG99b880b2019-09-26 11:19:52 -06001129 auto it = shader_map.find(debug_record[kInstCommonOutShaderId]);
1130 if (it != shader_map.end()) {
Karl Schultz7b024b42018-08-30 16:18:18 -06001131 shader_module_handle = it->second.shader_module;
1132 pipeline_handle = it->second.pipeline;
1133 pgm = it->second.pgm;
1134 }
Tony-LunarG1a7c9f92021-04-29 16:04:42 -06001135 bool gen_full_message = GenerateValidationMessage(debug_record, validation_message, vuid_msg, buffer_info, this);
Tony-LunarG63f82e02021-04-12 16:13:48 -06001136 if (gen_full_message) {
1137 UtilGenerateStageMessage(debug_record, stage_message);
1138 UtilGenerateCommonMessage(report_data, command_buffer, debug_record, shader_module_handle, pipeline_handle,
1139 buffer_info.pipeline_bind_point, operation_index, common_message);
1140 UtilGenerateSourceMessages(pgm, debug_record, false, filename_message, source_message);
1141 LogError(queue, vuid_msg.c_str(), "%s %s %s %s%s", validation_message.c_str(), common_message.c_str(), stage_message.c_str(),
1142 filename_message.c_str(), source_message.c_str());
1143 }
1144 else {
1145 LogError(queue, vuid_msg.c_str(), "%s", validation_message.c_str());
1146 }
Karl Schultz7b024b42018-08-30 16:18:18 -06001147 // The debug record at word kInstCommonOutSize is the number of words in the record
1148 // written by the shader. Clear the entire record plus the total_words word at the start.
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001149 const uint32_t words_to_clear = 1 + std::min(debug_record[kInstCommonOutSize], static_cast<uint32_t>(kInstMaxOutCnt));
Karl Schultz7b024b42018-08-30 16:18:18 -06001150 memset(debug_output_buffer, 0, sizeof(uint32_t) * words_to_clear);
1151}
1152
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001153// For the given command buffer, map its debug data buffers and read their contents for analysis.
Jeremy Gebben5ca80b32022-04-11 10:58:39 -06001154void gpuav_state::CommandBuffer::Process(VkQueue queue) {
1155 auto *device_state = static_cast<GpuAssisted *>(dev_data);
sjfricke52defd42022-08-08 16:37:46 +09001156 if (has_draw_cmd || has_trace_rays_cmd || has_dispatch_cmd) {
Jeremy Gebben5ca80b32022-04-11 10:58:39 -06001157 auto &gpu_buffer_list = gpuav_buffer_list;
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001158 uint32_t draw_index = 0;
1159 uint32_t compute_index = 0;
1160 uint32_t ray_trace_index = 0;
1161
1162 for (auto &buffer_info : gpu_buffer_list) {
Jeremy Gebben5ca80b32022-04-11 10:58:39 -06001163 char *data;
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001164
1165 uint32_t operation_index = 0;
1166 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
1167 operation_index = draw_index;
sjfricke9a209802022-08-03 17:57:40 +09001168 draw_index++;
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001169 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
1170 operation_index = compute_index;
sjfricke9a209802022-08-03 17:57:40 +09001171 compute_index++;
sjfricke62366d32022-08-01 21:04:10 +09001172 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) {
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001173 operation_index = ray_trace_index;
sjfricke9a209802022-08-03 17:57:40 +09001174 ray_trace_index++;
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001175 } else {
1176 assert(false);
1177 }
1178
Jeremy Gebben5ca80b32022-04-11 10:58:39 -06001179 VkResult result = vmaMapMemory(device_state->vmaAllocator, buffer_info.output_mem_block.allocation, (void **)&data);
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001180 if (result == VK_SUCCESS) {
Jeremy Gebben5ca80b32022-04-11 10:58:39 -06001181 device_state->AnalyzeAndGenerateMessages(commandBuffer(), queue, buffer_info, operation_index, (uint32_t *)data);
1182 vmaUnmapMemory(device_state->vmaAllocator, buffer_info.output_mem_block.allocation);
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001183 }
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001184 }
1185 }
Jeremy Gebben5ca80b32022-04-11 10:58:39 -06001186 ProcessAccelerationStructure(queue);
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -06001187}
1188
Jeremy Gebbenf4816f72022-07-15 08:56:06 -06001189void GpuAssisted::SetBindingState(uint32_t *data, uint32_t index, const cvdescriptorset::DescriptorBinding *binding) {
1190 switch (binding->descriptor_class) {
1191 case cvdescriptorset::DescriptorClass::GeneralBuffer: {
1192 auto buffer_binding = static_cast<const cvdescriptorset::BufferBinding *>(binding);
1193 for (uint32_t di = 0; di < buffer_binding->count; di++) {
1194 const auto &desc = buffer_binding->descriptors[di];
1195 if (!buffer_binding->updated[di]) {
1196 data[index++] = 0;
1197 continue;
1198 }
1199 auto buffer = desc.GetBuffer();
1200 if (buffer == VK_NULL_HANDLE) {
1201 data[index++] = UINT_MAX;
1202 } else {
1203 auto buffer_state = desc.GetBufferState();
1204 data[index++] = static_cast<uint32_t>(buffer_state->createInfo.size);
1205 }
1206 }
1207 break;
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001208 }
Jeremy Gebbenf4816f72022-07-15 08:56:06 -06001209 case cvdescriptorset::DescriptorClass::TexelBuffer: {
1210 auto texel_binding = static_cast<const cvdescriptorset::TexelBinding *>(binding);
1211 for (uint32_t di = 0; di < texel_binding->count; di++) {
1212 const auto &desc = texel_binding->descriptors[di];
1213 if (!texel_binding->updated[di]) {
1214 data[index++] = 0;
1215 continue;
1216 }
1217 auto buffer_view = desc.GetBufferView();
1218 if (buffer_view == VK_NULL_HANDLE) {
1219 data[index++] = UINT_MAX;
1220 } else {
1221 auto buffer_view_state = desc.GetBufferViewState();
1222 data[index++] = static_cast<uint32_t>(buffer_view_state->buffer_state->createInfo.size);
1223 }
1224 }
1225 break;
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001226 }
Jeremy Gebbenf4816f72022-07-15 08:56:06 -06001227 case cvdescriptorset::DescriptorClass::Mutable: {
1228 auto mutable_binding = static_cast<const cvdescriptorset::MutableBinding *>(binding);
1229 for (uint32_t di = 0; di < mutable_binding->count; di++) {
1230 const auto &desc = mutable_binding->descriptors[di];
1231 if (!mutable_binding->updated[di]) {
1232 data[index++] = 0;
1233 continue;
1234 }
Jeremy Gebbenc08f6502022-07-15 09:55:06 -06001235 switch (desc.ActiveType()) {
1236 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1237 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1238 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1239 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1240 data[index++] = static_cast<uint32_t>(desc.GetBufferSize());
1241 break;
1242 default:
Jeremy Gebbenf4816f72022-07-15 08:56:06 -06001243 data[index++] = 1;
Jeremy Gebbenc08f6502022-07-15 09:55:06 -06001244 break;
Jeremy Gebbenf4816f72022-07-15 08:56:06 -06001245 }
1246 }
1247 break;
ziga7a255fb2021-11-20 21:17:07 +01001248 }
Jeremy Gebbenf4816f72022-07-15 08:56:06 -06001249 default: {
1250 for (uint32_t i = 0; i < binding->count; i++, index++) {
1251 data[index] = static_cast<uint32_t>(binding->updated[i]);
1252 }
1253 break;
1254 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001255 }
1256}
1257
Tony-LunarG81efe392019-03-07 15:43:27 -07001258// For the given command buffer, map its debug data buffers and update the status of any update after bind descriptors
Jeremy Gebben135550d2022-03-21 07:15:07 -06001259void GpuAssisted::UpdateInstrumentationBuffer(gpuav_state::CommandBuffer *cb_node) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001260 uint32_t *data;
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06001261 for (auto &buffer_info : cb_node->gpuav_buffer_list) {
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001262 if (buffer_info.di_input_mem_block.update_at_submit.size() > 0) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001263 VkResult result =
1264 vmaMapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation, reinterpret_cast<void **>(&data));
Tony-LunarG81efe392019-03-07 15:43:27 -07001265 if (result == VK_SUCCESS) {
John Zulauf79f06582021-02-27 18:38:39 -07001266 for (const auto &update : buffer_info.di_input_mem_block.update_at_submit) {
Jeremy Gebbenf4816f72022-07-15 08:56:06 -06001267 SetBindingState(data, update.first, update.second);
Tony-LunarG81efe392019-03-07 15:43:27 -07001268 }
Tony-LunarG99b880b2019-09-26 11:19:52 -06001269 vmaUnmapMemory(vmaAllocator, buffer_info.di_input_mem_block.allocation);
Tony-LunarG81efe392019-03-07 15:43:27 -07001270 }
1271 }
1272 }
1273}
1274
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001275void GpuAssisted::PreRecordCommandBuffer(VkCommandBuffer command_buffer) {
Jeremy Gebben04697b02022-03-23 16:18:12 -06001276 auto cb_node = GetWrite<gpuav_state::CommandBuffer>(command_buffer);
Jeremy Gebben9f537102021-10-05 16:37:12 -06001277 UpdateInstrumentationBuffer(cb_node.get());
John Zulauf79f06582021-02-27 18:38:39 -07001278 for (auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebben04697b02022-03-23 16:18:12 -06001279 auto guard = secondary_cmd_buffer->WriteLock();
Jeremy Gebben135550d2022-03-21 07:15:07 -06001280 UpdateInstrumentationBuffer(static_cast<gpuav_state::CommandBuffer *>(secondary_cmd_buffer));
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001281 }
1282}
1283
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001284void GpuAssisted::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001285 ValidationStateTracker::PreCallRecordQueueSubmit(queue, submitCount, pSubmits, fence);
Tony-LunarG81efe392019-03-07 15:43:27 -07001286 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1287 const VkSubmitInfo *submit = &pSubmits[submit_idx];
1288 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001289 PreRecordCommandBuffer(submit->pCommandBuffers[i]);
Tony-LunarG81efe392019-03-07 15:43:27 -07001290 }
1291 }
1292}
Tony-LunarG26fe2842021-11-16 14:07:59 -07001293
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001294void GpuAssisted::PreCallRecordQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR *pSubmits,
1295 VkFence fence) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001296 ValidationStateTracker::PreCallRecordQueueSubmit2KHR(queue, submitCount, pSubmits, fence);
Jeremy Gebbena3705f42021-01-19 16:47:43 -07001297 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1298 const VkSubmitInfo2KHR *submit = &pSubmits[submit_idx];
1299 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
1300 PreRecordCommandBuffer(submit->pCommandBufferInfos[i].commandBuffer);
1301 }
1302 }
1303}
1304
Tony-LunarG26fe2842021-11-16 14:07:59 -07001305void GpuAssisted::PreCallRecordQueueSubmit2(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2 *pSubmits, VkFence fence) {
1306 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
1307 const VkSubmitInfo2 *submit = &pSubmits[submit_idx];
1308 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
1309 PreRecordCommandBuffer(submit->pCommandBufferInfos[i].commandBuffer);
1310 }
1311 }
1312}
1313
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001314void GpuAssisted::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
1315 uint32_t firstVertex, uint32_t firstInstance) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001316 ValidationStateTracker::PreCallRecordCmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001317 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAW);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001318}
1319
Tony-LunarG745150c2021-07-02 15:07:31 -06001320void GpuAssisted::PreCallRecordCmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint32_t drawCount,
1321 const VkMultiDrawInfoEXT *pVertexInfo, uint32_t instanceCount,
1322 uint32_t firstInstance, uint32_t stride) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001323 ValidationStateTracker::PreCallRecordCmdDrawMultiEXT(commandBuffer, drawCount, pVertexInfo, instanceCount, firstInstance,
1324 stride);
Tony-LunarG745150c2021-07-02 15:07:31 -06001325 for (uint32_t i = 0; i < drawCount; i++) {
1326 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMULTIEXT);
1327 }
1328}
1329
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001330void GpuAssisted::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
1331 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001332 ValidationStateTracker::PreCallRecordCmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset,
1333 firstInstance);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001334 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXED);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001335}
1336
Tony-LunarG745150c2021-07-02 15:07:31 -06001337void GpuAssisted::PreCallRecordCmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer, uint32_t drawCount,
1338 const VkMultiDrawIndexedInfoEXT *pIndexInfo, uint32_t instanceCount,
1339 uint32_t firstInstance, uint32_t stride, const int32_t *pVertexOffset) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001340 ValidationStateTracker::PreCallRecordCmdDrawMultiIndexedEXT(commandBuffer, drawCount, pIndexInfo, instanceCount, firstInstance,
1341 stride, pVertexOffset);
Tony-LunarG745150c2021-07-02 15:07:31 -06001342 for (uint32_t i = 0; i < drawCount; i++) {
1343 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMULTIINDEXEDEXT);
1344 }
1345}
1346
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001347void GpuAssisted::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
1348 uint32_t stride) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001349 ValidationStateTracker::PreCallRecordCmdDrawIndirect(commandBuffer, buffer, offset, count, stride);
sjfrickeca9a4802022-08-10 14:27:51 +09001350 GpuAssistedCmdIndirectState indirect_state = {buffer, offset, count, stride, VK_NULL_HANDLE, 0};
1351 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECT, &indirect_state);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001352}
1353
1354void GpuAssisted::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1355 uint32_t count, uint32_t stride) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001356 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride);
sjfrickeca9a4802022-08-10 14:27:51 +09001357 GpuAssistedCmdIndirectState indirect_state = {buffer, offset, count, stride, VK_NULL_HANDLE, 0};
1358 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECT, &indirect_state);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001359}
1360
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001361void GpuAssisted::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1362 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
1363 uint32_t stride) {
1364 ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1365 maxDrawCount, stride);
sjfrickeca9a4802022-08-10 14:27:51 +09001366 GpuAssistedCmdIndirectState indirect_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1367 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTCOUNTKHR, &indirect_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001368}
1369
1370void GpuAssisted::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1371 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001372
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001373 uint32_t stride) {
1374 ValidationStateTracker::PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1375 maxDrawCount, stride);
sjfrickeca9a4802022-08-10 14:27:51 +09001376 GpuAssistedCmdIndirectState indirect_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1377 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTCOUNT, &indirect_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001378}
1379
Tony-LunarG54176fb2020-12-02 10:47:22 -07001380void GpuAssisted::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
1381 uint32_t firstInstance, VkBuffer counterBuffer,
1382 VkDeviceSize counterBufferOffset, uint32_t counterOffset,
1383 uint32_t vertexStride) {
1384 ValidationStateTracker::PreCallRecordCmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer,
1385 counterBufferOffset, counterOffset, vertexStride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001386 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTBYTECOUNTEXT);
Tony-LunarG54176fb2020-12-02 10:47:22 -07001387}
1388
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001389void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1390 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1391 uint32_t maxDrawCount, uint32_t stride) {
1392 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer,
1393 countBufferOffset, maxDrawCount, stride);
sjfrickeca9a4802022-08-10 14:27:51 +09001394 GpuAssistedCmdIndirectState indirect_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1395 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECTCOUNTKHR, &indirect_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001396}
1397
1398void GpuAssisted::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1399 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1400 uint32_t maxDrawCount, uint32_t stride) {
1401 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
1402 maxDrawCount, stride);
sjfrickeca9a4802022-08-10 14:27:51 +09001403 GpuAssistedCmdIndirectState indirect_state = {buffer, offset, 0, stride, countBuffer, countBufferOffset};
1404 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECTCOUNT, &indirect_state);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001405}
1406
1407void GpuAssisted::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
1408 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001409 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001410}
1411
1412void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1413 uint32_t drawCount, uint32_t stride) {
1414 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001415 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSINDIRECTNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001416}
1417
1418void GpuAssisted::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
1419 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
1420 uint32_t maxDrawCount, uint32_t stride) {
1421 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer,
1422 countBufferOffset, maxDrawCount, stride);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001423 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSINDIRECTCOUNTNV);
Tony-LunarG2fb8ff02020-06-11 12:45:07 -06001424}
1425
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001426void GpuAssisted::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001427 ValidationStateTracker::PreCallRecordCmdDispatch(commandBuffer, x, y, z);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001428 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCH);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001429}
1430
1431void GpuAssisted::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001432 ValidationStateTracker::PreCallRecordCmdDispatchIndirect(commandBuffer, buffer, offset);
sjfrickeca9a4802022-08-10 14:27:51 +09001433 GpuAssistedCmdIndirectState indirect_state = {buffer, offset, 0, 0, VK_NULL_HANDLE, 0};
1434 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHINDIRECT, &indirect_state);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001435}
1436
Tony-LunarGd13f9b52020-09-08 15:45:45 -06001437void GpuAssisted::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1438 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1439 uint32_t groupCountZ) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001440 ValidationStateTracker::PreCallRecordCmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX,
1441 groupCountY, groupCountZ);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001442 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHBASE);
Tony-LunarGd13f9b52020-09-08 15:45:45 -06001443}
1444
Tony-LunarG52c8c602020-09-10 16:29:56 -06001445void GpuAssisted::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
1446 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
1447 uint32_t groupCountZ) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001448 ValidationStateTracker::PreCallRecordCmdDispatchBaseKHR(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX,
1449 groupCountY, groupCountZ);
sfricke-samsung85584a72021-09-30 21:43:38 -07001450 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHBASEKHR);
Tony-LunarG52c8c602020-09-10 16:29:56 -06001451}
1452
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001453void GpuAssisted::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
1454 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
1455 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
1456 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
1457 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
1458 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
1459 uint32_t width, uint32_t height, uint32_t depth) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001460 ValidationStateTracker::PreCallRecordCmdTraceRaysNV(
1461 commandBuffer, raygenShaderBindingTableBuffer, raygenShaderBindingOffset, missShaderBindingTableBuffer,
1462 missShaderBindingOffset, missShaderBindingStride, hitShaderBindingTableBuffer, hitShaderBindingOffset,
1463 hitShaderBindingStride, callableShaderBindingTableBuffer, callableShaderBindingOffset, callableShaderBindingStride, width,
1464 height, depth);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001465 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, CMD_TRACERAYSNV);
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001466}
1467
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001468void GpuAssisted::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001469 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1470 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1471 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1472 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001473 uint32_t height, uint32_t depth) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001474 ValidationStateTracker::PreCallRecordCmdTraceRaysKHR(commandBuffer, pRaygenShaderBindingTable, pMissShaderBindingTable,
1475 pHitShaderBindingTable, pCallableShaderBindingTable, width, height, depth);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001476 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, CMD_TRACERAYSKHR);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001477}
1478
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001479
1480void GpuAssisted::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -07001481 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
1482 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
1483 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
1484 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -07001485 VkDeviceAddress indirectDeviceAddress) {
Tony-LunarG9dc7d4a2021-11-04 13:25:59 -06001486 ValidationStateTracker::PreCallRecordCmdTraceRaysIndirectKHR(commandBuffer, pRaygenShaderBindingTable, pMissShaderBindingTable,
1487 pHitShaderBindingTable, pCallableShaderBindingTable,
1488 indirectDeviceAddress);
Tony-LunarG7de10e82020-11-24 11:31:55 -07001489 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, CMD_TRACERAYSINDIRECTKHR);
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001490}
1491
sfricke-samsungf91881c2022-03-31 01:12:00 -05001492void GpuAssisted::PreCallRecordCmdTraceRaysIndirect2KHR(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress) {
1493 ValidationStateTracker::PreCallRecordCmdTraceRaysIndirect2KHR(commandBuffer, indirectDeviceAddress);
1494 AllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, CMD_TRACERAYSINDIRECT2KHR);
1495}
1496
sjfricke43b340c2022-08-04 22:18:38 +09001497// This function will add the returned VkPipeline handle to another object incharge of destroying it. Caller does NOT have to
1498// destroy it
Jeremy Gebbenbba39212022-03-29 16:39:06 -06001499VkPipeline GpuAssisted::GetValidationPipeline(VkRenderPass render_pass) {
1500 VkPipeline pipeline = VK_NULL_HANDLE;
1501 //NOTE: for dynamic rendering, render_pass will be VK_NULL_HANDLE but we'll use that as a map
1502 //key anyways;
1503 auto pipeentry = pre_draw_validation_state.renderpass_to_pipeline.find(render_pass);
1504 if (pipeentry != pre_draw_validation_state.renderpass_to_pipeline.end()) {
1505 pipeline = pipeentry->second;
1506 }
1507 if (pipeline != VK_NULL_HANDLE) {
1508 return pipeline;
1509 }
1510 auto pipeline_stage_ci = LvlInitStruct<VkPipelineShaderStageCreateInfo>();
1511 pipeline_stage_ci.stage = VK_SHADER_STAGE_VERTEX_BIT;
sjfricke43b340c2022-08-04 22:18:38 +09001512 pipeline_stage_ci.module = pre_draw_validation_state.shader_module;
Jeremy Gebbenbba39212022-03-29 16:39:06 -06001513 pipeline_stage_ci.pName = "main";
1514
sjfricke43b340c2022-08-04 22:18:38 +09001515 auto pipeline_ci = LvlInitStruct<VkGraphicsPipelineCreateInfo>();
1516 auto vertex_input_state = LvlInitStruct<VkPipelineVertexInputStateCreateInfo>();
1517 auto input_assembly_state = LvlInitStruct<VkPipelineInputAssemblyStateCreateInfo>();
1518 input_assembly_state.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1519 auto rasterization_state = LvlInitStruct<VkPipelineRasterizationStateCreateInfo>();
1520 rasterization_state.rasterizerDiscardEnable = VK_TRUE;
1521 auto color_blend_state = LvlInitStruct<VkPipelineColorBlendStateCreateInfo>();
Jeremy Gebbenbba39212022-03-29 16:39:06 -06001522
sjfricke43b340c2022-08-04 22:18:38 +09001523 pipeline_ci.pVertexInputState = &vertex_input_state;
1524 pipeline_ci.pInputAssemblyState = &input_assembly_state;
1525 pipeline_ci.pRasterizationState = &rasterization_state;
1526 pipeline_ci.pColorBlendState = &color_blend_state;
1527 pipeline_ci.renderPass = render_pass;
1528 pipeline_ci.layout = pre_draw_validation_state.pipeline_layout;
1529 pipeline_ci.stageCount = 1;
1530 pipeline_ci.pStages = &pipeline_stage_ci;
Jeremy Gebbenbba39212022-03-29 16:39:06 -06001531
sjfricke43b340c2022-08-04 22:18:38 +09001532 VkResult result = DispatchCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr, &pipeline);
Jeremy Gebbenbba39212022-03-29 16:39:06 -06001533 if (result != VK_SUCCESS) {
1534 ReportSetupProblem(device, "Unable to create graphics pipeline. Aborting GPU-AV");
1535 aborted = true;
1536 return VK_NULL_HANDLE;
1537 }
1538
1539 pre_draw_validation_state.renderpass_to_pipeline.insert(render_pass, pipeline);
1540 return pipeline;
1541}
Jeff Bolz443c2ca2020-03-19 12:11:51 -05001542
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001543void GpuAssisted::AllocatePreDrawValidationResources(GpuAssistedDeviceMemoryBlock output_block,
Tony-LunarG56f0d0f2022-08-17 12:04:17 -06001544 GpuAssistedPreDrawResources &resources, const VkRenderPass render_pass,
sjfrickeca9a4802022-08-10 14:27:51 +09001545 VkPipeline *pPipeline, const GpuAssistedCmdIndirectState *indirect_state) {
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001546 VkResult result;
sjfrickeca9a4802022-08-10 14:27:51 +09001547 if (!pre_draw_validation_state.initialized) {
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001548 auto shader_module_ci = LvlInitStruct<VkShaderModuleCreateInfo>();
sjfrickebecf0722022-08-05 16:15:46 +09001549 shader_module_ci.codeSize = sizeof(gpu_pre_draw_vert);
1550 shader_module_ci.pCode = gpu_pre_draw_vert;
sjfricke43b340c2022-08-04 22:18:38 +09001551 result = DispatchCreateShaderModule(device, &shader_module_ci, nullptr, &pre_draw_validation_state.shader_module);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001552 if (result != VK_SUCCESS) {
1553 ReportSetupProblem(device, "Unable to create shader module. Aborting GPU-AV");
1554 aborted = true;
1555 return;
1556 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001557
sjfricke43b340c2022-08-04 22:18:38 +09001558 std::vector<VkDescriptorSetLayoutBinding> bindings = {
1559 {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, nullptr}, // output buffer
1560 {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, nullptr}, // count/draws buffer
1561 };
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001562
sjfrickee9b39372022-05-22 13:02:17 +09001563 VkDescriptorSetLayoutCreateInfo ds_layout_ci = LvlInitStruct<VkDescriptorSetLayoutCreateInfo>();
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001564 ds_layout_ci.bindingCount = static_cast<uint32_t>(bindings.size());
1565 ds_layout_ci.pBindings = bindings.data();
sjfricke43b340c2022-08-04 22:18:38 +09001566 result = DispatchCreateDescriptorSetLayout(device, &ds_layout_ci, nullptr, &pre_draw_validation_state.ds_layout);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001567 if (result != VK_SUCCESS) {
1568 ReportSetupProblem(device, "Unable to create descriptor set layout. Aborting GPU-AV");
1569 aborted = true;
1570 return;
1571 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001572
sjfricke43b340c2022-08-04 22:18:38 +09001573 VkPushConstantRange push_constant_range = {};
1574 push_constant_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
1575 push_constant_range.offset = 0;
1576 push_constant_range.size = resources.push_constant_words * sizeof(uint32_t);
1577 VkPipelineLayoutCreateInfo pipeline_layout_ci = LvlInitStruct<VkPipelineLayoutCreateInfo>();
1578 pipeline_layout_ci.pushConstantRangeCount = 1;
1579 pipeline_layout_ci.pPushConstantRanges = &push_constant_range;
1580 pipeline_layout_ci.setLayoutCount = 1;
1581 pipeline_layout_ci.pSetLayouts = &pre_draw_validation_state.ds_layout;
1582 result = DispatchCreatePipelineLayout(device, &pipeline_layout_ci, nullptr, &pre_draw_validation_state.pipeline_layout);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001583 if (result != VK_SUCCESS) {
1584 ReportSetupProblem(device, "Unable to create pipeline layout. Aborting GPU-AV");
1585 aborted = true;
1586 return;
1587 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001588
sjfrickeca9a4802022-08-10 14:27:51 +09001589 pre_draw_validation_state.initialized = true;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001590 }
Tony-LunarG463bae32022-02-25 09:31:17 -07001591
Jeremy Gebbenbba39212022-03-29 16:39:06 -06001592 *pPipeline = GetValidationPipeline(render_pass);
1593 if (*pPipeline == VK_NULL_HANDLE) {
sjfricke43b340c2022-08-04 22:18:38 +09001594 ReportSetupProblem(device, "Could not find or create a pipeline. Aborting GPU-AV");
1595 aborted = true;
Jeremy Gebbenbba39212022-03-29 16:39:06 -06001596 return;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001597 }
1598
sjfricke43b340c2022-08-04 22:18:38 +09001599 result = desc_set_manager->GetDescriptorSet(&resources.desc_pool, pre_draw_validation_state.ds_layout, &resources.desc_set);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001600 if (result != VK_SUCCESS) {
1601 ReportSetupProblem(device, "Unable to allocate descriptor set. Aborting GPU-AV");
1602 aborted = true;
1603 return;
1604 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001605
sjfricke43b340c2022-08-04 22:18:38 +09001606 const uint32_t buffer_count = 2;
1607 VkDescriptorBufferInfo buffer_infos[buffer_count] = {};
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001608 // Error output buffer
1609 buffer_infos[0].buffer = output_block.buffer;
1610 buffer_infos[0].offset = 0;
1611 buffer_infos[0].range = VK_WHOLE_SIZE;
sjfrickeca9a4802022-08-10 14:27:51 +09001612 if (indirect_state->count_buffer) {
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001613 // Count buffer
sjfrickeca9a4802022-08-10 14:27:51 +09001614 buffer_infos[1].buffer = indirect_state->count_buffer;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001615 } else {
1616 // Draw Buffer
sjfrickeca9a4802022-08-10 14:27:51 +09001617 buffer_infos[1].buffer = indirect_state->buffer;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001618 }
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001619 buffer_infos[1].offset = 0;
1620 buffer_infos[1].range = VK_WHOLE_SIZE;
1621
sjfricke43b340c2022-08-04 22:18:38 +09001622 VkWriteDescriptorSet desc_writes[buffer_count] = {};
1623 for (uint32_t i = 0; i < buffer_count; i++) {
sjfrickee9b39372022-05-22 13:02:17 +09001624 desc_writes[i] = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001625 desc_writes[i].dstBinding = i;
1626 desc_writes[i].descriptorCount = 1;
1627 desc_writes[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1628 desc_writes[i].pBufferInfo = &buffer_infos[i];
1629 desc_writes[i].dstSet = resources.desc_set;
1630 }
sjfricke43b340c2022-08-04 22:18:38 +09001631 DispatchUpdateDescriptorSets(device, buffer_count, desc_writes, 0, NULL);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001632}
sjfrickeca9a4802022-08-10 14:27:51 +09001633void GpuAssisted::AllocatePreDispatchValidationResources(GpuAssistedDeviceMemoryBlock output_block,
1634 GpuAssistedPreDispatchResources &resources,
1635 const GpuAssistedCmdIndirectState *indirect_state) {
1636 VkResult result;
1637 if (!pre_dispatch_validation_state.initialized) {
1638 auto shader_module_ci = LvlInitStruct<VkShaderModuleCreateInfo>();
1639 shader_module_ci.codeSize = sizeof(gpu_pre_dispatch_comp);
1640 shader_module_ci.pCode = gpu_pre_dispatch_comp;
1641 result = DispatchCreateShaderModule(device, &shader_module_ci, nullptr, &pre_dispatch_validation_state.shader_module);
1642 if (result != VK_SUCCESS) {
1643 ReportSetupProblem(device, "Unable to create shader module. Aborting GPU-AV");
1644 aborted = true;
1645 return;
1646 }
1647
1648 std::vector<VkDescriptorSetLayoutBinding> bindings = {
1649 {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, // output buffer
1650 {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}, // indirect buffer
1651 };
1652
1653 VkDescriptorSetLayoutCreateInfo ds_layout_ci = LvlInitStruct<VkDescriptorSetLayoutCreateInfo>();
1654 ds_layout_ci.bindingCount = static_cast<uint32_t>(bindings.size());
1655 ds_layout_ci.pBindings = bindings.data();
1656 result = DispatchCreateDescriptorSetLayout(device, &ds_layout_ci, nullptr, &pre_dispatch_validation_state.ds_layout);
1657 if (result != VK_SUCCESS) {
1658 ReportSetupProblem(device, "Unable to create descriptor set layout. Aborting GPU-AV");
1659 aborted = true;
1660 return;
1661 }
1662
1663 VkPushConstantRange push_constant_range = {};
1664 push_constant_range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
1665 push_constant_range.offset = 0;
1666 push_constant_range.size = resources.push_constant_words * sizeof(uint32_t);
1667 VkPipelineLayoutCreateInfo pipeline_layout_ci = LvlInitStruct<VkPipelineLayoutCreateInfo>();
1668 pipeline_layout_ci.pushConstantRangeCount = 1;
1669 pipeline_layout_ci.pPushConstantRanges = &push_constant_range;
1670 pipeline_layout_ci.setLayoutCount = 1;
1671 pipeline_layout_ci.pSetLayouts = &pre_dispatch_validation_state.ds_layout;
1672 result = DispatchCreatePipelineLayout(device, &pipeline_layout_ci, nullptr, &pre_dispatch_validation_state.pipeline_layout);
1673 if (result != VK_SUCCESS) {
1674 ReportSetupProblem(device, "Unable to create pipeline layout. Aborting GPU-AV");
1675 aborted = true;
1676 return;
1677 }
1678
1679 // Create pipeline
1680 auto pipeline_stage_ci = LvlInitStruct<VkPipelineShaderStageCreateInfo>();
1681 pipeline_stage_ci.stage = VK_SHADER_STAGE_COMPUTE_BIT;
1682 pipeline_stage_ci.module = pre_dispatch_validation_state.shader_module;
1683 pipeline_stage_ci.pName = "main";
1684
1685 auto pipeline_ci = LvlInitStruct<VkComputePipelineCreateInfo>();
1686 pipeline_ci.stage = pipeline_stage_ci;
1687 pipeline_ci.layout = pre_dispatch_validation_state.pipeline_layout;
1688
1689 result = DispatchCreateComputePipelines(device, VK_NULL_HANDLE, 1, &pipeline_ci, nullptr,
1690 &pre_dispatch_validation_state.pipeline);
1691 if (result != VK_SUCCESS) {
1692 ReportSetupProblem(device, "Failed to create compute pipeline for pre dispatch validation.");
1693 }
1694
1695 pre_dispatch_validation_state.initialized = true;
1696 }
1697
1698 result = desc_set_manager->GetDescriptorSet(&resources.desc_pool, pre_dispatch_validation_state.ds_layout, &resources.desc_set);
1699 if (result != VK_SUCCESS) {
1700 ReportSetupProblem(device, "Unable to allocate descriptor set. Aborting GPU-AV");
1701 aborted = true;
1702 return;
1703 }
1704
1705 const uint32_t buffer_count = 2;
1706 VkDescriptorBufferInfo buffer_infos[buffer_count] = {};
1707 // Error output buffer
1708 buffer_infos[0].buffer = output_block.buffer;
1709 buffer_infos[0].offset = 0;
1710 buffer_infos[0].range = VK_WHOLE_SIZE;
1711 buffer_infos[1].buffer = indirect_state->buffer;
1712 buffer_infos[1].offset = 0;
1713 buffer_infos[1].range = VK_WHOLE_SIZE;
1714
1715 VkWriteDescriptorSet desc_writes[buffer_count] = {};
1716 for (uint32_t i = 0; i < buffer_count; i++) {
1717 desc_writes[i] = LvlInitStruct<VkWriteDescriptorSet>();
1718 desc_writes[i].dstBinding = i;
1719 desc_writes[i].descriptorCount = 1;
1720 desc_writes[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1721 desc_writes[i].pBufferInfo = &buffer_infos[i];
1722 desc_writes[i].dstSet = resources.desc_set;
1723 }
1724 DispatchUpdateDescriptorSets(device, buffer_count, desc_writes, 0, nullptr);
1725}
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001726
Tony-LunarG7de10e82020-11-24 11:31:55 -07001727void GpuAssisted::AllocateValidationResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point,
sjfrickeca9a4802022-08-10 14:27:51 +09001728 CMD_TYPE cmd_type, const GpuAssistedCmdIndirectState *indirect_state) {
Jason Macnak67407e72019-07-11 11:05:09 -07001729 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
sjfricke62366d32022-08-01 21:04:10 +09001730 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) {
andreygca287f22019-04-10 00:15:33 +03001731 return;
1732 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07001733 VkResult result;
1734
Tony-LunarG99b880b2019-09-26 11:19:52 -06001735 if (aborted) return;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001736
Jeremy Gebben04697b02022-03-23 16:18:12 -06001737 auto cb_node = GetWrite<gpuav_state::CommandBuffer>(cmd_buffer);
Nathaniel Cesariobcb79682022-03-31 21:13:52 -06001738 if (!cb_node) {
1739 ReportSetupProblem(device, "Unrecognized command buffer");
1740 aborted = true;
1741 return;
1742 }
1743 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
1744 auto const &state = cb_node->lastBound[lv_bind_point];
1745 const auto *pipeline_state = state.pipeline_state;
1746
1747 // TODO (ncesario) remove once VK_EXT_graphics_pipeline_library support is added for GPU-AV
1748 if (pipeline_state->IsGraphicsLibrary()) {
1749 ReportSetupProblem(device, "GPU-AV does not currently support VK_EXT_graphics_pipeline_library");
1750 aborted = true;
1751 return;
1752 }
1753
Tony-LunarGb2501d22019-01-28 09:59:13 -07001754 std::vector<VkDescriptorSet> desc_sets;
1755 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -06001756 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001757 assert(result == VK_SUCCESS);
1758 if (result != VK_SUCCESS) {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07001759 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG99b880b2019-09-26 11:19:52 -06001760 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001761 return;
1762 }
1763
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001764 VkDescriptorBufferInfo output_desc_buffer_info = {};
Tony-LunarG99b880b2019-09-26 11:19:52 -06001765 output_desc_buffer_info.range = output_buffer_size;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001766
Tony-LunarG81efe392019-03-07 15:43:27 -07001767 // Allocate memory for the output block that the gpu will use to return any error information
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001768 GpuAssistedDeviceMemoryBlock output_block = {};
sjfrickee9b39372022-05-22 13:02:17 +09001769 VkBufferCreateInfo buffer_info = LvlInitStruct<VkBufferCreateInfo>();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001770 buffer_info.size = output_buffer_size;
1771 buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
1772 VmaAllocationCreateInfo alloc_info = {};
Tony-LunarGef497962022-04-19 08:48:52 -06001773 alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
Tony-LunarG20d18a72022-04-19 11:01:47 -06001774 alloc_info.pool = output_buffer_pool;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001775 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07001776 if (result != VK_SUCCESS) {
Tony-LunarGa2aa78b2022-04-19 08:41:38 -06001777 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.", true);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001778 aborted = true;
Tony-LunarGb2501d22019-01-28 09:59:13 -07001779 return;
1780 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001781
Tony-LunarG81efe392019-03-07 15:43:27 -07001782 // Clear the output block to zeros so that only error information from the gpu will be present
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001783 uint32_t *data_ptr;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001784 result = vmaMapMemory(vmaAllocator, output_block.allocation, reinterpret_cast<void **>(&data_ptr));
Tony-LunarG0e564722019-03-19 16:09:14 -06001785 if (result == VK_SUCCESS) {
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001786 memset(data_ptr, 0, output_buffer_size);
Tony-LunarG99b880b2019-09-26 11:19:52 -06001787 vmaUnmapMemory(vmaAllocator, output_block.allocation);
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001788 }
Tony-LunarG81efe392019-03-07 15:43:27 -07001789
Tony-LunarG2ba1cb32019-09-25 15:16:11 -06001790 GpuAssistedDeviceMemoryBlock di_input_block = {}, bda_input_block = {};
Tony-LunarG8eb5a002019-07-25 16:49:00 -06001791 VkDescriptorBufferInfo di_input_desc_buffer_info = {};
1792 VkDescriptorBufferInfo bda_input_desc_buffer_info = {};
1793 VkWriteDescriptorSet desc_writes[3] = {};
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001794 GpuAssistedPreDrawResources pre_draw_resources = {};
sjfrickeca9a4802022-08-10 14:27:51 +09001795 GpuAssistedPreDispatchResources pre_dispatch_resources = {};
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001796 uint32_t desc_count = 1;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001797 uint32_t number_of_sets = static_cast<uint32_t>(state.per_set.size());
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001798
sfricke-samsung85584a72021-09-30 21:43:38 -07001799 if (validate_draw_indirect && ((cmd_type == CMD_DRAWINDIRECTCOUNT || cmd_type == CMD_DRAWINDIRECTCOUNTKHR ||
1800 cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT || cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNTKHR) ||
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001801 ((cmd_type == CMD_DRAWINDIRECT || cmd_type == CMD_DRAWINDEXEDINDIRECT) &&
1802 !(enabled_features.core.drawIndirectFirstInstance)))) {
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001803 // Insert a draw that can examine some device memory right before the draw we're validating (Pre Draw Validation)
Tony-LunarG20678ff2021-05-07 14:56:26 -06001804 //
1805 // NOTE that this validation does not attempt to abort invalid api calls as most other validation does. A crash
1806 // or DEVICE_LOST resulting from the invalid call will prevent preceeding validation errors from being reported.
1807
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001808 assert(bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS);
sjfrickeca9a4802022-08-10 14:27:51 +09001809 assert(indirect_state != NULL);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001810 VkPipeline validation_pipeline;
Tony-LunarG56f0d0f2022-08-17 12:04:17 -06001811 AllocatePreDrawValidationResources(output_block, pre_draw_resources, cb_node->activeRenderPass.get()->renderPass(),
1812 &validation_pipeline, indirect_state);
Tony-LunarG2c6d57f2021-04-13 10:07:15 -06001813 if (aborted) return;
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001814
1815 // Save current graphics pipeline state
1816 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
Jeremy Gebben9f537102021-10-05 16:37:12 -06001817 restorable_state.Create(cb_node.get(), VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001818
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001819 // Save parameters for error message
sjfrickeca9a4802022-08-10 14:27:51 +09001820 pre_draw_resources.buffer = indirect_state->buffer;
1821 pre_draw_resources.offset = indirect_state->offset;
1822 pre_draw_resources.stride = indirect_state->stride;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001823
sjfricke43b340c2022-08-04 22:18:38 +09001824 uint32_t push_constants[pre_draw_resources.push_constant_words] = {};
sfricke-samsung85584a72021-09-30 21:43:38 -07001825 if (cmd_type == CMD_DRAWINDIRECTCOUNT || cmd_type == CMD_DRAWINDIRECTCOUNTKHR || cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT ||
1826 cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNTKHR) {
sjfricke43b340c2022-08-04 22:18:38 +09001827 // Validate count buffer
sjfrickeca9a4802022-08-10 14:27:51 +09001828 if (indirect_state->count_buffer_offset > std::numeric_limits<uint32_t>::max()) {
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001829 ReportSetupProblem(device,
1830 "Count buffer offset is larger than can be contained in an unsigned int. Aborting GPU-AV");
1831 aborted = true;
1832 return;
1833 }
1834
1835 // Buffer size must be >= (stride * (drawCount - 1) + offset + sizeof(VkDrawIndirectCommand))
1836 uint32_t struct_size;
sfricke-samsung85584a72021-09-30 21:43:38 -07001837 if (cmd_type == CMD_DRAWINDIRECTCOUNT || cmd_type == CMD_DRAWINDIRECTCOUNTKHR) {
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001838 struct_size = sizeof(VkDrawIndirectCommand);
1839 } else {
sfricke-samsung85584a72021-09-30 21:43:38 -07001840 assert(cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNT || cmd_type == CMD_DRAWINDEXEDINDIRECTCOUNTKHR);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001841 struct_size = sizeof(VkDrawIndexedIndirectCommand);
1842 }
sjfrickeca9a4802022-08-10 14:27:51 +09001843 auto buffer_state = Get<BUFFER_STATE>(indirect_state->buffer);
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001844 uint32_t max_count;
1845 uint64_t bufsize = buffer_state->createInfo.size;
sjfrickeca9a4802022-08-10 14:27:51 +09001846 uint64_t first_command_bytes = struct_size + indirect_state->offset;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001847 if (first_command_bytes > bufsize) {
1848 max_count = 0;
1849 } else {
sjfrickeca9a4802022-08-10 14:27:51 +09001850 max_count = 1 + static_cast<uint32_t>(std::floor(((bufsize - first_command_bytes) / indirect_state->stride)));
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001851 }
1852 pre_draw_resources.buf_size = buffer_state->createInfo.size;
1853
1854 assert(phys_dev_props.limits.maxDrawIndirectCount > 0);
sjfricke43b340c2022-08-04 22:18:38 +09001855 push_constants[0] = phys_dev_props.limits.maxDrawIndirectCount;
1856 push_constants[1] = max_count;
sjfrickeca9a4802022-08-10 14:27:51 +09001857 push_constants[2] = static_cast<uint32_t>((indirect_state->count_buffer_offset / sizeof(uint32_t)));
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001858 } else {
sjfricke43b340c2022-08-04 22:18:38 +09001859 // Validate buffer for firstInstance check instead of count buffer check
1860 push_constants[0] = 0;
sjfrickeca9a4802022-08-10 14:27:51 +09001861 push_constants[1] = indirect_state->draw_count;
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001862 if (cmd_type == CMD_DRAWINDIRECT) {
sjfricke43b340c2022-08-04 22:18:38 +09001863 push_constants[2] = static_cast<uint32_t>(
sjfrickeca9a4802022-08-10 14:27:51 +09001864 ((indirect_state->offset + offsetof(struct VkDrawIndirectCommand, firstInstance)) / sizeof(uint32_t)));
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001865 } else {
1866 assert(cmd_type == CMD_DRAWINDEXEDINDIRECT);
sjfricke43b340c2022-08-04 22:18:38 +09001867 push_constants[2] = static_cast<uint32_t>(
sjfrickeca9a4802022-08-10 14:27:51 +09001868 ((indirect_state->offset + offsetof(struct VkDrawIndexedIndirectCommand, firstInstance)) / sizeof(uint32_t)));
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001869 }
sjfrickeca9a4802022-08-10 14:27:51 +09001870 push_constants[3] = (indirect_state->stride / sizeof(uint32_t));
Tony-LunarG3723a3a2021-05-04 14:52:39 -06001871 }
Tony-LunarGf0d4e2b2021-04-14 11:52:28 -06001872
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001873 // Insert diagnostic draw
1874 DispatchCmdBindPipeline(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, validation_pipeline);
sjfricke43b340c2022-08-04 22:18:38 +09001875 DispatchCmdPushConstants(cmd_buffer, pre_draw_validation_state.pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0,
1876 sizeof(push_constants), push_constants);
1877 DispatchCmdBindDescriptorSets(cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pre_draw_validation_state.pipeline_layout, 0, 1,
1878 &pre_draw_resources.desc_set, 0, nullptr);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001879 DispatchCmdDraw(cmd_buffer, 3, 1, 0, 0);
1880
1881 // Restore the previous graphics pipeline state.
1882 restorable_state.Restore(cmd_buffer);
sjfrickeca9a4802022-08-10 14:27:51 +09001883 } else if (validate_dispatch_indirect && cmd_type == CMD_DISPATCHINDIRECT) {
1884 // Insert a dispatch that can examine some device memory right before the dispatch we're validating
1885 //
1886 // NOTE that this validation does not attempt to abort invalid api calls as most other validation does. A crash
1887 // or DEVICE_LOST resulting from the invalid call will prevent preceeding validation errors from being reported.
1888
1889 AllocatePreDispatchValidationResources(output_block, pre_dispatch_resources, indirect_state);
1890 if (aborted) return;
1891
1892 // Save current graphics pipeline state
1893 GPUAV_RESTORABLE_PIPELINE_STATE restorable_state;
1894 restorable_state.Create(cb_node.get(), VK_PIPELINE_BIND_POINT_COMPUTE);
1895
1896 // Save parameters for error message
1897 pre_dispatch_resources.buffer = indirect_state->buffer;
1898 pre_dispatch_resources.offset = indirect_state->offset;
1899
1900 uint32_t push_constants[pre_dispatch_resources.push_constant_words] = {};
1901 push_constants[0] = phys_dev_props.limits.maxComputeWorkGroupCount[0];
1902 push_constants[1] = phys_dev_props.limits.maxComputeWorkGroupCount[1];
1903 push_constants[2] = phys_dev_props.limits.maxComputeWorkGroupCount[2];
1904 push_constants[3] = static_cast<uint32_t>((indirect_state->offset / sizeof(uint32_t)));
1905
1906 // Insert diagnostic dispatch
1907 DispatchCmdBindPipeline(cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pre_dispatch_validation_state.pipeline);
1908 DispatchCmdPushConstants(cmd_buffer, pre_dispatch_validation_state.pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
1909 sizeof(push_constants), push_constants);
1910 DispatchCmdBindDescriptorSets(cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pre_dispatch_validation_state.pipeline_layout, 0,
1911 1, &pre_dispatch_resources.desc_set, 0, nullptr);
1912 DispatchCmdDispatch(cmd_buffer, 1, 1, 1);
1913
1914 // Restore the previous compute pipeline state.
1915 restorable_state.Restore(cmd_buffer);
Tony-LunarGa3ec16c2021-04-06 12:19:57 -06001916 }
1917
Tony-LunarGe29097a2020-12-03 10:59:19 -07001918 bool has_buffers = false;
Tony-LunarG81efe392019-03-07 15:43:27 -07001919 // Figure out how much memory we need for the input block based on how many sets and bindings there are
1920 // and how big each of the bindings is
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001921 if (number_of_sets > 0 && (descriptor_indexing || buffer_oob_enabled)) {
Tony-LunarG81efe392019-03-07 15:43:27 -07001922 uint32_t descriptor_count = 0; // Number of descriptors, including all array elements
1923 uint32_t binding_count = 0; // Number of bindings based on the max binding number used
John Zulauf79f06582021-02-27 18:38:39 -07001924 for (const auto &s : state.per_set) {
Jeff Bolzb1fc0732019-08-11 20:16:49 -05001925 auto desc = s.bound_descriptor_set;
Tony-LunarGd9224b12019-09-11 11:43:04 -06001926 if (desc && (desc->GetBindingCount() > 0)) {
Tony-LunarGa77cade2019-03-06 10:49:22 -07001927 binding_count += desc->GetLayout()->GetMaxBinding() + 1;
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06001928 for (const auto &binding : *desc) {
Tony-LunarG7564b382019-08-21 10:11:35 -06001929 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline uniform
1930 // blocks
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06001931 if (binding->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT) {
Tony-LunarG7564b382019-08-21 10:11:35 -06001932 descriptor_count++;
Mark Lobodzinskiafa7cb82020-01-29 16:49:36 -07001933 LogWarning(device, "UNASSIGNED-GPU-Assisted Validation Warning",
1934 "VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT descriptors will not be validated by GPU assisted "
1935 "validation");
Tony-LunarGa77cade2019-03-06 10:49:22 -07001936 } else {
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06001937 descriptor_count += binding->count;
Tony-LunarGa77cade2019-03-06 10:49:22 -07001938 }
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06001939 if (!has_buffers && (binding->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ||
1940 binding->type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC ||
1941 binding->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
1942 binding->type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
1943 binding->type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
1944 binding->type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07001945 has_buffers = true;
Tony-LunarGa77cade2019-03-06 10:49:22 -07001946 }
Tony-LunarGc28e28a2020-08-14 10:37:48 -06001947 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001948 }
1949 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001950
Tony-LunarGe29097a2020-12-03 10:59:19 -07001951 if (descriptor_indexing || has_buffers) {
1952 // Note that the size of the input buffer is dependent on the maximum binding number, which
1953 // can be very large. This is because for (set = s, binding = b, index = i), the validation
1954 // code is going to dereference Input[ i + Input[ b + Input[ s + Input[ Input[0] ] ] ] ] to
1955 // see if descriptors have been written. In gpu_validation.md, we note this and advise
1956 // using densely packed bindings as a best practice when using gpu-av with descriptor indexing
1957 uint32_t words_needed;
1958 if (descriptor_indexing) {
1959 words_needed = 1 + (number_of_sets * 2) + (binding_count * 2) + descriptor_count;
1960 } else {
1961 words_needed = 1 + number_of_sets + binding_count + descriptor_count;
1962 }
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001963 buffer_info.size = words_needed * 4;
Tony-LunarG20d18a72022-04-19 11:01:47 -06001964 alloc_info.pool = VK_NULL_HANDLE;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001965 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &di_input_block.buffer, &di_input_block.allocation,
1966 nullptr);
Tony-LunarGe29097a2020-12-03 10:59:19 -07001967 if (result != VK_SUCCESS) {
Tony-LunarGa2aa78b2022-04-19 08:41:38 -06001968 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.", true);
Tony-LunarGe29097a2020-12-03 10:59:19 -07001969 aborted = true;
1970 return;
1971 }
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001972
Tony-LunarGe29097a2020-12-03 10:59:19 -07001973 // Populate input buffer first with the sizes of every descriptor in every set, then with whether
1974 // each element of each descriptor has been written or not. See gpu_validation.md for a more thourough
1975 // outline of the input buffer format
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001976 result = vmaMapMemory(vmaAllocator, di_input_block.allocation, reinterpret_cast<void **>(&data_ptr));
1977 memset(data_ptr, 0, static_cast<size_t>(buffer_info.size));
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07001978
Tony-LunarGe29097a2020-12-03 10:59:19 -07001979 // Descriptor indexing needs the number of descriptors at each binding.
1980 if (descriptor_indexing) {
1981 // Pointer to a sets array that points into the sizes array
1982 uint32_t *sets_to_sizes = data_ptr + 1;
1983 // Pointer to the sizes array that contains the array size of the descriptor at each binding
1984 uint32_t *sizes = sets_to_sizes + number_of_sets;
1985 // Pointer to another sets array that points into the bindings array that points into the written array
1986 uint32_t *sets_to_bindings = sizes + binding_count;
1987 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
1988 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
1989 // Index of the next entry in the written array to be updated
1990 uint32_t written_index = 1 + (number_of_sets * 2) + (binding_count * 2);
1991 uint32_t bind_counter = number_of_sets + 1;
1992 // Index of the start of the sets_to_bindings array
1993 data_ptr[0] = number_of_sets + binding_count + 1;
1994
John Zulauf79f06582021-02-27 18:38:39 -07001995 for (const auto &s : state.per_set) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07001996 auto desc = s.bound_descriptor_set;
1997 if (desc && (desc->GetBindingCount() > 0)) {
1998 auto layout = desc->GetLayout();
Tony-LunarGe29097a2020-12-03 10:59:19 -07001999 // For each set, fill in index of its bindings sizes in the sizes array
2000 *sets_to_sizes++ = bind_counter;
2001 // For each set, fill in the index of its bindings in the bindings_to_written array
2002 *sets_to_bindings++ = bind_counter + number_of_sets + binding_count;
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06002003 for (auto &binding : *desc) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002004 // For each binding, fill in its size in the sizes array
2005 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2006 // uniform blocks
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06002007 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == binding->type) {
2008 sizes[binding->binding] = 1;
Tony-LunarGe29097a2020-12-03 10:59:19 -07002009 } else {
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06002010 sizes[binding->binding] = binding->count;
Tony-LunarGe29097a2020-12-03 10:59:19 -07002011 }
2012 // Fill in the starting index for this binding in the written array in the bindings_to_written array
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06002013 bindings_to_written[binding->binding] = written_index;
Tony-LunarGe29097a2020-12-03 10:59:19 -07002014
2015 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2016 // uniform blocks
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06002017 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == binding->type) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002018 data_ptr[written_index++] = UINT_MAX;
2019 continue;
2020 }
2021
Jeremy Gebbenf4816f72022-07-15 08:56:06 -06002022 if ((binding->binding_flags & VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT) != 0) {
2023 di_input_block.update_at_submit[written_index] = binding.get();
2024 } else {
2025 SetBindingState(data_ptr, written_index, binding.get());
Tony-LunarGe29097a2020-12-03 10:59:19 -07002026 }
Jeremy Gebbenf4816f72022-07-15 08:56:06 -06002027 written_index += binding->count;
Tony-LunarGe29097a2020-12-03 10:59:19 -07002028 }
2029 auto last = desc->GetLayout()->GetMaxBinding();
2030 bindings_to_written += last + 1;
2031 bind_counter += last + 1;
2032 sizes += last + 1;
2033 } else {
2034 *sets_to_sizes++ = 0;
2035 *sets_to_bindings++ = 0;
2036 }
2037 }
2038 } else {
2039 // If no descriptor indexing, we don't need number of descriptors at each binding, so
2040 // no sets_to_sizes or sizes arrays, just sets_to_bindings, bindings_to_written and written_index
2041
2042 // Pointer to sets array that points into the bindings array that points into the written array
2043 uint32_t *sets_to_bindings = data_ptr + 1;
2044 // Pointer to the bindings array that points at the start of the writes in the writes array for each binding
2045 uint32_t *bindings_to_written = sets_to_bindings + number_of_sets;
2046 // Index of the next entry in the written array to be updated
2047 uint32_t written_index = 1 + number_of_sets + binding_count;
2048 uint32_t bind_counter = number_of_sets + 1;
2049 data_ptr[0] = 1;
2050
John Zulauf79f06582021-02-27 18:38:39 -07002051 for (const auto &s : state.per_set) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002052 auto desc = s.bound_descriptor_set;
2053 if (desc && (desc->GetBindingCount() > 0)) {
2054 auto layout = desc->GetLayout();
Tony-LunarGe29097a2020-12-03 10:59:19 -07002055 *sets_to_bindings++ = bind_counter;
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06002056 for (auto &binding : *desc) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002057 // Fill in the starting index for this binding in the written array in the bindings_to_written array
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06002058 bindings_to_written[binding->binding] = written_index;
Tony-LunarGe29097a2020-12-03 10:59:19 -07002059
2060 // Shader instrumentation is tracking inline uniform blocks as scalers. Don't try to validate inline
2061 // uniform blocks
Jeremy Gebben1b9fdb82022-06-15 15:31:32 -06002062 if (VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT == binding->type) {
Tony-LunarGe29097a2020-12-03 10:59:19 -07002063 data_ptr[written_index++] = UINT_MAX;
2064 continue;
2065 }
2066
Jeremy Gebbenf4816f72022-07-15 08:56:06 -06002067 // note that VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT is part of descriptor indexing
2068 SetBindingState(data_ptr, written_index, binding.get());
2069 written_index += binding->count;
Tony-LunarGe29097a2020-12-03 10:59:19 -07002070 }
2071 auto last = desc->GetLayout()->GetMaxBinding();
2072 bindings_to_written += last + 1;
2073 bind_counter += last + 1;
2074 } else {
2075 *sets_to_bindings++ = 0;
2076 }
2077 }
2078 }
2079 vmaUnmapMemory(vmaAllocator, di_input_block.allocation);
2080
2081 di_input_desc_buffer_info.range = (words_needed * 4);
2082 di_input_desc_buffer_info.buffer = di_input_block.buffer;
2083 di_input_desc_buffer_info.offset = 0;
2084
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06002085 desc_writes[1] = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarGe29097a2020-12-03 10:59:19 -07002086 desc_writes[1].dstBinding = 1;
2087 desc_writes[1].descriptorCount = 1;
2088 desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2089 desc_writes[1].pBufferInfo = &di_input_desc_buffer_info;
2090 desc_writes[1].dstSet = desc_sets[0];
2091
2092 desc_count = 2;
2093 }
Tony-LunarG0e564722019-03-19 16:09:14 -06002094 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002095
sfricke-samsung45996a42021-09-16 13:45:27 -07002096 if ((IsExtEnabled(device_extensions.vk_ext_buffer_device_address) ||
2097 IsExtEnabled(device_extensions.vk_khr_buffer_device_address)) &&
Jeremy Gebbenb0171bb2022-03-18 13:46:13 -06002098 shaderInt64 && enabled_features.core12.bufferDeviceAddress) {
2099 auto address_ranges = GetBufferAddressRanges();
2100 if (address_ranges.size() > 0) {
2101 // Example BDA input buffer assuming 2 buffers using BDA:
2102 // Word 0 | Index of start of buffer sizes (in this case 5)
2103 // Word 1 | 0x0000000000000000
2104 // Word 2 | Device Address of first buffer (Addresses sorted in ascending order)
2105 // Word 3 | Device Address of second buffer
2106 // Word 4 | 0xffffffffffffffff
2107 // Word 5 | 0 (size of pretend buffer at word 1)
2108 // Word 6 | Size in bytes of first buffer
2109 // Word 7 | Size in bytes of second buffer
2110 // Word 8 | 0 (size of pretend buffer in word 4)
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002111
Jeremy Gebbenb0171bb2022-03-18 13:46:13 -06002112 uint32_t num_buffers = static_cast<uint32_t>(address_ranges.size());
2113 uint32_t words_needed = (num_buffers + 3) + (num_buffers + 2);
Jeremy Gebbenb0171bb2022-03-18 13:46:13 -06002114 buffer_info.size = words_needed * 8; // 64 bit words
Tony-LunarG20d18a72022-04-19 11:01:47 -06002115 alloc_info.pool = VK_NULL_HANDLE;
Jeremy Gebbenb0171bb2022-03-18 13:46:13 -06002116 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &bda_input_block.buffer, &bda_input_block.allocation,
2117 nullptr);
2118 if (result != VK_SUCCESS) {
Tony-LunarGa2aa78b2022-04-19 08:41:38 -06002119 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.", true);
Jeremy Gebbenb0171bb2022-03-18 13:46:13 -06002120 aborted = true;
2121 return;
2122 }
2123 uint64_t *bda_data;
2124 result = vmaMapMemory(vmaAllocator, bda_input_block.allocation, reinterpret_cast<void **>(&bda_data));
2125 uint32_t address_index = 1;
2126 uint32_t size_index = 3 + num_buffers;
2127 memset(bda_data, 0, static_cast<size_t>(buffer_info.size));
2128 bda_data[0] = size_index; // Start of buffer sizes
2129 bda_data[address_index++] = 0; // NULL address
2130 bda_data[size_index++] = 0;
2131
2132 for (const auto &range : address_ranges) {
2133 bda_data[address_index++] = range.begin;
2134 bda_data[size_index++] = range.end - range.begin;
2135 }
2136 bda_data[address_index] = UINTPTR_MAX;
2137 bda_data[size_index] = 0;
2138 vmaUnmapMemory(vmaAllocator, bda_input_block.allocation);
2139
2140 bda_input_desc_buffer_info.range = (words_needed * 8);
2141 bda_input_desc_buffer_info.buffer = bda_input_block.buffer;
2142 bda_input_desc_buffer_info.offset = 0;
2143
2144 desc_writes[desc_count] = LvlInitStruct<VkWriteDescriptorSet>();
2145 desc_writes[desc_count].dstBinding = 2;
2146 desc_writes[desc_count].descriptorCount = 1;
2147 desc_writes[desc_count].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2148 desc_writes[desc_count].pBufferInfo = &bda_input_desc_buffer_info;
2149 desc_writes[desc_count].dstSet = desc_sets[0];
2150 desc_count++;
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002151 }
Tony-LunarG8eb5a002019-07-25 16:49:00 -06002152 }
2153
Tony-LunarGb2501d22019-01-28 09:59:13 -07002154 // Write the descriptor
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002155 output_desc_buffer_info.buffer = output_block.buffer;
2156 output_desc_buffer_info.offset = 0;
Tony-LunarGb2501d22019-01-28 09:59:13 -07002157
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06002158 desc_writes[0] = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarG1b2e0c32019-02-07 17:13:27 -07002159 desc_writes[0].descriptorCount = 1;
2160 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2161 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
2162 desc_writes[0].dstSet = desc_sets[0];
2163 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002164
locke-lunargb8d7a7a2020-10-25 16:01:52 -06002165 if (pipeline_state) {
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -07002166 const auto &pipeline_layout = pipeline_state->PipelineLayoutState();
2167 if ((pipeline_layout->set_layouts.size() <= desc_set_bind_index) && !pipeline_layout->Destroyed()) {
2168 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_layout->layout(), desc_set_bind_index, 1,
Tony-LunarG99b880b2019-09-26 11:19:52 -06002169 desc_sets.data(), 0, nullptr);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002170 }
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -07002171 if (pipeline_layout->Destroyed()) {
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002172 ReportSetupProblem(device, "Pipeline layout has been destroyed, aborting GPU-AV");
2173 aborted = true;
2174 } else {
2175 // Record buffer and memory info in CB state tracking
sjfrickeca9a4802022-08-10 14:27:51 +09002176 cb_node->gpuav_buffer_list.emplace_back(output_block, di_input_block, bda_input_block, pre_draw_resources,
2177 pre_dispatch_resources, desc_sets[0], desc_pool, bind_point, cmd_type);
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002178 }
Tony-LunarGb2501d22019-01-28 09:59:13 -07002179 } else {
Mark Lobodzinskia8151b02020-02-27 13:38:08 -07002180 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG9de6e5f2020-06-22 13:02:48 -06002181 aborted = true;
2182 }
2183 if (aborted) {
Tony-LunarG99b880b2019-09-26 11:19:52 -06002184 vmaDestroyBuffer(vmaAllocator, di_input_block.buffer, di_input_block.allocation);
2185 vmaDestroyBuffer(vmaAllocator, bda_input_block.buffer, bda_input_block.allocation);
2186 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
Tony-LunarGb2501d22019-01-28 09:59:13 -07002187 return;
2188 }
2189}
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06002190
2191std::shared_ptr<CMD_BUFFER_STATE> GpuAssisted::CreateCmdBufferState(VkCommandBuffer cb,
2192 const VkCommandBufferAllocateInfo *pCreateInfo,
Jeremy Gebbencd7fa282021-10-27 10:25:32 -06002193 const COMMAND_POOL_STATE *pool) {
Jeremy Gebben135550d2022-03-21 07:15:07 -06002194 return std::static_pointer_cast<CMD_BUFFER_STATE>(std::make_shared<gpuav_state::CommandBuffer>(this, cb, pCreateInfo, pool));
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06002195}
2196
Jeremy Gebben135550d2022-03-21 07:15:07 -06002197gpuav_state::CommandBuffer::CommandBuffer(GpuAssisted *ga, VkCommandBuffer cb, const VkCommandBufferAllocateInfo *pCreateInfo,
2198 const COMMAND_POOL_STATE *pool)
Jeremy Gebben5ca80b32022-04-11 10:58:39 -06002199 : gpu_utils_state::CommandBuffer(ga, cb, pCreateInfo, pool) {}
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06002200
Jeremy Gebben135550d2022-03-21 07:15:07 -06002201void gpuav_state::CommandBuffer::Reset() {
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06002202 CMD_BUFFER_STATE::Reset();
2203 auto gpuav = static_cast<GpuAssisted *>(dev_data);
2204 // Free the device memory and descriptor set(s) associated with a command buffer.
2205 if (gpuav->aborted) {
2206 return;
2207 }
2208 for (auto &buffer_info : gpuav_buffer_list) {
2209 gpuav->DestroyBuffer(buffer_info);
2210 }
2211 gpuav_buffer_list.clear();
2212
2213 for (auto &as_validation_buffer_info : as_validation_buffers) {
2214 gpuav->DestroyBuffer(as_validation_buffer_info);
2215 }
2216 as_validation_buffers.clear();
2217}