blob: 3ea9f2fa488da5cd2d45d5fb64b49ec55f853ea6 [file] [log] [blame]
Tony-LunarGfb2ab872021-01-13 15:17:15 -07001/* Copyright (c) 2020-2021 The Khronos Group Inc.
2 * Copyright (c) 2020-2021 Valve Corporation
3 * Copyright (c) 2020-2021 LunarG, Inc.
Tony-LunarG04717522019-10-17 10:41:17 -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 *
17 * Author: Tony Barbour <tony@lunarg.com>
18 */
19
Tony-LunarGb5fae462020-03-05 12:43:25 -070020#include "debug_printf.h"
Tony-LunarG04717522019-10-17 10:41:17 -060021#include "spirv-tools/optimizer.hpp"
22#include "spirv-tools/instrument.hpp"
23#include <iostream>
Tony-LunarG04717522019-10-17 10:41:17 -060024#include "layer_chassis_dispatch.h"
Jeremy Gebbena3705f42021-01-19 16:47:43 -070025#include "sync_utils.h"
Jeremy Gebben159b3cc2021-06-03 09:09:03 -060026#include "cmd_buffer_state.h"
Tony-LunarG04717522019-10-17 10:41:17 -060027
Tony-LunarG04717522019-10-17 10:41:17 -060028static const VkShaderStageFlags kShaderStageAllRayTracing =
29 VK_SHADER_STAGE_ANY_HIT_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV | VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV |
30 VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV | VK_SHADER_STAGE_RAYGEN_BIT_NV;
31
Tony-LunarG5af54eb2020-03-27 15:32:51 -060032// Convenience function for reporting problems with setting up Debug Printf.
Tony-LunarG1dce2392019-10-23 16:49:29 -060033template <typename T>
Tony-LunarGb5fae462020-03-05 12:43:25 -070034void DebugPrintf::ReportSetupProblem(T object, const char *const specific_message) const {
Tony-LunarG5af54eb2020-03-27 15:32:51 -060035 LogError(object, "UNASSIGNED-DEBUG-PRINTF ", "Detail: (%s)", specific_message);
Tony-LunarG04717522019-10-17 10:41:17 -060036}
37
38// Turn on necessary device features.
Tony-LunarGb5fae462020-03-05 12:43:25 -070039void DebugPrintf::PreCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info,
40 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
Mark Lobodzinskib588cd42020-09-30 11:03:34 -060041 void *modified_create_info) {
Tony-LunarG04717522019-10-17 10:41:17 -060042 DispatchGetPhysicalDeviceFeatures(gpu, &supported_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -060043 VkPhysicalDeviceFeatures features = {};
44 features.vertexPipelineStoresAndAtomics = true;
45 features.fragmentStoresAndAtomics = true;
Mark Lobodzinskib588cd42020-09-30 11:03:34 -060046 UtilPreCallRecordCreateDevice(gpu, reinterpret_cast<safe_VkDeviceCreateInfo *>(modified_create_info), supported_features,
47 features);
Tony-LunarG04717522019-10-17 10:41:17 -060048}
Tony-LunarG1dce2392019-10-23 16:49:29 -060049
Tony-LunarG04717522019-10-17 10:41:17 -060050// Perform initializations that can be done at Create Device time.
Tony-LunarGb5fae462020-03-05 12:43:25 -070051void DebugPrintf::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
52 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -060053 ValidationStateTracker::PostCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice, result);
54
55 ValidationObject *device_object = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
56 ValidationObject *validation_data = GetValidationObject(device_object->object_dispatch, this->container_type);
Tony-LunarGb5fae462020-03-05 12:43:25 -070057 DebugPrintf *device_debug_printf = static_cast<DebugPrintf *>(validation_data);
58 device_debug_printf->physicalDevice = physicalDevice;
59 device_debug_printf->device = *pDevice;
Tony-LunarG43416b42019-10-31 16:47:24 -060060
61 const char *size_string = getLayerOption("khronos_validation.printf_buffer_size");
Tony-LunarGb5fae462020-03-05 12:43:25 -070062 device_debug_printf->output_buffer_size = *size_string ? atoi(size_string) : 1024;
Tony-LunarG43416b42019-10-31 16:47:24 -060063 const char *verbose_string = getLayerOption("khronos_validation.printf_verbose");
Tony-LunarGb5fae462020-03-05 12:43:25 -070064 device_debug_printf->verbose = *verbose_string ? !strcmp(verbose_string, "true") : false;
Tony-LunarG43416b42019-10-31 16:47:24 -060065 const char *stdout_string = getLayerOption("khronos_validation.printf_to_stdout");
Tony-LunarGb5fae462020-03-05 12:43:25 -070066 device_debug_printf->use_stdout = *stdout_string ? !strcmp(stdout_string, "true") : false;
67 if (getenv("DEBUG_PRINTF_TO_STDOUT")) device_debug_printf->use_stdout = true;
Tony-LunarG04717522019-10-17 10:41:17 -060068
Tony-LunarGb5fae462020-03-05 12:43:25 -070069 if (device_debug_printf->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Tony-LunarGbbbed672020-03-04 10:51:11 -070070 ReportSetupProblem(device, "Debug Printf requires Vulkan 1.1 or later. Debug Printf disabled.");
Tony-LunarGb5fae462020-03-05 12:43:25 -070071 device_debug_printf->aborted = true;
Tony-LunarG04717522019-10-17 10:41:17 -060072 return;
73 }
74
75 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Tony-LunarG1dce2392019-10-23 16:49:29 -060076 ReportSetupProblem(device,
Tony-LunarGbbbed672020-03-04 10:51:11 -070077 "Debug Printf requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
78 "Debug Printf disabled.");
Tony-LunarGb5fae462020-03-05 12:43:25 -070079 device_debug_printf->aborted = true;
Tony-LunarG04717522019-10-17 10:41:17 -060080 return;
81 }
Tony-LunarG9586e732020-03-04 10:50:30 -070082
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -060083 if (enabled[gpu_validation]) {
Tony-LunarG9586e732020-03-04 10:50:30 -070084 ReportSetupProblem(device,
85 "Debug Printf cannot be enabled when gpu assisted validation is enabled. "
86 "Debug Printf disabled.");
Tony-LunarGb5fae462020-03-05 12:43:25 -070087 device_debug_printf->aborted = true;
Tony-LunarG9586e732020-03-04 10:50:30 -070088 return;
89 }
90
Tony-LunarG1dce2392019-10-23 16:49:29 -060091 std::vector<VkDescriptorSetLayoutBinding> bindings;
92 VkDescriptorSetLayoutBinding binding = {3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
Tony-LunarGc7ed2082020-06-11 14:00:04 -060093 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_MESH_BIT_NV |
94 VK_SHADER_STAGE_TASK_BIT_NV | VK_SHADER_STAGE_COMPUTE_BIT |
95 kShaderStageAllRayTracing,
Tony-LunarG1dce2392019-10-23 16:49:29 -060096 NULL};
97 bindings.push_back(binding);
Tony-LunarGb5fae462020-03-05 12:43:25 -070098 UtilPostCallRecordCreateDevice(pCreateInfo, bindings, device_debug_printf, device_debug_printf->phys_dev_props);
Tony-LunarG04717522019-10-17 10:41:17 -060099}
100
Tony-LunarGb5fae462020-03-05 12:43:25 -0700101void DebugPrintf::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
102 UtilPreCallRecordDestroyDevice(this);
Tony-LunarG0a863bc2020-09-16 09:50:04 -0600103 ValidationStateTracker::PreCallRecordDestroyDevice(device, pAllocator);
104 // State Tracker can end up making vma calls through callbacks - don't destroy allocator until ST is done
105 if (vmaAllocator) {
106 vmaDestroyAllocator(vmaAllocator);
107 }
108 desc_set_manager.reset();
Tony-LunarG04717522019-10-17 10:41:17 -0600109}
110
111// Modify the pipeline layout to include our debug descriptor set and any needed padding with the dummy descriptor set.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700112void DebugPrintf::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
113 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
114 void *cpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600115 if (aborted) {
116 return;
117 }
118
119 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
120
121 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
122 std::ostringstream strm;
123 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Tony-LunarGbbbed672020-03-04 10:51:11 -0700124 << "Application has too many descriptor sets in the pipeline layout to continue with debug printf. "
Tony-LunarG04717522019-10-17 10:41:17 -0600125 << "Not modifying the pipeline layout. "
126 << "Instrumented shaders are replaced with non-instrumented shaders.";
Tony-LunarG1dce2392019-10-23 16:49:29 -0600127 ReportSetupProblem(device, strm.str().c_str());
Tony-LunarG04717522019-10-17 10:41:17 -0600128 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700129 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Tony-LunarG04717522019-10-17 10:41:17 -0600130 }
131}
132
Tony-LunarGb5fae462020-03-05 12:43:25 -0700133void DebugPrintf::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
134 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
135 VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -0600136 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
137 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600138 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600139 aborted = true;
140 }
141}
142
143// Free the device memory and descriptor set associated with a command buffer.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700144void DebugPrintf::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG04717522019-10-17 10:41:17 -0600145 if (aborted) {
146 return;
147 }
Tony-LunarGb5fae462020-03-05 12:43:25 -0700148 auto debug_printf_buffer_list = GetBufferInfo(commandBuffer);
John Zulauf79f06582021-02-27 18:38:39 -0700149 for (const auto &buffer_info : debug_printf_buffer_list) {
Tony-LunarG04717522019-10-17 10:41:17 -0600150 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
151 if (buffer_info.desc_set != VK_NULL_HANDLE) {
152 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
153 }
154 }
155 command_buffer_map.erase(commandBuffer);
156}
157
158// Just gives a warning about a possible deadlock.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700159bool DebugPrintf::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
160 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
161 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
162 uint32_t bufferMemoryBarrierCount,
163 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
164 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG04717522019-10-17 10:41:17 -0600165 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600166 ReportSetupProblem(commandBuffer,
167 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
Tony-LunarGbbbed672020-03-04 10:51:11 -0700168 "Debug Printf waits on queue completion. "
Tony-LunarG1dce2392019-10-23 16:49:29 -0600169 "This wait could block the host's signaling of this event, resulting in deadlock.");
Tony-LunarG04717522019-10-17 10:41:17 -0600170 }
171 return false;
172}
173
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700174bool DebugPrintf::PreCallValidateCmdWaitEvents2KHR(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
175 const VkDependencyInfoKHR *pDependencyInfos) const {
176 VkPipelineStageFlags2KHR srcStageMask = 0;
177
178 for (uint32_t i = 0; i < eventCount; i++) {
179 auto stage_masks = sync_utils::GetGlobalStageMasks(pDependencyInfos[i]);
180 srcStageMask = stage_masks.src;
181 }
182
183 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
184 ReportSetupProblem(commandBuffer,
185 "CmdWaitEvents2KHR recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
186 "Debug Printf waits on queue completion. "
187 "This wait could block the host's signaling of this event, resulting in deadlock.");
188 }
189 return false;
190}
191
Tony-LunarGb5fae462020-03-05 12:43:25 -0700192void DebugPrintf::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
193 const VkGraphicsPipelineCreateInfo *pCreateInfos,
194 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
195 void *cgpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600196 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
197 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700198 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
199 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600200 cgpl_state->printf_create_infos = new_pipeline_create_infos;
201 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->printf_create_infos.data());
202}
203
Tony-LunarGb5fae462020-03-05 12:43:25 -0700204void DebugPrintf::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
205 const VkComputePipelineCreateInfo *pCreateInfos,
206 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
207 void *ccpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600208 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
209 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700210 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
211 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600212 ccpl_state->printf_create_infos = new_pipeline_create_infos;
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600213 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->printf_create_infos.data());
Tony-LunarG04717522019-10-17 10:41:17 -0600214}
215
Tony-LunarGb5fae462020-03-05 12:43:25 -0700216void DebugPrintf::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
217 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
218 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
219 void *crtpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600220 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
221 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700222 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
223 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600224 crtpl_state->printf_create_infos = new_pipeline_create_infos;
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600225 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->printf_create_infos.data());
Tony-LunarG04717522019-10-17 10:41:17 -0600226}
227
sourav parmarcd5fb182020-07-17 12:58:44 -0700228void DebugPrintf::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
229 VkPipelineCache pipelineCache, uint32_t count,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700230 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
231 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
232 void *crtpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600233 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
234 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700235 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
236 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600237 crtpl_state->printf_create_infos = new_pipeline_create_infos;
238 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->printf_create_infos.data());
Tony-LunarG04717522019-10-17 10:41:17 -0600239}
Tony-LunarG04717522019-10-17 10:41:17 -0600240
Tony-LunarGb5fae462020-03-05 12:43:25 -0700241void DebugPrintf::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
242 const VkGraphicsPipelineCreateInfo *pCreateInfos,
243 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
244 VkResult result, void *cgpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600245 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
246 pPipelines, result, cgpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600247 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
248 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, cgpl_state->printf_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -0700249 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600250}
251
Tony-LunarGb5fae462020-03-05 12:43:25 -0700252void DebugPrintf::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
253 const VkComputePipelineCreateInfo *pCreateInfos,
254 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
255 VkResult result, void *ccpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600256 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
257 result, ccpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600258 create_compute_pipeline_api_state *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
259 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, ccpl_state->printf_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -0700260 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600261}
262
Tony-LunarGb5fae462020-03-05 12:43:25 -0700263void DebugPrintf::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
264 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
265 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
266 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600267 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarG04717522019-10-17 10:41:17 -0600268 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
269 pPipelines, result, crtpl_state_data);
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600270 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->printf_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -0700271 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600272}
273
Tony-LunarGfb2ab872021-01-13 15:17:15 -0700274void DebugPrintf::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
275 VkPipelineCache pipelineCache, uint32_t count,
276 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
277 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
278 VkResult result, void *crtpl_state_data) {
279 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
280 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesKHR(
281 device, deferredOperation, pipelineCache, count, pCreateInfos, pAllocator, pPipelines, result, crtpl_state_data);
282 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->printf_create_infos.data());
283 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
284}
285
Tony-LunarG04717522019-10-17 10:41:17 -0600286// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700287void DebugPrintf::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG04717522019-10-17 10:41:17 -0600288 for (auto it = shader_map.begin(); it != shader_map.end();) {
289 if (it->second.pipeline == pipeline) {
290 it = shader_map.erase(it);
291 } else {
292 ++it;
293 }
294 }
295 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
296}
297// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700298bool DebugPrintf::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
299 uint32_t *unique_shader_id) {
Tony-LunarG04717522019-10-17 10:41:17 -0600300 if (aborted) return false;
301 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
302
303 // Load original shader SPIR-V
304 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
305 new_pgm.clear();
306 new_pgm.reserve(num_words);
307 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
308
309 // Call the optimizer to instrument the shader.
310 // Use the unique_shader_module_id as a shader ID so we can look up its handle later in the shader_map.
311 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
312 using namespace spvtools;
Tony-LunarG8a51b7d2020-07-01 15:57:23 -0600313 spv_target_env target_env = PickSpirvEnv(api_version, (device_extensions.vk_khr_spirv_1_4 != kNotEnabled));
Tony-LunarGf29f77f2020-08-26 15:48:00 -0600314 spvtools::ValidatorOptions val_options;
315 AdjustValidatorOptions(device_extensions, enabled_features, val_options);
316 spvtools::OptimizerOptions opt_options;
317 opt_options.set_run_validator(true);
318 opt_options.set_validator_options(val_options);
Tony-LunarG04717522019-10-17 10:41:17 -0600319 Optimizer optimizer(target_env);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700320 const spvtools::MessageConsumer debug_printf_console_message_consumer =
Tony-LunarG79641702020-07-13 15:43:05 -0600321 [this](spv_message_level_t level, const char *, const spv_position_t &position, const char *message) -> void {
322 switch (level) {
323 case SPV_MSG_FATAL:
324 case SPV_MSG_INTERNAL_ERROR:
325 case SPV_MSG_ERROR:
326 this->LogError(this->device, "UNASSIGNED-Debug-Printf", "Error during shader instrumentation: line %zu: %s",
327 position.index, message);
328 break;
329 default:
330 break;
331 }
332 };
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700333 optimizer.SetMessageConsumer(debug_printf_console_message_consumer);
Tony-LunarG04717522019-10-17 10:41:17 -0600334 optimizer.RegisterPass(CreateInstDebugPrintfPass(desc_set_bind_index, unique_shader_module_id));
Tony-LunarGf29f77f2020-08-26 15:48:00 -0600335 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm, opt_options);
Tony-LunarG04717522019-10-17 10:41:17 -0600336 if (!pass) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600337 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Tony-LunarG04717522019-10-17 10:41:17 -0600338 }
339 *unique_shader_id = unique_shader_module_id++;
340 return pass;
341}
342// Create the instrumented shader data to provide to the driver.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700343void DebugPrintf::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
344 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
345 void *csm_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600346 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
347 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
348 if (pass) {
349 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
350 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
351 }
352}
Tony-LunarG04717522019-10-17 10:41:17 -0600353
354vartype vartype_lookup(char intype) {
355 switch (intype) {
356 case 'd':
357 case 'i':
358 return varsigned;
359 break;
360
361 case 'f':
362 case 'F':
363 case 'a':
364 case 'A':
365 case 'e':
366 case 'E':
367 case 'g':
368 case 'G':
369 return varfloat;
370 break;
371
372 case 'u':
373 case 'x':
374 case 'o':
375 default:
376 return varunsigned;
377 break;
378 }
379}
380
Tony-LunarGa19e31e2020-03-30 13:30:29 -0600381std::vector<DPFSubstring> DebugPrintf::ParseFormatString(const std::string format_string) {
382 const char types[] = {'d', 'i', 'o', 'u', 'x', 'X', 'a', 'A', 'e', 'E', 'f', 'F', 'g', 'G', 'v', '\0'};
Tony-LunarGb5fae462020-03-05 12:43:25 -0700383 std::vector<DPFSubstring> parsed_strings;
Tony-LunarG04717522019-10-17 10:41:17 -0600384 size_t pos = 0;
385 size_t begin = 0;
386 size_t percent = 0;
387
388 while (begin < format_string.length()) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700389 DPFSubstring substring;
Tony-LunarG04717522019-10-17 10:41:17 -0600390
391 // Find a percent sign
392 pos = percent = format_string.find_first_of('%', pos);
393 if (pos == std::string::npos) {
394 // End of the format string Push the rest of the characters
395 substring.string = format_string.substr(begin, format_string.length());
396 substring.needs_value = false;
397 parsed_strings.push_back(substring);
398 break;
399 }
400 pos++;
401 if (format_string[pos] == '%') {
402 pos++;
403 continue; // %% - skip it
404 }
405 // Find the type of the value
406 pos = format_string.find_first_of(types, pos);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700407 if (pos == format_string.npos) {
Tony-LunarG04717522019-10-17 10:41:17 -0600408 // This really shouldn't happen with a legal value string
409 pos = format_string.length();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700410 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600411 char tempstring[32];
412 int count = 0;
413 std::string specifier = {};
414
415 if (format_string[pos] == 'v') {
416 // Vector must be of size 2, 3, or 4
417 // and format %v<size><type>
418 specifier = format_string.substr(percent, pos - percent);
419 count = atoi(&format_string[pos + 1]);
420 pos += 2;
421
422 // skip v<count>, handle long
423 specifier.push_back(format_string[pos]);
424 if (format_string[pos + 1] == 'l') {
425 specifier.push_back('l');
426 pos++;
427 }
428
429 // Take the preceding characters, and the percent through the type
430 substring.string = format_string.substr(begin, percent - begin);
431 substring.string += specifier;
432 substring.needs_value = true;
433 substring.type = vartype_lookup(specifier.back());
434 parsed_strings.push_back(substring);
435
436 // Continue with a comma separated list
437 sprintf(tempstring, ", %s", specifier.c_str());
438 substring.string = tempstring;
439 for (int i = 0; i < (count - 1); i++) {
440 parsed_strings.push_back(substring);
441 }
442 } else {
443 // Single non-vector value
444 if (format_string[pos + 1] == 'l') pos++; // Save long size
445 substring.string = format_string.substr(begin, pos - begin + 1);
446 substring.needs_value = true;
447 substring.type = vartype_lookup(format_string[pos]);
448 parsed_strings.push_back(substring);
449 }
450 begin = pos + 1;
451 }
452 }
453 return parsed_strings;
454}
455
Tony-LunarGb5fae462020-03-05 12:43:25 -0700456std::string DebugPrintf::FindFormatString(std::vector<unsigned int> pgm, uint32_t string_id) {
Tony-LunarG04717522019-10-17 10:41:17 -0600457 std::string format_string;
458 SHADER_MODULE_STATE shader;
459 shader.words = pgm;
460 if (shader.words.size() > 0) {
John Zulauf79f06582021-02-27 18:38:39 -0700461 for (const auto &insn : shader) {
Tony-LunarG04717522019-10-17 10:41:17 -0600462 if (insn.opcode() == spv::OpString) {
463 uint32_t offset = insn.offset();
464 if (pgm[offset + 1] == string_id) {
465 format_string = reinterpret_cast<char *>(&pgm[offset + 2]);
466 break;
467 }
468 }
469 }
470 }
471
472 return format_string;
473}
474
Corentin Wallez171ac5e2020-03-31 16:09:05 +0200475// GCC and clang don't like using variables as format strings in sprintf.
476// #pragma GCC is recognized by both compilers
477#if defined(__GNUC__) || defined(__clang__)
Tony-LunarG04717522019-10-17 10:41:17 -0600478#pragma GCC diagnostic push
479#pragma GCC diagnostic ignored "-Wformat-security"
480#endif
481
Tony-LunarGb5fae462020-03-05 12:43:25 -0700482void snprintf_with_malloc(std::stringstream &shader_message, DPFSubstring substring, size_t needed, void *values) {
Tony-LunarG04717522019-10-17 10:41:17 -0600483 char *buffer = static_cast<char *>(malloc((needed + 1) * sizeof(char))); // Add 1 for terminator
484 if (substring.longval) {
485 snprintf(buffer, needed, substring.string.c_str(), substring.longval);
486 } else if (!substring.needs_value) {
487 snprintf(buffer, needed, substring.string.c_str());
488 } else {
489 switch (substring.type) {
490 case varunsigned:
491 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<uint32_t *>(values) - 1);
492 break;
493
494 case varsigned:
495 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<int32_t *>(values) - 1);
496 break;
497
498 case varfloat:
499 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<float *>(values) - 1);
500 break;
501 }
502 }
503 shader_message << buffer;
504 free(buffer);
505}
506
Tony-LunarG7de10e82020-11-24 11:31:55 -0700507void DebugPrintf::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, DPFBufferInfo &buffer_info,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700508 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Tony-LunarG04717522019-10-17 10:41:17 -0600509 // Word Content
510 // 0 Size of output record, including this word
511 // 1 Shader ID
512 // 2 Instruction Position
513 // 3 Stage Ordinal
514 // 4 Stage - specific Info Word 0
515 // 5 Stage - specific Info Word 1
516 // 6 Stage - specific Info Word 2
517 // 7 Printf Format String Id
518 // 8 Printf Values Word 0 (optional)
519 // 9 Printf Values Word 1 (optional)
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600520 uint32_t expect = debug_output_buffer[0];
521 if (!expect) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600522
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600523 uint32_t index = 1;
Tony-LunarG04717522019-10-17 10:41:17 -0600524 while (debug_output_buffer[index]) {
Tony-LunarG04717522019-10-17 10:41:17 -0600525 std::stringstream shader_message;
Tony-LunarG04717522019-10-17 10:41:17 -0600526 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
527 VkPipeline pipeline_handle = VK_NULL_HANDLE;
528 std::vector<unsigned int> pgm;
529
Tony-LunarGb5fae462020-03-05 12:43:25 -0700530 DPFOutputRecord *debug_record = reinterpret_cast<DPFOutputRecord *>(&debug_output_buffer[index]);
Tony-LunarG04717522019-10-17 10:41:17 -0600531 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
532 // by the instrumented shader.
533 auto it = shader_map.find(debug_record->shader_id);
534 if (it != shader_map.end()) {
535 shader_module_handle = it->second.shader_module;
536 pipeline_handle = it->second.pipeline;
537 pgm = it->second.pgm;
538 }
539 // Search through the shader source for the printf format string for this invocation
540 auto format_string = FindFormatString(pgm, debug_record->format_string_id);
541 // Break the format string into strings with 1 or 0 value
542 auto format_substrings = ParseFormatString(format_string);
543 void *values = static_cast<void *>(&debug_record->values);
544 const uint32_t static_size = 1024;
545 // Sprintf each format substring into a temporary string then add that to the message
546 for (auto &substring : format_substrings) {
547 char temp_string[static_size];
548 size_t needed = 0;
Tony-LunarGef469c92021-05-14 06:33:22 -0600549 std::vector<std::string> format_strings = { "%ul", "%lu", "%lx" };
550 size_t ul_pos = 0;
551 bool print_hex = true;
552 for (auto ul_string : format_strings) {
553 ul_pos = substring.string.find(ul_string);
554 if (ul_pos != std::string::npos) {
555 if (ul_string == "%lu") print_hex = false;
556 break;
557 }
558 }
Tony-LunarG04717522019-10-17 10:41:17 -0600559 if (ul_pos != std::string::npos) {
560 // Unsigned 64 bit value
561 substring.longval = *static_cast<uint64_t *>(values);
562 values = static_cast<uint64_t *>(values) + 1;
Tony-LunarGef469c92021-05-14 06:33:22 -0600563 if (print_hex) {
564 substring.string.replace(ul_pos + 1, 2, PRIx64);
565 } else {
566 substring.string.replace(ul_pos + 1, 2, PRIu64);
567 }
Tony-LunarG04717522019-10-17 10:41:17 -0600568 needed = snprintf(temp_string, static_size, substring.string.c_str(), substring.longval);
569 } else {
570 if (substring.needs_value) {
571 switch (substring.type) {
572 case varunsigned:
573 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<uint32_t *>(values));
574 break;
575
576 case varsigned:
577 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<int32_t *>(values));
578 break;
579
580 case varfloat:
581 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<float *>(values));
582 break;
583 }
584 values = static_cast<uint32_t *>(values) + 1;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700585 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600586 needed = snprintf(temp_string, static_size, substring.string.c_str());
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700587 }
Tony-LunarG04717522019-10-17 10:41:17 -0600588 }
589
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700590 if (needed < static_size) {
Tony-LunarG04717522019-10-17 10:41:17 -0600591 shader_message << temp_string;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700592 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600593 // Static buffer not big enough for message, use malloc to get enough
594 snprintf_with_malloc(shader_message, substring, needed, values);
595 }
596 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600597
598 if (verbose) {
599 std::string stage_message;
600 std::string common_message;
601 std::string filename_message;
602 std::string source_message;
Tony-LunarGb5fae462020-03-05 12:43:25 -0700603 UtilGenerateStageMessage(&debug_output_buffer[index], stage_message);
604 UtilGenerateCommonMessage(report_data, command_buffer, &debug_output_buffer[index], shader_module_handle,
Tony-LunarG7de10e82020-11-24 11:31:55 -0700605 pipeline_handle, buffer_info.pipeline_bind_point, operation_index, common_message);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700606 UtilGenerateSourceMessages(pgm, &debug_output_buffer[index], true, filename_message, source_message);
Tony-LunarG43416b42019-10-31 16:47:24 -0600607 if (use_stdout) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600608 std::cout << "UNASSIGNED-DEBUG-PRINTF " << common_message.c_str() << " " << stage_message.c_str() << " "
Tony-LunarGb5fae462020-03-05 12:43:25 -0700609 << shader_message.str().c_str() << " " << filename_message.c_str() << " " << source_message.c_str();
Tony-LunarG43416b42019-10-31 16:47:24 -0600610 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600611 LogInfo(queue, "UNASSIGNED-DEBUG-PRINTF", "%s %s %s %s%s", common_message.c_str(), stage_message.c_str(),
612 shader_message.str().c_str(), filename_message.c_str(), source_message.c_str());
Tony-LunarG43416b42019-10-31 16:47:24 -0600613 }
614 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600615 if (use_stdout) {
Tony-LunarG43416b42019-10-31 16:47:24 -0600616 std::cout << shader_message.str();
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600617 } else {
618 // Don't let LogInfo process any '%'s in the string
619 LogInfo(device, "UNASSIGNED-DEBUG-PRINTF", "%s", shader_message.str().c_str());
620 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600621 }
Tony-LunarG04717522019-10-17 10:41:17 -0600622 index += debug_record->size;
623 }
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600624 if ((index - 1) != expect) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600625 LogWarning(device, "UNASSIGNED-DEBUG-PRINTF",
626 "WARNING - Debug Printf message was truncated, likely due to a buffer size that was too small for the message");
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600627 }
Tony-LunarG04717522019-10-17 10:41:17 -0600628 memset(debug_output_buffer, 0, 4 * (debug_output_buffer[0] + 1));
629}
Tony-LunarG43416b42019-10-31 16:47:24 -0600630
Tony-LunarG04717522019-10-17 10:41:17 -0600631#if defined(__GNUC__)
632#pragma GCC diagnostic pop
633#endif
634
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700635bool DebugPrintf::CommandBufferNeedsProcessing(VkCommandBuffer command_buffer) {
636 bool buffers_present = false;
637 auto cb_node = GetCBState(command_buffer);
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600638 if (GetBufferInfo(cb_node->commandBuffer()).size()) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700639 buffers_present = true;
640 }
John Zulauf79f06582021-02-27 18:38:39 -0700641 for (const auto *secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600642 if (GetBufferInfo(secondaryCmdBuffer->commandBuffer()).size()) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700643 buffers_present = true;
644 }
645 }
646 return buffers_present;
647}
648
649void DebugPrintf::ProcessCommandBuffer(VkQueue queue, VkCommandBuffer command_buffer) {
650 auto cb_node = GetCBState(command_buffer);
651 UtilProcessInstrumentationBuffer(queue, cb_node, this);
John Zulauf79f06582021-02-27 18:38:39 -0700652 for (auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700653 UtilProcessInstrumentationBuffer(queue, secondary_cmd_buffer, this);
654 }
655}
656
Tony-LunarG04717522019-10-17 10:41:17 -0600657// Issue a memory barrier to make GPU-written data available to host.
658// Wait for the queue to complete execution.
659// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700660void DebugPrintf::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
661 VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -0600662 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
663
Mark Lobodzinski09379db2020-05-07 08:22:01 -0600664 if (aborted || (result != VK_SUCCESS)) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600665 bool buffers_present = false;
666 // Don't QueueWaitIdle if there's nothing to process
667 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
668 const VkSubmitInfo *submit = &pSubmits[submit_idx];
669 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700670 buffers_present |= CommandBufferNeedsProcessing(submit->pCommandBuffers[i]);
Tony-LunarG04717522019-10-17 10:41:17 -0600671 }
672 }
673 if (!buffers_present) return;
674
Tony-LunarGb5fae462020-03-05 12:43:25 -0700675 UtilSubmitBarrier(queue, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600676
677 DispatchQueueWaitIdle(queue);
678
679 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
680 const VkSubmitInfo *submit = &pSubmits[submit_idx];
681 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700682 ProcessCommandBuffer(queue, submit->pCommandBuffers[i]);
683 }
684 }
685}
686
687void DebugPrintf::PostCallRecordQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR *pSubmits,
688 VkFence fence, VkResult result) {
689 ValidationStateTracker::PostCallRecordQueueSubmit2KHR(queue, submitCount, pSubmits, fence, result);
690
691 if (aborted || (result != VK_SUCCESS)) return;
692 bool buffers_present = false;
693 // Don't QueueWaitIdle if there's nothing to process
694 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
695 const auto *submit = &pSubmits[submit_idx];
696 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
697 buffers_present |= CommandBufferNeedsProcessing(submit->pCommandBufferInfos[i].commandBuffer);
698 }
699 }
700 if (!buffers_present) return;
701
702 UtilSubmitBarrier(queue, this);
703
704 DispatchQueueWaitIdle(queue);
705
706 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
707 const VkSubmitInfo2KHR *submit = &pSubmits[submit_idx];
708 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
709 ProcessCommandBuffer(queue, submit->pCommandBufferInfos[i].commandBuffer);
Tony-LunarG04717522019-10-17 10:41:17 -0600710 }
711 }
712}
713
Tony-LunarGb5fae462020-03-05 12:43:25 -0700714void DebugPrintf::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
715 uint32_t firstVertex, uint32_t firstInstance) {
716 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600717}
718
Tony-LunarGb5fae462020-03-05 12:43:25 -0700719void DebugPrintf::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
720 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
721 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600722}
723
Tony-LunarGb5fae462020-03-05 12:43:25 -0700724void DebugPrintf::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
725 uint32_t stride) {
726 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600727}
728
Tony-LunarGb5fae462020-03-05 12:43:25 -0700729void DebugPrintf::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
730 uint32_t count, uint32_t stride) {
731 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600732}
733
Tony-LunarGb5fae462020-03-05 12:43:25 -0700734void DebugPrintf::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
735 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600736}
737
Tony-LunarGb5fae462020-03-05 12:43:25 -0700738void DebugPrintf::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
739 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600740}
741
Tony-LunarGd13f9b52020-09-08 15:45:45 -0600742void DebugPrintf::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
743 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
744 uint32_t groupCountZ) {
745 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
746}
747
Tony-LunarG52c8c602020-09-10 16:29:56 -0600748void DebugPrintf::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
749 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
750 uint32_t groupCountZ) {
751 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
752}
753
Tony-LunarG2fb8ff02020-06-11 12:45:07 -0600754void DebugPrintf::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
755 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
756 uint32_t stride) {
757 ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
758 maxDrawCount, stride);
759 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
760}
761
762void DebugPrintf::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
763 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
764 uint32_t stride) {
765 ValidationStateTracker::PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
766 maxDrawCount, stride);
767 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
768}
769
770void DebugPrintf::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
771 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
772 uint32_t maxDrawCount, uint32_t stride) {
773 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer,
774 countBufferOffset, maxDrawCount, stride);
775 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
776}
777
778void DebugPrintf::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
779 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
780 uint32_t maxDrawCount, uint32_t stride) {
781 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
782 maxDrawCount, stride);
783 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
784}
785
Tony-LunarG54176fb2020-12-02 10:47:22 -0700786void DebugPrintf::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
787 uint32_t firstInstance, VkBuffer counterBuffer,
788 VkDeviceSize counterBufferOffset, uint32_t counterOffset,
789 uint32_t vertexStride) {
790 ValidationStateTracker::PreCallRecordCmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer,
791 counterBufferOffset, counterOffset, vertexStride);
792 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
793}
794
Tony-LunarG2fb8ff02020-06-11 12:45:07 -0600795void DebugPrintf::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
796 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
797 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
798}
799
800void DebugPrintf::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
801 uint32_t drawCount, uint32_t stride) {
802 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
803 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
804}
805
806void DebugPrintf::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
807 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
808 uint32_t maxDrawCount, uint32_t stride) {
809 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer,
810 countBufferOffset, maxDrawCount, stride);
811 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
812}
813
Tony-LunarGb5fae462020-03-05 12:43:25 -0700814void DebugPrintf::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
815 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
816 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
817 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
818 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
819 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
820 uint32_t width, uint32_t height, uint32_t depth) {
821 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
822}
823
824void DebugPrintf::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
Tony-LunarG04717522019-10-17 10:41:17 -0600825 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
826 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
827 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
828 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
829 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
830 uint32_t width, uint32_t height, uint32_t depth) {
Tony-LunarG04717522019-10-17 10:41:17 -0600831 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
832 cb_state->hasTraceRaysCmd = true;
833}
834
Tony-LunarGb5fae462020-03-05 12:43:25 -0700835void DebugPrintf::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700836 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
837 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
838 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
839 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700840 uint32_t height, uint32_t depth) {
841 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600842}
843
Tony-LunarGb5fae462020-03-05 12:43:25 -0700844void DebugPrintf::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700845 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
846 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
847 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
848 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700849 uint32_t height, uint32_t depth) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600850 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
851 cb_state->hasTraceRaysCmd = true;
852}
853
Tony-LunarGb5fae462020-03-05 12:43:25 -0700854void DebugPrintf::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700855 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
856 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
857 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
858 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -0700859 VkDeviceAddress indirectDeviceAddress) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700860 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600861}
862
Tony-LunarGb5fae462020-03-05 12:43:25 -0700863void DebugPrintf::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700864 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
865 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
866 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
867 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -0700868 VkDeviceAddress indirectDeviceAddress) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600869 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
870 cb_state->hasTraceRaysCmd = true;
871}
872
Tony-LunarGb5fae462020-03-05 12:43:25 -0700873void DebugPrintf::AllocateDebugPrintfResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Tony-LunarG04717522019-10-17 10:41:17 -0600874 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
875 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
876 return;
877 }
878 VkResult result;
879
880 if (aborted) return;
881
882 std::vector<VkDescriptorSet> desc_sets;
883 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600884 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarG04717522019-10-17 10:41:17 -0600885 assert(result == VK_SUCCESS);
886 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600887 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600888 aborted = true;
889 return;
890 }
891
892 VkDescriptorBufferInfo output_desc_buffer_info = {};
893 output_desc_buffer_info.range = output_buffer_size;
894
895 auto cb_node = GetCBState(cmd_buffer);
896 if (!cb_node) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600897 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG04717522019-10-17 10:41:17 -0600898 aborted = true;
899 return;
900 }
901
902 // Allocate memory for the output block that the gpu will use to return values for printf
Tony-LunarGb5fae462020-03-05 12:43:25 -0700903 DPFDeviceMemoryBlock output_block = {};
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700904 VkBufferCreateInfo buffer_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
905 buffer_info.size = output_buffer_size;
906 buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
907 VmaAllocationCreateInfo alloc_info = {};
908 alloc_info.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
909 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarG04717522019-10-17 10:41:17 -0600910 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600911 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600912 aborted = true;
913 return;
914 }
915
916 // Clear the output block to zeros so that only printf values from the gpu will be present
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700917 uint32_t *data;
918 result = vmaMapMemory(vmaAllocator, output_block.allocation, reinterpret_cast<void **>(&data));
Tony-LunarG04717522019-10-17 10:41:17 -0600919 if (result == VK_SUCCESS) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700920 memset(data, 0, output_buffer_size);
Tony-LunarG04717522019-10-17 10:41:17 -0600921 vmaUnmapMemory(vmaAllocator, output_block.allocation);
922 }
923
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600924 auto desc_writes = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarG04717522019-10-17 10:41:17 -0600925 const uint32_t desc_count = 1;
926
927 // Write the descriptor
928 output_desc_buffer_info.buffer = output_block.buffer;
929 output_desc_buffer_info.offset = 0;
930
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600931 desc_writes.descriptorCount = 1;
932 desc_writes.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
933 desc_writes.pBufferInfo = &output_desc_buffer_info;
934 desc_writes.dstSet = desc_sets[0];
935 desc_writes.dstBinding = 3;
936 DispatchUpdateDescriptorSets(device, desc_count, &desc_writes, 0, NULL);
Tony-LunarG04717522019-10-17 10:41:17 -0600937
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600938 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
939 const auto *pipeline_state = cb_node->lastBound[lv_bind_point].pipeline_state;
940 if (pipeline_state) {
941 if (pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600942 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout(), desc_set_bind_index, 1,
Tony-LunarG04717522019-10-17 10:41:17 -0600943 desc_sets.data(), 0, nullptr);
944 }
945 // Record buffer and memory info in CB state tracking
Tony-LunarG1dce2392019-10-23 16:49:29 -0600946 GetBufferInfo(cmd_buffer).emplace_back(output_block, desc_sets[0], desc_pool, bind_point);
Tony-LunarG04717522019-10-17 10:41:17 -0600947 } else {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600948 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG04717522019-10-17 10:41:17 -0600949 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
950 aborted = true;
951 return;
952 }
953}