blob: 7ed7d44ad05dc91c55f31646df0fd3460a25467a [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"
Tony-LunarG04717522019-10-17 10:41:17 -060026
Tony-LunarG04717522019-10-17 10:41:17 -060027static const VkShaderStageFlags kShaderStageAllRayTracing =
28 VK_SHADER_STAGE_ANY_HIT_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV | VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV |
29 VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV | VK_SHADER_STAGE_RAYGEN_BIT_NV;
30
Tony-LunarG5af54eb2020-03-27 15:32:51 -060031// Convenience function for reporting problems with setting up Debug Printf.
Tony-LunarG1dce2392019-10-23 16:49:29 -060032template <typename T>
Tony-LunarGb5fae462020-03-05 12:43:25 -070033void DebugPrintf::ReportSetupProblem(T object, const char *const specific_message) const {
Tony-LunarG5af54eb2020-03-27 15:32:51 -060034 LogError(object, "UNASSIGNED-DEBUG-PRINTF ", "Detail: (%s)", specific_message);
Tony-LunarG04717522019-10-17 10:41:17 -060035}
36
37// Turn on necessary device features.
Tony-LunarGb5fae462020-03-05 12:43:25 -070038void DebugPrintf::PreCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info,
39 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
Mark Lobodzinskib588cd42020-09-30 11:03:34 -060040 void *modified_create_info) {
Tony-LunarG04717522019-10-17 10:41:17 -060041 DispatchGetPhysicalDeviceFeatures(gpu, &supported_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -060042 VkPhysicalDeviceFeatures features = {};
43 features.vertexPipelineStoresAndAtomics = true;
44 features.fragmentStoresAndAtomics = true;
Mark Lobodzinskib588cd42020-09-30 11:03:34 -060045 UtilPreCallRecordCreateDevice(gpu, reinterpret_cast<safe_VkDeviceCreateInfo *>(modified_create_info), supported_features,
46 features);
Tony-LunarG04717522019-10-17 10:41:17 -060047}
Tony-LunarG1dce2392019-10-23 16:49:29 -060048
Tony-LunarG04717522019-10-17 10:41:17 -060049// Perform initializations that can be done at Create Device time.
Tony-LunarGb5fae462020-03-05 12:43:25 -070050void DebugPrintf::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
51 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -060052 ValidationStateTracker::PostCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice, result);
53
54 ValidationObject *device_object = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
55 ValidationObject *validation_data = GetValidationObject(device_object->object_dispatch, this->container_type);
Tony-LunarGb5fae462020-03-05 12:43:25 -070056 DebugPrintf *device_debug_printf = static_cast<DebugPrintf *>(validation_data);
57 device_debug_printf->physicalDevice = physicalDevice;
58 device_debug_printf->device = *pDevice;
Tony-LunarG43416b42019-10-31 16:47:24 -060059
60 const char *size_string = getLayerOption("khronos_validation.printf_buffer_size");
Tony-LunarGb5fae462020-03-05 12:43:25 -070061 device_debug_printf->output_buffer_size = *size_string ? atoi(size_string) : 1024;
Tony-LunarG43416b42019-10-31 16:47:24 -060062 const char *verbose_string = getLayerOption("khronos_validation.printf_verbose");
Tony-LunarGb5fae462020-03-05 12:43:25 -070063 device_debug_printf->verbose = *verbose_string ? !strcmp(verbose_string, "true") : false;
Tony-LunarG43416b42019-10-31 16:47:24 -060064 const char *stdout_string = getLayerOption("khronos_validation.printf_to_stdout");
Tony-LunarGb5fae462020-03-05 12:43:25 -070065 device_debug_printf->use_stdout = *stdout_string ? !strcmp(stdout_string, "true") : false;
66 if (getenv("DEBUG_PRINTF_TO_STDOUT")) device_debug_printf->use_stdout = true;
Tony-LunarG04717522019-10-17 10:41:17 -060067
Tony-LunarGb5fae462020-03-05 12:43:25 -070068 if (device_debug_printf->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Tony-LunarGbbbed672020-03-04 10:51:11 -070069 ReportSetupProblem(device, "Debug Printf requires Vulkan 1.1 or later. Debug Printf disabled.");
Tony-LunarGb5fae462020-03-05 12:43:25 -070070 device_debug_printf->aborted = true;
Tony-LunarG04717522019-10-17 10:41:17 -060071 return;
72 }
73
74 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Tony-LunarG1dce2392019-10-23 16:49:29 -060075 ReportSetupProblem(device,
Tony-LunarGbbbed672020-03-04 10:51:11 -070076 "Debug Printf requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
77 "Debug Printf disabled.");
Tony-LunarGb5fae462020-03-05 12:43:25 -070078 device_debug_printf->aborted = true;
Tony-LunarG04717522019-10-17 10:41:17 -060079 return;
80 }
Tony-LunarG9586e732020-03-04 10:50:30 -070081
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -060082 if (enabled[gpu_validation]) {
Tony-LunarG9586e732020-03-04 10:50:30 -070083 ReportSetupProblem(device,
84 "Debug Printf cannot be enabled when gpu assisted validation is enabled. "
85 "Debug Printf disabled.");
Tony-LunarGb5fae462020-03-05 12:43:25 -070086 device_debug_printf->aborted = true;
Tony-LunarG9586e732020-03-04 10:50:30 -070087 return;
88 }
89
Tony-LunarG1dce2392019-10-23 16:49:29 -060090 std::vector<VkDescriptorSetLayoutBinding> bindings;
91 VkDescriptorSetLayoutBinding binding = {3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
Tony-LunarGc7ed2082020-06-11 14:00:04 -060092 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_MESH_BIT_NV |
93 VK_SHADER_STAGE_TASK_BIT_NV | VK_SHADER_STAGE_COMPUTE_BIT |
94 kShaderStageAllRayTracing,
Tony-LunarG1dce2392019-10-23 16:49:29 -060095 NULL};
96 bindings.push_back(binding);
Tony-LunarGb5fae462020-03-05 12:43:25 -070097 UtilPostCallRecordCreateDevice(pCreateInfo, bindings, device_debug_printf, device_debug_printf->phys_dev_props);
Tony-LunarG04717522019-10-17 10:41:17 -060098}
99
Tony-LunarGb5fae462020-03-05 12:43:25 -0700100void DebugPrintf::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
101 UtilPreCallRecordDestroyDevice(this);
Tony-LunarG0a863bc2020-09-16 09:50:04 -0600102 ValidationStateTracker::PreCallRecordDestroyDevice(device, pAllocator);
103 // State Tracker can end up making vma calls through callbacks - don't destroy allocator until ST is done
104 if (vmaAllocator) {
105 vmaDestroyAllocator(vmaAllocator);
106 }
107 desc_set_manager.reset();
Tony-LunarG04717522019-10-17 10:41:17 -0600108}
109
110// 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 -0700111void DebugPrintf::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
112 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
113 void *cpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600114 if (aborted) {
115 return;
116 }
117
118 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
119
120 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
121 std::ostringstream strm;
122 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Tony-LunarGbbbed672020-03-04 10:51:11 -0700123 << "Application has too many descriptor sets in the pipeline layout to continue with debug printf. "
Tony-LunarG04717522019-10-17 10:41:17 -0600124 << "Not modifying the pipeline layout. "
125 << "Instrumented shaders are replaced with non-instrumented shaders.";
Tony-LunarG1dce2392019-10-23 16:49:29 -0600126 ReportSetupProblem(device, strm.str().c_str());
Tony-LunarG04717522019-10-17 10:41:17 -0600127 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700128 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Tony-LunarG04717522019-10-17 10:41:17 -0600129 }
130}
131
Tony-LunarGb5fae462020-03-05 12:43:25 -0700132void DebugPrintf::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
133 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
134 VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -0600135 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
136 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600137 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600138 aborted = true;
139 }
140}
141
142// Free the device memory and descriptor set associated with a command buffer.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700143void DebugPrintf::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG04717522019-10-17 10:41:17 -0600144 if (aborted) {
145 return;
146 }
Tony-LunarGb5fae462020-03-05 12:43:25 -0700147 auto debug_printf_buffer_list = GetBufferInfo(commandBuffer);
John Zulauf79f06582021-02-27 18:38:39 -0700148 for (const auto &buffer_info : debug_printf_buffer_list) {
Tony-LunarG04717522019-10-17 10:41:17 -0600149 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
150 if (buffer_info.desc_set != VK_NULL_HANDLE) {
151 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
152 }
153 }
154 command_buffer_map.erase(commandBuffer);
155}
156
157// Just gives a warning about a possible deadlock.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700158bool DebugPrintf::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
159 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
160 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
161 uint32_t bufferMemoryBarrierCount,
162 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
163 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG04717522019-10-17 10:41:17 -0600164 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600165 ReportSetupProblem(commandBuffer,
166 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
Tony-LunarGbbbed672020-03-04 10:51:11 -0700167 "Debug Printf waits on queue completion. "
Tony-LunarG1dce2392019-10-23 16:49:29 -0600168 "This wait could block the host's signaling of this event, resulting in deadlock.");
Tony-LunarG04717522019-10-17 10:41:17 -0600169 }
170 return false;
171}
172
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700173bool DebugPrintf::PreCallValidateCmdWaitEvents2KHR(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
174 const VkDependencyInfoKHR *pDependencyInfos) const {
175 VkPipelineStageFlags2KHR srcStageMask = 0;
176
177 for (uint32_t i = 0; i < eventCount; i++) {
178 auto stage_masks = sync_utils::GetGlobalStageMasks(pDependencyInfos[i]);
179 srcStageMask = stage_masks.src;
180 }
181
182 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
183 ReportSetupProblem(commandBuffer,
184 "CmdWaitEvents2KHR recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
185 "Debug Printf waits on queue completion. "
186 "This wait could block the host's signaling of this event, resulting in deadlock.");
187 }
188 return false;
189}
190
Tony-LunarGb5fae462020-03-05 12:43:25 -0700191void DebugPrintf::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
192 const VkGraphicsPipelineCreateInfo *pCreateInfos,
193 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
194 void *cgpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600195 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
196 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700197 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
198 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600199 cgpl_state->printf_create_infos = new_pipeline_create_infos;
200 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->printf_create_infos.data());
201}
202
Tony-LunarGb5fae462020-03-05 12:43:25 -0700203void DebugPrintf::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
204 const VkComputePipelineCreateInfo *pCreateInfos,
205 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
206 void *ccpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600207 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
208 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700209 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
210 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600211 ccpl_state->printf_create_infos = new_pipeline_create_infos;
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600212 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->printf_create_infos.data());
Tony-LunarG04717522019-10-17 10:41:17 -0600213}
214
Tony-LunarGb5fae462020-03-05 12:43:25 -0700215void DebugPrintf::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
216 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
217 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
218 void *crtpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600219 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
220 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700221 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
222 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600223 crtpl_state->printf_create_infos = new_pipeline_create_infos;
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600224 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->printf_create_infos.data());
Tony-LunarG04717522019-10-17 10:41:17 -0600225}
226
sourav parmarcd5fb182020-07-17 12:58:44 -0700227void DebugPrintf::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
228 VkPipelineCache pipelineCache, uint32_t count,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700229 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
230 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
231 void *crtpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600232 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
233 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700234 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
235 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600236 crtpl_state->printf_create_infos = new_pipeline_create_infos;
237 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->printf_create_infos.data());
Tony-LunarG04717522019-10-17 10:41:17 -0600238}
Tony-LunarG04717522019-10-17 10:41:17 -0600239
Tony-LunarGb5fae462020-03-05 12:43:25 -0700240void DebugPrintf::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
241 const VkGraphicsPipelineCreateInfo *pCreateInfos,
242 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
243 VkResult result, void *cgpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600244 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
245 pPipelines, result, cgpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600246 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
247 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, cgpl_state->printf_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -0700248 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600249}
250
Tony-LunarGb5fae462020-03-05 12:43:25 -0700251void DebugPrintf::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
252 const VkComputePipelineCreateInfo *pCreateInfos,
253 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
254 VkResult result, void *ccpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600255 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
256 result, ccpl_state_data);
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600257 create_compute_pipeline_api_state *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
258 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, ccpl_state->printf_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -0700259 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600260}
261
Tony-LunarGb5fae462020-03-05 12:43:25 -0700262void DebugPrintf::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
263 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
264 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
265 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600266 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarG04717522019-10-17 10:41:17 -0600267 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
268 pPipelines, result, crtpl_state_data);
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600269 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->printf_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -0700270 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600271}
272
Tony-LunarGfb2ab872021-01-13 15:17:15 -0700273void DebugPrintf::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
274 VkPipelineCache pipelineCache, uint32_t count,
275 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
276 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
277 VkResult result, void *crtpl_state_data) {
278 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
279 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesKHR(
280 device, deferredOperation, pipelineCache, count, pCreateInfos, pAllocator, pPipelines, result, crtpl_state_data);
281 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->printf_create_infos.data());
282 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
283}
284
Tony-LunarG04717522019-10-17 10:41:17 -0600285// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700286void DebugPrintf::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG04717522019-10-17 10:41:17 -0600287 for (auto it = shader_map.begin(); it != shader_map.end();) {
288 if (it->second.pipeline == pipeline) {
289 it = shader_map.erase(it);
290 } else {
291 ++it;
292 }
293 }
294 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
295}
296// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700297bool DebugPrintf::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
298 uint32_t *unique_shader_id) {
Tony-LunarG04717522019-10-17 10:41:17 -0600299 if (aborted) return false;
300 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
301
302 // Load original shader SPIR-V
303 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
304 new_pgm.clear();
305 new_pgm.reserve(num_words);
306 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
307
308 // Call the optimizer to instrument the shader.
309 // Use the unique_shader_module_id as a shader ID so we can look up its handle later in the shader_map.
310 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
311 using namespace spvtools;
Tony-LunarG8a51b7d2020-07-01 15:57:23 -0600312 spv_target_env target_env = PickSpirvEnv(api_version, (device_extensions.vk_khr_spirv_1_4 != kNotEnabled));
Tony-LunarGf29f77f2020-08-26 15:48:00 -0600313 spvtools::ValidatorOptions val_options;
314 AdjustValidatorOptions(device_extensions, enabled_features, val_options);
315 spvtools::OptimizerOptions opt_options;
316 opt_options.set_run_validator(true);
317 opt_options.set_validator_options(val_options);
Tony-LunarG04717522019-10-17 10:41:17 -0600318 Optimizer optimizer(target_env);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700319 const spvtools::MessageConsumer debug_printf_console_message_consumer =
Tony-LunarG79641702020-07-13 15:43:05 -0600320 [this](spv_message_level_t level, const char *, const spv_position_t &position, const char *message) -> void {
321 switch (level) {
322 case SPV_MSG_FATAL:
323 case SPV_MSG_INTERNAL_ERROR:
324 case SPV_MSG_ERROR:
325 this->LogError(this->device, "UNASSIGNED-Debug-Printf", "Error during shader instrumentation: line %zu: %s",
326 position.index, message);
327 break;
328 default:
329 break;
330 }
331 };
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700332 optimizer.SetMessageConsumer(debug_printf_console_message_consumer);
Tony-LunarG04717522019-10-17 10:41:17 -0600333 optimizer.RegisterPass(CreateInstDebugPrintfPass(desc_set_bind_index, unique_shader_module_id));
Tony-LunarGf29f77f2020-08-26 15:48:00 -0600334 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm, opt_options);
Tony-LunarG04717522019-10-17 10:41:17 -0600335 if (!pass) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600336 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Tony-LunarG04717522019-10-17 10:41:17 -0600337 }
338 *unique_shader_id = unique_shader_module_id++;
339 return pass;
340}
341// Create the instrumented shader data to provide to the driver.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700342void DebugPrintf::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
343 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
344 void *csm_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600345 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
346 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
347 if (pass) {
348 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
349 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
350 }
351}
Tony-LunarG04717522019-10-17 10:41:17 -0600352
353vartype vartype_lookup(char intype) {
354 switch (intype) {
355 case 'd':
356 case 'i':
357 return varsigned;
358 break;
359
360 case 'f':
361 case 'F':
362 case 'a':
363 case 'A':
364 case 'e':
365 case 'E':
366 case 'g':
367 case 'G':
368 return varfloat;
369 break;
370
371 case 'u':
372 case 'x':
373 case 'o':
374 default:
375 return varunsigned;
376 break;
377 }
378}
379
Tony-LunarGa19e31e2020-03-30 13:30:29 -0600380std::vector<DPFSubstring> DebugPrintf::ParseFormatString(const std::string format_string) {
381 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 -0700382 std::vector<DPFSubstring> parsed_strings;
Tony-LunarG04717522019-10-17 10:41:17 -0600383 size_t pos = 0;
384 size_t begin = 0;
385 size_t percent = 0;
386
387 while (begin < format_string.length()) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700388 DPFSubstring substring;
Tony-LunarG04717522019-10-17 10:41:17 -0600389
390 // Find a percent sign
391 pos = percent = format_string.find_first_of('%', pos);
392 if (pos == std::string::npos) {
393 // End of the format string Push the rest of the characters
394 substring.string = format_string.substr(begin, format_string.length());
395 substring.needs_value = false;
396 parsed_strings.push_back(substring);
397 break;
398 }
399 pos++;
400 if (format_string[pos] == '%') {
401 pos++;
402 continue; // %% - skip it
403 }
404 // Find the type of the value
405 pos = format_string.find_first_of(types, pos);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700406 if (pos == format_string.npos) {
Tony-LunarG04717522019-10-17 10:41:17 -0600407 // This really shouldn't happen with a legal value string
408 pos = format_string.length();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700409 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600410 char tempstring[32];
411 int count = 0;
412 std::string specifier = {};
413
414 if (format_string[pos] == 'v') {
415 // Vector must be of size 2, 3, or 4
416 // and format %v<size><type>
417 specifier = format_string.substr(percent, pos - percent);
418 count = atoi(&format_string[pos + 1]);
419 pos += 2;
420
421 // skip v<count>, handle long
422 specifier.push_back(format_string[pos]);
423 if (format_string[pos + 1] == 'l') {
424 specifier.push_back('l');
425 pos++;
426 }
427
428 // Take the preceding characters, and the percent through the type
429 substring.string = format_string.substr(begin, percent - begin);
430 substring.string += specifier;
431 substring.needs_value = true;
432 substring.type = vartype_lookup(specifier.back());
433 parsed_strings.push_back(substring);
434
435 // Continue with a comma separated list
436 sprintf(tempstring, ", %s", specifier.c_str());
437 substring.string = tempstring;
438 for (int i = 0; i < (count - 1); i++) {
439 parsed_strings.push_back(substring);
440 }
441 } else {
442 // Single non-vector value
443 if (format_string[pos + 1] == 'l') pos++; // Save long size
444 substring.string = format_string.substr(begin, pos - begin + 1);
445 substring.needs_value = true;
446 substring.type = vartype_lookup(format_string[pos]);
447 parsed_strings.push_back(substring);
448 }
449 begin = pos + 1;
450 }
451 }
452 return parsed_strings;
453}
454
Tony-LunarGb5fae462020-03-05 12:43:25 -0700455std::string DebugPrintf::FindFormatString(std::vector<unsigned int> pgm, uint32_t string_id) {
Tony-LunarG04717522019-10-17 10:41:17 -0600456 std::string format_string;
457 SHADER_MODULE_STATE shader;
458 shader.words = pgm;
459 if (shader.words.size() > 0) {
John Zulauf79f06582021-02-27 18:38:39 -0700460 for (const auto &insn : shader) {
Tony-LunarG04717522019-10-17 10:41:17 -0600461 if (insn.opcode() == spv::OpString) {
462 uint32_t offset = insn.offset();
463 if (pgm[offset + 1] == string_id) {
464 format_string = reinterpret_cast<char *>(&pgm[offset + 2]);
465 break;
466 }
467 }
468 }
469 }
470
471 return format_string;
472}
473
Corentin Wallez171ac5e2020-03-31 16:09:05 +0200474// GCC and clang don't like using variables as format strings in sprintf.
475// #pragma GCC is recognized by both compilers
476#if defined(__GNUC__) || defined(__clang__)
Tony-LunarG04717522019-10-17 10:41:17 -0600477#pragma GCC diagnostic push
478#pragma GCC diagnostic ignored "-Wformat-security"
479#endif
480
Tony-LunarGb5fae462020-03-05 12:43:25 -0700481void snprintf_with_malloc(std::stringstream &shader_message, DPFSubstring substring, size_t needed, void *values) {
Tony-LunarG04717522019-10-17 10:41:17 -0600482 char *buffer = static_cast<char *>(malloc((needed + 1) * sizeof(char))); // Add 1 for terminator
483 if (substring.longval) {
484 snprintf(buffer, needed, substring.string.c_str(), substring.longval);
485 } else if (!substring.needs_value) {
486 snprintf(buffer, needed, substring.string.c_str());
487 } else {
488 switch (substring.type) {
489 case varunsigned:
490 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<uint32_t *>(values) - 1);
491 break;
492
493 case varsigned:
494 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<int32_t *>(values) - 1);
495 break;
496
497 case varfloat:
498 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<float *>(values) - 1);
499 break;
500 }
501 }
502 shader_message << buffer;
503 free(buffer);
504}
505
Tony-LunarG7de10e82020-11-24 11:31:55 -0700506void DebugPrintf::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, DPFBufferInfo &buffer_info,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700507 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Tony-LunarG04717522019-10-17 10:41:17 -0600508 // Word Content
509 // 0 Size of output record, including this word
510 // 1 Shader ID
511 // 2 Instruction Position
512 // 3 Stage Ordinal
513 // 4 Stage - specific Info Word 0
514 // 5 Stage - specific Info Word 1
515 // 6 Stage - specific Info Word 2
516 // 7 Printf Format String Id
517 // 8 Printf Values Word 0 (optional)
518 // 9 Printf Values Word 1 (optional)
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600519 uint32_t expect = debug_output_buffer[0];
520 if (!expect) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600521
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600522 uint32_t index = 1;
Tony-LunarG04717522019-10-17 10:41:17 -0600523 while (debug_output_buffer[index]) {
Tony-LunarG04717522019-10-17 10:41:17 -0600524 std::stringstream shader_message;
Tony-LunarG04717522019-10-17 10:41:17 -0600525 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
526 VkPipeline pipeline_handle = VK_NULL_HANDLE;
527 std::vector<unsigned int> pgm;
528
Tony-LunarGb5fae462020-03-05 12:43:25 -0700529 DPFOutputRecord *debug_record = reinterpret_cast<DPFOutputRecord *>(&debug_output_buffer[index]);
Tony-LunarG04717522019-10-17 10:41:17 -0600530 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
531 // by the instrumented shader.
532 auto it = shader_map.find(debug_record->shader_id);
533 if (it != shader_map.end()) {
534 shader_module_handle = it->second.shader_module;
535 pipeline_handle = it->second.pipeline;
536 pgm = it->second.pgm;
537 }
538 // Search through the shader source for the printf format string for this invocation
539 auto format_string = FindFormatString(pgm, debug_record->format_string_id);
540 // Break the format string into strings with 1 or 0 value
541 auto format_substrings = ParseFormatString(format_string);
542 void *values = static_cast<void *>(&debug_record->values);
543 const uint32_t static_size = 1024;
544 // Sprintf each format substring into a temporary string then add that to the message
545 for (auto &substring : format_substrings) {
546 char temp_string[static_size];
547 size_t needed = 0;
548 const size_t ul_pos = substring.string.find("%ul");
549 if (ul_pos != std::string::npos) {
550 // Unsigned 64 bit value
551 substring.longval = *static_cast<uint64_t *>(values);
552 values = static_cast<uint64_t *>(values) + 1;
553 substring.string.replace(ul_pos + 1, 2, PRIx64);
554 needed = snprintf(temp_string, static_size, substring.string.c_str(), substring.longval);
555 } else {
556 if (substring.needs_value) {
557 switch (substring.type) {
558 case varunsigned:
559 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<uint32_t *>(values));
560 break;
561
562 case varsigned:
563 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<int32_t *>(values));
564 break;
565
566 case varfloat:
567 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<float *>(values));
568 break;
569 }
570 values = static_cast<uint32_t *>(values) + 1;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700571 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600572 needed = snprintf(temp_string, static_size, substring.string.c_str());
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700573 }
Tony-LunarG04717522019-10-17 10:41:17 -0600574 }
575
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700576 if (needed < static_size) {
Tony-LunarG04717522019-10-17 10:41:17 -0600577 shader_message << temp_string;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700578 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600579 // Static buffer not big enough for message, use malloc to get enough
580 snprintf_with_malloc(shader_message, substring, needed, values);
581 }
582 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600583
584 if (verbose) {
585 std::string stage_message;
586 std::string common_message;
587 std::string filename_message;
588 std::string source_message;
Tony-LunarGb5fae462020-03-05 12:43:25 -0700589 UtilGenerateStageMessage(&debug_output_buffer[index], stage_message);
590 UtilGenerateCommonMessage(report_data, command_buffer, &debug_output_buffer[index], shader_module_handle,
Tony-LunarG7de10e82020-11-24 11:31:55 -0700591 pipeline_handle, buffer_info.pipeline_bind_point, operation_index, common_message);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700592 UtilGenerateSourceMessages(pgm, &debug_output_buffer[index], true, filename_message, source_message);
Tony-LunarG43416b42019-10-31 16:47:24 -0600593 if (use_stdout) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600594 std::cout << "UNASSIGNED-DEBUG-PRINTF " << common_message.c_str() << " " << stage_message.c_str() << " "
Tony-LunarGb5fae462020-03-05 12:43:25 -0700595 << shader_message.str().c_str() << " " << filename_message.c_str() << " " << source_message.c_str();
Tony-LunarG43416b42019-10-31 16:47:24 -0600596 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600597 LogInfo(queue, "UNASSIGNED-DEBUG-PRINTF", "%s %s %s %s%s", common_message.c_str(), stage_message.c_str(),
598 shader_message.str().c_str(), filename_message.c_str(), source_message.c_str());
Tony-LunarG43416b42019-10-31 16:47:24 -0600599 }
600 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600601 if (use_stdout) {
Tony-LunarG43416b42019-10-31 16:47:24 -0600602 std::cout << shader_message.str();
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600603 } else {
604 // Don't let LogInfo process any '%'s in the string
605 LogInfo(device, "UNASSIGNED-DEBUG-PRINTF", "%s", shader_message.str().c_str());
606 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600607 }
Tony-LunarG04717522019-10-17 10:41:17 -0600608 index += debug_record->size;
609 }
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600610 if ((index - 1) != expect) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600611 LogWarning(device, "UNASSIGNED-DEBUG-PRINTF",
612 "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 -0600613 }
Tony-LunarG04717522019-10-17 10:41:17 -0600614 memset(debug_output_buffer, 0, 4 * (debug_output_buffer[0] + 1));
615}
Tony-LunarG43416b42019-10-31 16:47:24 -0600616
Tony-LunarG04717522019-10-17 10:41:17 -0600617#if defined(__GNUC__)
618#pragma GCC diagnostic pop
619#endif
620
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700621bool DebugPrintf::CommandBufferNeedsProcessing(VkCommandBuffer command_buffer) {
622 bool buffers_present = false;
623 auto cb_node = GetCBState(command_buffer);
624 if (GetBufferInfo(cb_node->commandBuffer).size()) {
625 buffers_present = true;
626 }
John Zulauf79f06582021-02-27 18:38:39 -0700627 for (const auto *secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700628 if (GetBufferInfo(secondaryCmdBuffer->commandBuffer).size()) {
629 buffers_present = true;
630 }
631 }
632 return buffers_present;
633}
634
635void DebugPrintf::ProcessCommandBuffer(VkQueue queue, VkCommandBuffer command_buffer) {
636 auto cb_node = GetCBState(command_buffer);
637 UtilProcessInstrumentationBuffer(queue, cb_node, this);
John Zulauf79f06582021-02-27 18:38:39 -0700638 for (auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700639 UtilProcessInstrumentationBuffer(queue, secondary_cmd_buffer, this);
640 }
641}
642
Tony-LunarG04717522019-10-17 10:41:17 -0600643// Issue a memory barrier to make GPU-written data available to host.
644// Wait for the queue to complete execution.
645// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700646void DebugPrintf::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
647 VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -0600648 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
649
Mark Lobodzinski09379db2020-05-07 08:22:01 -0600650 if (aborted || (result != VK_SUCCESS)) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600651 bool buffers_present = false;
652 // Don't QueueWaitIdle if there's nothing to process
653 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
654 const VkSubmitInfo *submit = &pSubmits[submit_idx];
655 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700656 buffers_present |= CommandBufferNeedsProcessing(submit->pCommandBuffers[i]);
Tony-LunarG04717522019-10-17 10:41:17 -0600657 }
658 }
659 if (!buffers_present) return;
660
Tony-LunarGb5fae462020-03-05 12:43:25 -0700661 UtilSubmitBarrier(queue, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600662
663 DispatchQueueWaitIdle(queue);
664
665 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
666 const VkSubmitInfo *submit = &pSubmits[submit_idx];
667 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700668 ProcessCommandBuffer(queue, submit->pCommandBuffers[i]);
669 }
670 }
671}
672
673void DebugPrintf::PostCallRecordQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR *pSubmits,
674 VkFence fence, VkResult result) {
675 ValidationStateTracker::PostCallRecordQueueSubmit2KHR(queue, submitCount, pSubmits, fence, result);
676
677 if (aborted || (result != VK_SUCCESS)) return;
678 bool buffers_present = false;
679 // Don't QueueWaitIdle if there's nothing to process
680 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
681 const auto *submit = &pSubmits[submit_idx];
682 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
683 buffers_present |= CommandBufferNeedsProcessing(submit->pCommandBufferInfos[i].commandBuffer);
684 }
685 }
686 if (!buffers_present) return;
687
688 UtilSubmitBarrier(queue, this);
689
690 DispatchQueueWaitIdle(queue);
691
692 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
693 const VkSubmitInfo2KHR *submit = &pSubmits[submit_idx];
694 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
695 ProcessCommandBuffer(queue, submit->pCommandBufferInfos[i].commandBuffer);
Tony-LunarG04717522019-10-17 10:41:17 -0600696 }
697 }
698}
699
Tony-LunarGb5fae462020-03-05 12:43:25 -0700700void DebugPrintf::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
701 uint32_t firstVertex, uint32_t firstInstance) {
702 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600703}
704
Tony-LunarGb5fae462020-03-05 12:43:25 -0700705void DebugPrintf::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
706 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
707 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600708}
709
Tony-LunarGb5fae462020-03-05 12:43:25 -0700710void DebugPrintf::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
711 uint32_t stride) {
712 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600713}
714
Tony-LunarGb5fae462020-03-05 12:43:25 -0700715void DebugPrintf::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
716 uint32_t count, uint32_t stride) {
717 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600718}
719
Tony-LunarGb5fae462020-03-05 12:43:25 -0700720void DebugPrintf::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
721 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600722}
723
Tony-LunarGb5fae462020-03-05 12:43:25 -0700724void DebugPrintf::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
725 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600726}
727
Tony-LunarGd13f9b52020-09-08 15:45:45 -0600728void DebugPrintf::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
729 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
730 uint32_t groupCountZ) {
731 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
732}
733
Tony-LunarG52c8c602020-09-10 16:29:56 -0600734void DebugPrintf::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
735 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
736 uint32_t groupCountZ) {
737 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
738}
739
Tony-LunarG2fb8ff02020-06-11 12:45:07 -0600740void DebugPrintf::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
741 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
742 uint32_t stride) {
743 ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
744 maxDrawCount, stride);
745 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
746}
747
748void DebugPrintf::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
749 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
750 uint32_t stride) {
751 ValidationStateTracker::PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
752 maxDrawCount, stride);
753 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
754}
755
756void DebugPrintf::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
757 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
758 uint32_t maxDrawCount, uint32_t stride) {
759 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer,
760 countBufferOffset, maxDrawCount, stride);
761 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
762}
763
764void DebugPrintf::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
765 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
766 uint32_t maxDrawCount, uint32_t stride) {
767 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
768 maxDrawCount, stride);
769 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
770}
771
Tony-LunarG54176fb2020-12-02 10:47:22 -0700772void DebugPrintf::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
773 uint32_t firstInstance, VkBuffer counterBuffer,
774 VkDeviceSize counterBufferOffset, uint32_t counterOffset,
775 uint32_t vertexStride) {
776 ValidationStateTracker::PreCallRecordCmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer,
777 counterBufferOffset, counterOffset, vertexStride);
778 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
779}
780
Tony-LunarG2fb8ff02020-06-11 12:45:07 -0600781void DebugPrintf::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
782 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
783 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
784}
785
786void DebugPrintf::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
787 uint32_t drawCount, uint32_t stride) {
788 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
789 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
790}
791
792void DebugPrintf::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
793 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
794 uint32_t maxDrawCount, uint32_t stride) {
795 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer,
796 countBufferOffset, maxDrawCount, stride);
797 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
798}
799
Tony-LunarGb5fae462020-03-05 12:43:25 -0700800void DebugPrintf::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
801 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
802 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
803 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
804 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
805 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
806 uint32_t width, uint32_t height, uint32_t depth) {
807 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
808}
809
810void DebugPrintf::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
Tony-LunarG04717522019-10-17 10:41:17 -0600811 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
812 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
813 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
814 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
815 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
816 uint32_t width, uint32_t height, uint32_t depth) {
Tony-LunarG04717522019-10-17 10:41:17 -0600817 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
818 cb_state->hasTraceRaysCmd = true;
819}
820
Tony-LunarGb5fae462020-03-05 12:43:25 -0700821void DebugPrintf::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700822 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
823 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
824 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
825 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700826 uint32_t height, uint32_t depth) {
827 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600828}
829
Tony-LunarGb5fae462020-03-05 12:43:25 -0700830void DebugPrintf::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700831 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
832 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
833 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
834 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700835 uint32_t height, uint32_t depth) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600836 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
837 cb_state->hasTraceRaysCmd = true;
838}
839
Tony-LunarGb5fae462020-03-05 12:43:25 -0700840void DebugPrintf::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700841 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
842 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
843 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
844 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -0700845 VkDeviceAddress indirectDeviceAddress) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700846 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600847}
848
Tony-LunarGb5fae462020-03-05 12:43:25 -0700849void DebugPrintf::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700850 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
851 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
852 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
853 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -0700854 VkDeviceAddress indirectDeviceAddress) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600855 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
856 cb_state->hasTraceRaysCmd = true;
857}
858
Tony-LunarGb5fae462020-03-05 12:43:25 -0700859void DebugPrintf::AllocateDebugPrintfResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Tony-LunarG04717522019-10-17 10:41:17 -0600860 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
861 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
862 return;
863 }
864 VkResult result;
865
866 if (aborted) return;
867
868 std::vector<VkDescriptorSet> desc_sets;
869 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600870 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarG04717522019-10-17 10:41:17 -0600871 assert(result == VK_SUCCESS);
872 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600873 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600874 aborted = true;
875 return;
876 }
877
878 VkDescriptorBufferInfo output_desc_buffer_info = {};
879 output_desc_buffer_info.range = output_buffer_size;
880
881 auto cb_node = GetCBState(cmd_buffer);
882 if (!cb_node) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600883 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG04717522019-10-17 10:41:17 -0600884 aborted = true;
885 return;
886 }
887
888 // Allocate memory for the output block that the gpu will use to return values for printf
Tony-LunarGb5fae462020-03-05 12:43:25 -0700889 DPFDeviceMemoryBlock output_block = {};
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700890 VkBufferCreateInfo buffer_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
891 buffer_info.size = output_buffer_size;
892 buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
893 VmaAllocationCreateInfo alloc_info = {};
894 alloc_info.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
895 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarG04717522019-10-17 10:41:17 -0600896 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600897 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600898 aborted = true;
899 return;
900 }
901
902 // Clear the output block to zeros so that only printf values from the gpu will be present
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700903 uint32_t *data;
904 result = vmaMapMemory(vmaAllocator, output_block.allocation, reinterpret_cast<void **>(&data));
Tony-LunarG04717522019-10-17 10:41:17 -0600905 if (result == VK_SUCCESS) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700906 memset(data, 0, output_buffer_size);
Tony-LunarG04717522019-10-17 10:41:17 -0600907 vmaUnmapMemory(vmaAllocator, output_block.allocation);
908 }
909
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600910 auto desc_writes = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarG04717522019-10-17 10:41:17 -0600911 const uint32_t desc_count = 1;
912
913 // Write the descriptor
914 output_desc_buffer_info.buffer = output_block.buffer;
915 output_desc_buffer_info.offset = 0;
916
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600917 desc_writes.descriptorCount = 1;
918 desc_writes.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
919 desc_writes.pBufferInfo = &output_desc_buffer_info;
920 desc_writes.dstSet = desc_sets[0];
921 desc_writes.dstBinding = 3;
922 DispatchUpdateDescriptorSets(device, desc_count, &desc_writes, 0, NULL);
Tony-LunarG04717522019-10-17 10:41:17 -0600923
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600924 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
925 const auto *pipeline_state = cb_node->lastBound[lv_bind_point].pipeline_state;
926 if (pipeline_state) {
927 if (pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index) {
Tony-LunarG04717522019-10-17 10:41:17 -0600928 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout, desc_set_bind_index, 1,
929 desc_sets.data(), 0, nullptr);
930 }
931 // Record buffer and memory info in CB state tracking
Tony-LunarG1dce2392019-10-23 16:49:29 -0600932 GetBufferInfo(cmd_buffer).emplace_back(output_block, desc_sets[0], desc_pool, bind_point);
Tony-LunarG04717522019-10-17 10:41:17 -0600933 } else {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600934 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG04717522019-10-17 10:41:17 -0600935 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
936 aborted = true;
937 return;
938 }
939}