blob: 819467395e669af1d1974e093070f291b0d61e4c [file] [log] [blame]
Tony-LunarG4c253372022-01-18 13:51:07 -07001/* Copyright (c) 2020-2022 The Khronos Group Inc.
2 * Copyright (c) 2020-2022 Valve Corporation
3 * Copyright (c) 2020-2022 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) {
Jeremy Gebben36a3b832022-03-23 10:54:18 -060042 // Use a local variable to query features since this method runs in the instance validation object.
43 // To avoid confusion and race conditions about which physical device's features are stored in the
44 // 'supported_devices' member variable, it will only be set in the device validation objects.
45 // See CreateDevice() below.
46 VkPhysicalDeviceFeatures gpu_supported_features;
47 DispatchGetPhysicalDeviceFeatures(gpu, &gpu_supported_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -060048 VkPhysicalDeviceFeatures features = {};
49 features.vertexPipelineStoresAndAtomics = true;
50 features.fragmentStoresAndAtomics = true;
Jeremy Gebben36a3b832022-03-23 10:54:18 -060051 UtilPreCallRecordCreateDevice(gpu, reinterpret_cast<safe_VkDeviceCreateInfo *>(modified_create_info), gpu_supported_features,
Mark Lobodzinskib588cd42020-09-30 11:03:34 -060052 features);
Tony-LunarG04717522019-10-17 10:41:17 -060053}
Tony-LunarG1dce2392019-10-23 16:49:29 -060054
Tony-LunarG04717522019-10-17 10:41:17 -060055// Perform initializations that can be done at Create Device time.
Jeremy Gebben36a3b832022-03-23 10:54:18 -060056void DebugPrintf::CreateDevice(const VkDeviceCreateInfo *pCreateInfo) {
57 ValidationStateTracker::CreateDevice(pCreateInfo);
Tony-LunarG43416b42019-10-31 16:47:24 -060058
59 const char *size_string = getLayerOption("khronos_validation.printf_buffer_size");
Jeremy Gebben36a3b832022-03-23 10:54:18 -060060 output_buffer_size = *size_string ? atoi(size_string) : 1024;
Tony-LunarGc99dbef2021-06-14 15:11:50 -060061
62 std::string verbose_string = getLayerOption("khronos_validation.printf_verbose");
63 transform(verbose_string.begin(), verbose_string.end(), verbose_string.begin(), ::tolower);
Jeremy Gebben36a3b832022-03-23 10:54:18 -060064 verbose = verbose_string.length() ? !verbose_string.compare("true") : false;
Tony-LunarGc99dbef2021-06-14 15:11:50 -060065
66 std::string stdout_string = getLayerOption("khronos_validation.printf_to_stdout");
67 transform(stdout_string.begin(), stdout_string.end(), stdout_string.begin(), ::tolower);
Jeremy Gebben36a3b832022-03-23 10:54:18 -060068 use_stdout = stdout_string.length() ? !stdout_string.compare("true") : false;
69 if (getenv("DEBUG_PRINTF_TO_STDOUT")) use_stdout = true;
Tony-LunarG04717522019-10-17 10:41:17 -060070
Jeremy Gebben36a3b832022-03-23 10:54:18 -060071 if (phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Tony-LunarGbbbed672020-03-04 10:51:11 -070072 ReportSetupProblem(device, "Debug Printf requires Vulkan 1.1 or later. Debug Printf disabled.");
Jeremy Gebben36a3b832022-03-23 10:54:18 -060073 aborted = true;
Tony-LunarG04717522019-10-17 10:41:17 -060074 return;
75 }
76
Jeremy Gebben36a3b832022-03-23 10:54:18 -060077 DispatchGetPhysicalDeviceFeatures(physical_device, &supported_features);
Tony-LunarG04717522019-10-17 10:41:17 -060078 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Tony-LunarG1dce2392019-10-23 16:49:29 -060079 ReportSetupProblem(device,
Tony-LunarGbbbed672020-03-04 10:51:11 -070080 "Debug Printf requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
81 "Debug Printf disabled.");
Jeremy Gebben36a3b832022-03-23 10:54:18 -060082 aborted = true;
Tony-LunarG04717522019-10-17 10:41:17 -060083 return;
84 }
Tony-LunarG9586e732020-03-04 10:50:30 -070085
Mark Lobodzinski90eea5b2020-05-15 12:54:00 -060086 if (enabled[gpu_validation]) {
Tony-LunarG9586e732020-03-04 10:50:30 -070087 ReportSetupProblem(device,
88 "Debug Printf cannot be enabled when gpu assisted validation is enabled. "
89 "Debug Printf disabled.");
Jeremy Gebben36a3b832022-03-23 10:54:18 -060090 aborted = true;
Tony-LunarG9586e732020-03-04 10:50:30 -070091 return;
92 }
93
Tony-LunarG1dce2392019-10-23 16:49:29 -060094 std::vector<VkDescriptorSetLayoutBinding> bindings;
95 VkDescriptorSetLayoutBinding binding = {3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
Tony-LunarGc7ed2082020-06-11 14:00:04 -060096 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_MESH_BIT_NV |
97 VK_SHADER_STAGE_TASK_BIT_NV | VK_SHADER_STAGE_COMPUTE_BIT |
98 kShaderStageAllRayTracing,
Tony-LunarG1dce2392019-10-23 16:49:29 -060099 NULL};
100 bindings.push_back(binding);
Jeremy Gebben36a3b832022-03-23 10:54:18 -0600101 UtilPostCallRecordCreateDevice(pCreateInfo, bindings, this, phys_dev_props);
Tony-LunarG04717522019-10-17 10:41:17 -0600102}
103
Tony-LunarGb5fae462020-03-05 12:43:25 -0700104void DebugPrintf::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
105 UtilPreCallRecordDestroyDevice(this);
Tony-LunarG0a863bc2020-09-16 09:50:04 -0600106 ValidationStateTracker::PreCallRecordDestroyDevice(device, pAllocator);
107 // State Tracker can end up making vma calls through callbacks - don't destroy allocator until ST is done
108 if (vmaAllocator) {
109 vmaDestroyAllocator(vmaAllocator);
110 }
111 desc_set_manager.reset();
Tony-LunarG04717522019-10-17 10:41:17 -0600112}
113
114// 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 -0700115void DebugPrintf::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
116 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
117 void *cpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600118 if (aborted) {
119 return;
120 }
121
122 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
123
124 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
125 std::ostringstream strm;
126 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Tony-LunarGbbbed672020-03-04 10:51:11 -0700127 << "Application has too many descriptor sets in the pipeline layout to continue with debug printf. "
Tony-LunarG04717522019-10-17 10:41:17 -0600128 << "Not modifying the pipeline layout. "
129 << "Instrumented shaders are replaced with non-instrumented shaders.";
Tony-LunarG1dce2392019-10-23 16:49:29 -0600130 ReportSetupProblem(device, strm.str().c_str());
Tony-LunarG04717522019-10-17 10:41:17 -0600131 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700132 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Tony-LunarG04717522019-10-17 10:41:17 -0600133 }
134}
135
Tony-LunarGb5fae462020-03-05 12:43:25 -0700136void DebugPrintf::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
137 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
138 VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -0600139 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
140 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600141 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600142 aborted = true;
143 }
144}
145
146// Free the device memory and descriptor set associated with a command buffer.
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600147void DebugPrintf::DestroyBuffer(DPFBufferInfo &buffer_info) {
148 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
149 if (buffer_info.desc_set != VK_NULL_HANDLE) {
150 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Tony-LunarG04717522019-10-17 10:41:17 -0600151 }
Tony-LunarG04717522019-10-17 10:41:17 -0600152}
153
154// Just gives a warning about a possible deadlock.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700155bool DebugPrintf::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
156 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
157 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
158 uint32_t bufferMemoryBarrierCount,
159 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
160 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG04717522019-10-17 10:41:17 -0600161 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600162 ReportSetupProblem(commandBuffer,
163 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
Tony-LunarGbbbed672020-03-04 10:51:11 -0700164 "Debug Printf waits on queue completion. "
Tony-LunarG1dce2392019-10-23 16:49:29 -0600165 "This wait could block the host's signaling of this event, resulting in deadlock.");
Tony-LunarG04717522019-10-17 10:41:17 -0600166 }
167 return false;
168}
169
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700170bool DebugPrintf::PreCallValidateCmdWaitEvents2KHR(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
171 const VkDependencyInfoKHR *pDependencyInfos) const {
Jeremy Gebbenf18d4362022-01-27 14:37:25 -0700172 VkPipelineStageFlags2KHR src_stage_mask = 0;
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700173
174 for (uint32_t i = 0; i < eventCount; i++) {
175 auto stage_masks = sync_utils::GetGlobalStageMasks(pDependencyInfos[i]);
Jeremy Gebbenf18d4362022-01-27 14:37:25 -0700176 src_stage_mask |= stage_masks.src;
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700177 }
178
Jeremy Gebbenf18d4362022-01-27 14:37:25 -0700179 if (src_stage_mask & VK_PIPELINE_STAGE_HOST_BIT) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700180 ReportSetupProblem(commandBuffer,
181 "CmdWaitEvents2KHR recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
182 "Debug Printf waits on queue completion. "
183 "This wait could block the host's signaling of this event, resulting in deadlock.");
184 }
185 return false;
186}
187
Tony-LunarG1364cf52021-11-17 16:10:11 -0700188bool DebugPrintf::PreCallValidateCmdWaitEvents2(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
189 const VkDependencyInfo *pDependencyInfos) const {
Jeremy Gebbenf18d4362022-01-27 14:37:25 -0700190 VkPipelineStageFlags2 src_stage_mask = 0;
Tony-LunarG1364cf52021-11-17 16:10:11 -0700191
192 for (uint32_t i = 0; i < eventCount; i++) {
193 auto stage_masks = sync_utils::GetGlobalStageMasks(pDependencyInfos[i]);
Jeremy Gebbenf18d4362022-01-27 14:37:25 -0700194 src_stage_mask |= stage_masks.src;
Tony-LunarG1364cf52021-11-17 16:10:11 -0700195 }
196
Jeremy Gebbenf18d4362022-01-27 14:37:25 -0700197 if (src_stage_mask & VK_PIPELINE_STAGE_HOST_BIT) {
Tony-LunarG1364cf52021-11-17 16:10:11 -0700198 ReportSetupProblem(commandBuffer,
199 "CmdWaitEvents2 recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
200 "Debug Printf waits on queue completion. "
201 "This wait could block the host's signaling of this event, resulting in deadlock.");
202 }
203 return false;
204}
205
Tony-LunarGb5fae462020-03-05 12:43:25 -0700206void DebugPrintf::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
207 const VkGraphicsPipelineCreateInfo *pCreateInfos,
208 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
209 void *cgpl_state_data) {
Tony-LunarG00e7b7d2021-06-30 12:59:43 -0600210 if (aborted) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600211 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
212 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700213 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
214 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600215 cgpl_state->printf_create_infos = new_pipeline_create_infos;
216 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->printf_create_infos.data());
217}
218
Tony-LunarGb5fae462020-03-05 12:43:25 -0700219void DebugPrintf::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
220 const VkComputePipelineCreateInfo *pCreateInfos,
221 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
222 void *ccpl_state_data) {
Tony-LunarG00e7b7d2021-06-30 12:59:43 -0600223 if (aborted) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600224 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
225 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700226 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
227 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600228 ccpl_state->printf_create_infos = new_pipeline_create_infos;
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600229 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->printf_create_infos.data());
Tony-LunarG04717522019-10-17 10:41:17 -0600230}
231
Tony-LunarGb5fae462020-03-05 12:43:25 -0700232void DebugPrintf::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
233 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
234 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
235 void *crtpl_state_data) {
Tony-LunarG00e7b7d2021-06-30 12:59:43 -0600236 if (aborted) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600237 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
238 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700239 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
240 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600241 crtpl_state->printf_create_infos = new_pipeline_create_infos;
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600242 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->printf_create_infos.data());
Tony-LunarG04717522019-10-17 10:41:17 -0600243}
244
sourav parmarcd5fb182020-07-17 12:58:44 -0700245void DebugPrintf::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
246 VkPipelineCache pipelineCache, uint32_t count,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700247 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
248 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
249 void *crtpl_state_data) {
Tony-LunarG00e7b7d2021-06-30 12:59:43 -0600250 if (aborted) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600251 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
252 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700253 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
254 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600255 crtpl_state->printf_create_infos = new_pipeline_create_infos;
256 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->printf_create_infos.data());
Tony-LunarG04717522019-10-17 10:41:17 -0600257}
Tony-LunarG04717522019-10-17 10:41:17 -0600258
Tony-LunarGb5fae462020-03-05 12:43:25 -0700259void DebugPrintf::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
260 const VkGraphicsPipelineCreateInfo *pCreateInfos,
261 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
262 VkResult result, void *cgpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600263 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
264 pPipelines, result, cgpl_state_data);
Tony-LunarG00e7b7d2021-06-30 12:59:43 -0600265 if (aborted) return;
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600266 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
267 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, cgpl_state->printf_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -0700268 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600269}
270
Tony-LunarGb5fae462020-03-05 12:43:25 -0700271void DebugPrintf::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
272 const VkComputePipelineCreateInfo *pCreateInfos,
273 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
274 VkResult result, void *ccpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600275 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
276 result, ccpl_state_data);
Tony-LunarG00e7b7d2021-06-30 12:59:43 -0600277 if (aborted) return;
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600278 create_compute_pipeline_api_state *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
279 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, ccpl_state->printf_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -0700280 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600281}
282
Tony-LunarGb5fae462020-03-05 12:43:25 -0700283void DebugPrintf::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
284 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
285 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
286 VkResult result, void *crtpl_state_data) {
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600287 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarG04717522019-10-17 10:41:17 -0600288 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
289 pPipelines, result, crtpl_state_data);
Tony-LunarG00e7b7d2021-06-30 12:59:43 -0600290 if (aborted) return;
Tony-LunarG9b9dc022020-10-08 13:55:37 -0600291 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->printf_create_infos.data());
Tony-LunarGb5fae462020-03-05 12:43:25 -0700292 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600293}
294
Tony-LunarGfb2ab872021-01-13 15:17:15 -0700295void DebugPrintf::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
296 VkPipelineCache pipelineCache, uint32_t count,
297 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
298 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
299 VkResult result, void *crtpl_state_data) {
300 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
301 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesKHR(
302 device, deferredOperation, pipelineCache, count, pCreateInfos, pAllocator, pPipelines, result, crtpl_state_data);
Tony-LunarG00e7b7d2021-06-30 12:59:43 -0600303 if (aborted) return;
Tony-LunarGfb2ab872021-01-13 15:17:15 -0700304 UtilCopyCreatePipelineFeedbackData(count, pCreateInfos, crtpl_state->printf_create_infos.data());
aitor-lunarg3c145292022-03-25 17:30:11 +0100305
306 bool is_operation_deferred = (deferredOperation != VK_NULL_HANDLE && result == VK_OPERATION_DEFERRED_KHR);
307 if (is_operation_deferred) {
308 std::vector<safe_VkRayTracingPipelineCreateInfoKHR> infos{pCreateInfos, pCreateInfos + count};
309 auto register_fn = [this, infos, pAllocator](const std::vector<VkPipeline> &pipelines) {
310 UtilPostCallRecordPipelineCreations(static_cast<uint32_t>(infos.size()),
311 reinterpret_cast<const VkRayTracingPipelineCreateInfoKHR *>(infos.data()),
312 pAllocator, pipelines.data(), VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
313 };
314
315 auto layer_data = GetLayerDataPtr(get_dispatch_key(device), layer_data_map);
316 if (wrap_handles) {
317 deferredOperation = layer_data->Unwrap(deferredOperation);
318 }
319 std::vector<std::function<void(const std::vector<VkPipeline> &)>> cleanup_fn;
320 auto find_res = layer_data->deferred_operation_post_check.pop(deferredOperation);
321 if (find_res->first) {
322 cleanup_fn = std::move(find_res->second);
323 }
324 cleanup_fn.emplace_back(register_fn);
325 layer_data->deferred_operation_post_check.insert(deferredOperation, cleanup_fn);
326 } else {
327 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR,
328 this);
329 }
Tony-LunarGfb2ab872021-01-13 15:17:15 -0700330}
331
Tony-LunarG04717522019-10-17 10:41:17 -0600332// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700333void DebugPrintf::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG04717522019-10-17 10:41:17 -0600334 for (auto it = shader_map.begin(); it != shader_map.end();) {
335 if (it->second.pipeline == pipeline) {
336 it = shader_map.erase(it);
337 } else {
338 ++it;
339 }
340 }
341 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
342}
343// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
sfricke-samsung7fac88a2022-01-26 11:44:22 -0800344bool DebugPrintf::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<uint32_t> &new_pgm,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700345 uint32_t *unique_shader_id) {
Tony-LunarG04717522019-10-17 10:41:17 -0600346 if (aborted) return false;
347 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
348
349 // Load original shader SPIR-V
350 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
351 new_pgm.clear();
352 new_pgm.reserve(num_words);
353 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
354
355 // Call the optimizer to instrument the shader.
356 // Use the unique_shader_module_id as a shader ID so we can look up its handle later in the shader_map.
357 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
358 using namespace spvtools;
sfricke-samsung45996a42021-09-16 13:45:27 -0700359 spv_target_env target_env = PickSpirvEnv(api_version, IsExtEnabled(device_extensions.vk_khr_spirv_1_4));
Tony-LunarGf29f77f2020-08-26 15:48:00 -0600360 spvtools::ValidatorOptions val_options;
361 AdjustValidatorOptions(device_extensions, enabled_features, val_options);
362 spvtools::OptimizerOptions opt_options;
363 opt_options.set_run_validator(true);
364 opt_options.set_validator_options(val_options);
Tony-LunarG04717522019-10-17 10:41:17 -0600365 Optimizer optimizer(target_env);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700366 const spvtools::MessageConsumer debug_printf_console_message_consumer =
Tony-LunarG79641702020-07-13 15:43:05 -0600367 [this](spv_message_level_t level, const char *, const spv_position_t &position, const char *message) -> void {
368 switch (level) {
369 case SPV_MSG_FATAL:
370 case SPV_MSG_INTERNAL_ERROR:
371 case SPV_MSG_ERROR:
372 this->LogError(this->device, "UNASSIGNED-Debug-Printf", "Error during shader instrumentation: line %zu: %s",
373 position.index, message);
374 break;
375 default:
376 break;
377 }
378 };
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700379 optimizer.SetMessageConsumer(debug_printf_console_message_consumer);
Tony-LunarG04717522019-10-17 10:41:17 -0600380 optimizer.RegisterPass(CreateInstDebugPrintfPass(desc_set_bind_index, unique_shader_module_id));
Tony-LunarGf29f77f2020-08-26 15:48:00 -0600381 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm, opt_options);
Tony-LunarG04717522019-10-17 10:41:17 -0600382 if (!pass) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600383 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Tony-LunarG04717522019-10-17 10:41:17 -0600384 }
385 *unique_shader_id = unique_shader_module_id++;
386 return pass;
387}
388// Create the instrumented shader data to provide to the driver.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700389void DebugPrintf::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
390 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
391 void *csm_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600392 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
393 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
394 if (pass) {
395 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
sfricke-samsung7fac88a2022-01-26 11:44:22 -0800396 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(uint32_t);
Tony-LunarG04717522019-10-17 10:41:17 -0600397 }
398}
Tony-LunarG04717522019-10-17 10:41:17 -0600399
400vartype vartype_lookup(char intype) {
401 switch (intype) {
402 case 'd':
403 case 'i':
404 return varsigned;
405 break;
406
407 case 'f':
408 case 'F':
409 case 'a':
410 case 'A':
411 case 'e':
412 case 'E':
413 case 'g':
414 case 'G':
415 return varfloat;
416 break;
417
418 case 'u':
419 case 'x':
420 case 'o':
421 default:
422 return varunsigned;
423 break;
424 }
425}
426
Tony-LunarGa19e31e2020-03-30 13:30:29 -0600427std::vector<DPFSubstring> DebugPrintf::ParseFormatString(const std::string format_string) {
428 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 -0700429 std::vector<DPFSubstring> parsed_strings;
Tony-LunarG04717522019-10-17 10:41:17 -0600430 size_t pos = 0;
431 size_t begin = 0;
432 size_t percent = 0;
433
434 while (begin < format_string.length()) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700435 DPFSubstring substring;
Tony-LunarG04717522019-10-17 10:41:17 -0600436
437 // Find a percent sign
438 pos = percent = format_string.find_first_of('%', pos);
439 if (pos == std::string::npos) {
440 // End of the format string Push the rest of the characters
441 substring.string = format_string.substr(begin, format_string.length());
442 substring.needs_value = false;
443 parsed_strings.push_back(substring);
444 break;
445 }
446 pos++;
447 if (format_string[pos] == '%') {
448 pos++;
449 continue; // %% - skip it
450 }
451 // Find the type of the value
452 pos = format_string.find_first_of(types, pos);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700453 if (pos == format_string.npos) {
Tony-LunarG04717522019-10-17 10:41:17 -0600454 // This really shouldn't happen with a legal value string
455 pos = format_string.length();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700456 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600457 char tempstring[32];
458 int count = 0;
459 std::string specifier = {};
460
461 if (format_string[pos] == 'v') {
462 // Vector must be of size 2, 3, or 4
463 // and format %v<size><type>
464 specifier = format_string.substr(percent, pos - percent);
465 count = atoi(&format_string[pos + 1]);
466 pos += 2;
467
468 // skip v<count>, handle long
469 specifier.push_back(format_string[pos]);
470 if (format_string[pos + 1] == 'l') {
471 specifier.push_back('l');
472 pos++;
473 }
474
475 // Take the preceding characters, and the percent through the type
476 substring.string = format_string.substr(begin, percent - begin);
477 substring.string += specifier;
478 substring.needs_value = true;
479 substring.type = vartype_lookup(specifier.back());
480 parsed_strings.push_back(substring);
481
482 // Continue with a comma separated list
483 sprintf(tempstring, ", %s", specifier.c_str());
484 substring.string = tempstring;
485 for (int i = 0; i < (count - 1); i++) {
486 parsed_strings.push_back(substring);
487 }
488 } else {
489 // Single non-vector value
490 if (format_string[pos + 1] == 'l') pos++; // Save long size
491 substring.string = format_string.substr(begin, pos - begin + 1);
492 substring.needs_value = true;
493 substring.type = vartype_lookup(format_string[pos]);
494 parsed_strings.push_back(substring);
495 }
496 begin = pos + 1;
497 }
498 }
499 return parsed_strings;
500}
501
sfricke-samsung7fac88a2022-01-26 11:44:22 -0800502std::string DebugPrintf::FindFormatString(std::vector<uint32_t> pgm, uint32_t string_id) {
Tony-LunarG04717522019-10-17 10:41:17 -0600503 std::string format_string;
sfricke-samsungef15e482022-01-26 11:32:49 -0800504 SHADER_MODULE_STATE module_state(pgm);
505 if (module_state.words.size() > 0) {
506 for (const auto &insn : module_state) {
Tony-LunarG04717522019-10-17 10:41:17 -0600507 if (insn.opcode() == spv::OpString) {
508 uint32_t offset = insn.offset();
509 if (pgm[offset + 1] == string_id) {
510 format_string = reinterpret_cast<char *>(&pgm[offset + 2]);
511 break;
512 }
513 }
514 }
515 }
516
517 return format_string;
518}
519
Corentin Wallez171ac5e2020-03-31 16:09:05 +0200520// GCC and clang don't like using variables as format strings in sprintf.
521// #pragma GCC is recognized by both compilers
522#if defined(__GNUC__) || defined(__clang__)
Tony-LunarG04717522019-10-17 10:41:17 -0600523#pragma GCC diagnostic push
524#pragma GCC diagnostic ignored "-Wformat-security"
525#endif
526
Tony-LunarGb5fae462020-03-05 12:43:25 -0700527void snprintf_with_malloc(std::stringstream &shader_message, DPFSubstring substring, size_t needed, void *values) {
Tony-LunarG04717522019-10-17 10:41:17 -0600528 char *buffer = static_cast<char *>(malloc((needed + 1) * sizeof(char))); // Add 1 for terminator
529 if (substring.longval) {
530 snprintf(buffer, needed, substring.string.c_str(), substring.longval);
531 } else if (!substring.needs_value) {
532 snprintf(buffer, needed, substring.string.c_str());
533 } else {
534 switch (substring.type) {
535 case varunsigned:
536 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<uint32_t *>(values) - 1);
537 break;
538
539 case varsigned:
540 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<int32_t *>(values) - 1);
541 break;
542
543 case varfloat:
544 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<float *>(values) - 1);
545 break;
546 }
547 }
548 shader_message << buffer;
549 free(buffer);
550}
551
Tony-LunarG7de10e82020-11-24 11:31:55 -0700552void DebugPrintf::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, DPFBufferInfo &buffer_info,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700553 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Tony-LunarG04717522019-10-17 10:41:17 -0600554 // Word Content
555 // 0 Size of output record, including this word
556 // 1 Shader ID
557 // 2 Instruction Position
558 // 3 Stage Ordinal
559 // 4 Stage - specific Info Word 0
560 // 5 Stage - specific Info Word 1
561 // 6 Stage - specific Info Word 2
562 // 7 Printf Format String Id
563 // 8 Printf Values Word 0 (optional)
564 // 9 Printf Values Word 1 (optional)
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600565 uint32_t expect = debug_output_buffer[0];
566 if (!expect) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600567
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600568 uint32_t index = 1;
Tony-LunarG04717522019-10-17 10:41:17 -0600569 while (debug_output_buffer[index]) {
Tony-LunarG04717522019-10-17 10:41:17 -0600570 std::stringstream shader_message;
Tony-LunarG04717522019-10-17 10:41:17 -0600571 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
572 VkPipeline pipeline_handle = VK_NULL_HANDLE;
sfricke-samsung7fac88a2022-01-26 11:44:22 -0800573 std::vector<uint32_t> pgm;
Tony-LunarG04717522019-10-17 10:41:17 -0600574
Tony-LunarGb5fae462020-03-05 12:43:25 -0700575 DPFOutputRecord *debug_record = reinterpret_cast<DPFOutputRecord *>(&debug_output_buffer[index]);
Tony-LunarG04717522019-10-17 10:41:17 -0600576 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
577 // by the instrumented shader.
578 auto it = shader_map.find(debug_record->shader_id);
579 if (it != shader_map.end()) {
580 shader_module_handle = it->second.shader_module;
581 pipeline_handle = it->second.pipeline;
582 pgm = it->second.pgm;
583 }
584 // Search through the shader source for the printf format string for this invocation
585 auto format_string = FindFormatString(pgm, debug_record->format_string_id);
586 // Break the format string into strings with 1 or 0 value
587 auto format_substrings = ParseFormatString(format_string);
588 void *values = static_cast<void *>(&debug_record->values);
589 const uint32_t static_size = 1024;
590 // Sprintf each format substring into a temporary string then add that to the message
591 for (auto &substring : format_substrings) {
592 char temp_string[static_size];
593 size_t needed = 0;
Tony-LunarGef469c92021-05-14 06:33:22 -0600594 std::vector<std::string> format_strings = { "%ul", "%lu", "%lx" };
595 size_t ul_pos = 0;
596 bool print_hex = true;
597 for (auto ul_string : format_strings) {
598 ul_pos = substring.string.find(ul_string);
599 if (ul_pos != std::string::npos) {
600 if (ul_string == "%lu") print_hex = false;
601 break;
602 }
603 }
Tony-LunarG04717522019-10-17 10:41:17 -0600604 if (ul_pos != std::string::npos) {
605 // Unsigned 64 bit value
606 substring.longval = *static_cast<uint64_t *>(values);
607 values = static_cast<uint64_t *>(values) + 1;
Tony-LunarGef469c92021-05-14 06:33:22 -0600608 if (print_hex) {
609 substring.string.replace(ul_pos + 1, 2, PRIx64);
610 } else {
611 substring.string.replace(ul_pos + 1, 2, PRIu64);
612 }
Tony-LunarG04717522019-10-17 10:41:17 -0600613 needed = snprintf(temp_string, static_size, substring.string.c_str(), substring.longval);
614 } else {
615 if (substring.needs_value) {
616 switch (substring.type) {
617 case varunsigned:
618 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<uint32_t *>(values));
619 break;
620
621 case varsigned:
622 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<int32_t *>(values));
623 break;
624
625 case varfloat:
626 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<float *>(values));
627 break;
628 }
629 values = static_cast<uint32_t *>(values) + 1;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700630 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600631 needed = snprintf(temp_string, static_size, substring.string.c_str());
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700632 }
Tony-LunarG04717522019-10-17 10:41:17 -0600633 }
634
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700635 if (needed < static_size) {
Tony-LunarG04717522019-10-17 10:41:17 -0600636 shader_message << temp_string;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700637 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600638 // Static buffer not big enough for message, use malloc to get enough
639 snprintf_with_malloc(shader_message, substring, needed, values);
640 }
641 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600642
643 if (verbose) {
644 std::string stage_message;
645 std::string common_message;
646 std::string filename_message;
647 std::string source_message;
Tony-LunarGb5fae462020-03-05 12:43:25 -0700648 UtilGenerateStageMessage(&debug_output_buffer[index], stage_message);
649 UtilGenerateCommonMessage(report_data, command_buffer, &debug_output_buffer[index], shader_module_handle,
Tony-LunarG7de10e82020-11-24 11:31:55 -0700650 pipeline_handle, buffer_info.pipeline_bind_point, operation_index, common_message);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700651 UtilGenerateSourceMessages(pgm, &debug_output_buffer[index], true, filename_message, source_message);
Tony-LunarG43416b42019-10-31 16:47:24 -0600652 if (use_stdout) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600653 std::cout << "UNASSIGNED-DEBUG-PRINTF " << common_message.c_str() << " " << stage_message.c_str() << " "
Tony-LunarGb5fae462020-03-05 12:43:25 -0700654 << shader_message.str().c_str() << " " << filename_message.c_str() << " " << source_message.c_str();
Tony-LunarG43416b42019-10-31 16:47:24 -0600655 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600656 LogInfo(queue, "UNASSIGNED-DEBUG-PRINTF", "%s %s %s %s%s", common_message.c_str(), stage_message.c_str(),
657 shader_message.str().c_str(), filename_message.c_str(), source_message.c_str());
Tony-LunarG43416b42019-10-31 16:47:24 -0600658 }
659 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600660 if (use_stdout) {
Tony-LunarG43416b42019-10-31 16:47:24 -0600661 std::cout << shader_message.str();
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600662 } else {
663 // Don't let LogInfo process any '%'s in the string
664 LogInfo(device, "UNASSIGNED-DEBUG-PRINTF", "%s", shader_message.str().c_str());
665 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600666 }
Tony-LunarG04717522019-10-17 10:41:17 -0600667 index += debug_record->size;
668 }
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600669 if ((index - 1) != expect) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600670 LogWarning(device, "UNASSIGNED-DEBUG-PRINTF",
671 "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 -0600672 }
Tony-LunarG04717522019-10-17 10:41:17 -0600673 memset(debug_output_buffer, 0, 4 * (debug_output_buffer[0] + 1));
674}
Tony-LunarG43416b42019-10-31 16:47:24 -0600675
Tony-LunarG04717522019-10-17 10:41:17 -0600676#if defined(__GNUC__)
677#pragma GCC diagnostic pop
678#endif
679
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700680bool DebugPrintf::CommandBufferNeedsProcessing(VkCommandBuffer command_buffer) {
681 bool buffers_present = false;
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -0600682 auto cb_node = Get<debug_printf_state::CommandBuffer>(command_buffer);
Jeremy Gebben9f537102021-10-05 16:37:12 -0600683 if (GetBufferInfo(cb_node.get()).size()) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700684 buffers_present = true;
685 }
John Zulauf79f06582021-02-27 18:38:39 -0700686 for (const auto *secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600687 if (GetBufferInfo(secondaryCmdBuffer).size()) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700688 buffers_present = true;
689 }
690 }
691 return buffers_present;
692}
693
694void DebugPrintf::ProcessCommandBuffer(VkQueue queue, VkCommandBuffer command_buffer) {
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -0600695 auto cb_node = Get<debug_printf_state::CommandBuffer>(command_buffer);
Jeremy Gebben9f537102021-10-05 16:37:12 -0600696 UtilProcessInstrumentationBuffer(queue, cb_node.get(), this);
John Zulauf79f06582021-02-27 18:38:39 -0700697 for (auto *secondary_cmd_buffer : cb_node->linkedCommandBuffers) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700698 UtilProcessInstrumentationBuffer(queue, secondary_cmd_buffer, this);
699 }
700}
701
Tony-LunarG04717522019-10-17 10:41:17 -0600702// Issue a memory barrier to make GPU-written data available to host.
703// Wait for the queue to complete execution.
704// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700705void DebugPrintf::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
706 VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -0600707 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
708
Mark Lobodzinski09379db2020-05-07 08:22:01 -0600709 if (aborted || (result != VK_SUCCESS)) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600710 bool buffers_present = false;
711 // Don't QueueWaitIdle if there's nothing to process
712 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
713 const VkSubmitInfo *submit = &pSubmits[submit_idx];
714 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700715 buffers_present |= CommandBufferNeedsProcessing(submit->pCommandBuffers[i]);
Tony-LunarG04717522019-10-17 10:41:17 -0600716 }
717 }
718 if (!buffers_present) return;
719
Tony-LunarGb5fae462020-03-05 12:43:25 -0700720 UtilSubmitBarrier(queue, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600721
722 DispatchQueueWaitIdle(queue);
723
724 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
725 const VkSubmitInfo *submit = &pSubmits[submit_idx];
726 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700727 ProcessCommandBuffer(queue, submit->pCommandBuffers[i]);
728 }
729 }
730}
731
Tony-LunarG26fe2842021-11-16 14:07:59 -0700732void DebugPrintf::RecordQueueSubmit2(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2 *pSubmits, VkFence fence,
733 VkResult result) {
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700734 if (aborted || (result != VK_SUCCESS)) return;
735 bool buffers_present = false;
736 // Don't QueueWaitIdle if there's nothing to process
737 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
738 const auto *submit = &pSubmits[submit_idx];
739 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
740 buffers_present |= CommandBufferNeedsProcessing(submit->pCommandBufferInfos[i].commandBuffer);
741 }
742 }
743 if (!buffers_present) return;
744
745 UtilSubmitBarrier(queue, this);
746
747 DispatchQueueWaitIdle(queue);
748
749 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
Tony-LunarG26fe2842021-11-16 14:07:59 -0700750 const VkSubmitInfo2 *submit = &pSubmits[submit_idx];
Jeremy Gebbena3705f42021-01-19 16:47:43 -0700751 for (uint32_t i = 0; i < submit->commandBufferInfoCount; i++) {
752 ProcessCommandBuffer(queue, submit->pCommandBufferInfos[i].commandBuffer);
Tony-LunarG04717522019-10-17 10:41:17 -0600753 }
754 }
755}
756
Tony-LunarG26fe2842021-11-16 14:07:59 -0700757void DebugPrintf::PostCallRecordQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR *pSubmits,
758 VkFence fence, VkResult result) {
759 ValidationStateTracker::PostCallRecordQueueSubmit2KHR(queue, submitCount, pSubmits, fence, result);
760 RecordQueueSubmit2(queue, submitCount, pSubmits, fence, result);
761}
762
763void DebugPrintf::PostCallRecordQueueSubmit2(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2 *pSubmits, VkFence fence,
764 VkResult result) {
765 ValidationStateTracker::PostCallRecordQueueSubmit2(queue, submitCount, pSubmits, fence, result);
766 RecordQueueSubmit2(queue, submitCount, pSubmits, fence, result);
767}
768
Tony-LunarGb5fae462020-03-05 12:43:25 -0700769void DebugPrintf::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
770 uint32_t firstVertex, uint32_t firstInstance) {
771 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600772}
773
Tony-LunarG745150c2021-07-02 15:07:31 -0600774void DebugPrintf::PreCallRecordCmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint32_t drawCount,
775 const VkMultiDrawInfoEXT *pVertexInfo, uint32_t instanceCount,
776 uint32_t firstInstance, uint32_t stride) {
777 for(uint32_t i = 0; i < drawCount; i++) {
778 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
779 }
780}
781
Tony-LunarGb5fae462020-03-05 12:43:25 -0700782void DebugPrintf::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
783 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
784 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600785}
786
Tony-LunarG745150c2021-07-02 15:07:31 -0600787void DebugPrintf::PreCallRecordCmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer, uint32_t drawCount,
788 const VkMultiDrawIndexedInfoEXT *pIndexInfo, uint32_t instanceCount,
789 uint32_t firstInstance, uint32_t stride, const int32_t *pVertexOffset) {
790 for (uint32_t i = 0; i < drawCount; i++) {
791 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
792 }
793}
794
Tony-LunarGb5fae462020-03-05 12:43:25 -0700795void DebugPrintf::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
796 uint32_t stride) {
797 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600798}
799
Tony-LunarGb5fae462020-03-05 12:43:25 -0700800void DebugPrintf::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
801 uint32_t count, uint32_t stride) {
802 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600803}
804
Tony-LunarGb5fae462020-03-05 12:43:25 -0700805void DebugPrintf::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
806 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600807}
808
Tony-LunarGb5fae462020-03-05 12:43:25 -0700809void DebugPrintf::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
810 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600811}
812
Tony-LunarGd13f9b52020-09-08 15:45:45 -0600813void DebugPrintf::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
814 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
815 uint32_t groupCountZ) {
816 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
817}
818
Tony-LunarG52c8c602020-09-10 16:29:56 -0600819void DebugPrintf::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
820 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
821 uint32_t groupCountZ) {
822 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
823}
824
Tony-LunarG2fb8ff02020-06-11 12:45:07 -0600825void DebugPrintf::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
826 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
827 uint32_t stride) {
828 ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
829 maxDrawCount, stride);
830 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
831}
832
833void DebugPrintf::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
834 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
835 uint32_t stride) {
836 ValidationStateTracker::PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
837 maxDrawCount, stride);
838 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
839}
840
841void DebugPrintf::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
842 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
843 uint32_t maxDrawCount, uint32_t stride) {
844 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer,
845 countBufferOffset, maxDrawCount, stride);
846 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
847}
848
849void DebugPrintf::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
850 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
851 uint32_t maxDrawCount, uint32_t stride) {
852 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
853 maxDrawCount, stride);
854 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
855}
856
Tony-LunarG54176fb2020-12-02 10:47:22 -0700857void DebugPrintf::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
858 uint32_t firstInstance, VkBuffer counterBuffer,
859 VkDeviceSize counterBufferOffset, uint32_t counterOffset,
860 uint32_t vertexStride) {
861 ValidationStateTracker::PreCallRecordCmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer,
862 counterBufferOffset, counterOffset, vertexStride);
863 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
864}
865
Tony-LunarG2fb8ff02020-06-11 12:45:07 -0600866void DebugPrintf::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
867 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
868 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
869}
870
871void DebugPrintf::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
872 uint32_t drawCount, uint32_t stride) {
873 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
874 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
875}
876
877void DebugPrintf::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
878 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
879 uint32_t maxDrawCount, uint32_t stride) {
880 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer,
881 countBufferOffset, maxDrawCount, stride);
882 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
883}
884
Tony-LunarGb5fae462020-03-05 12:43:25 -0700885void DebugPrintf::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
886 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
887 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
888 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
889 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
890 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
891 uint32_t width, uint32_t height, uint32_t depth) {
892 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
893}
894
895void DebugPrintf::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
Tony-LunarG04717522019-10-17 10:41:17 -0600896 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
897 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
898 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
899 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
900 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
901 uint32_t width, uint32_t height, uint32_t depth) {
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -0600902 auto cb_state = Get<debug_printf_state::CommandBuffer>(commandBuffer);
Tony-LunarG04717522019-10-17 10:41:17 -0600903 cb_state->hasTraceRaysCmd = true;
904}
905
Tony-LunarGb5fae462020-03-05 12:43:25 -0700906void DebugPrintf::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700907 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
908 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
909 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
910 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700911 uint32_t height, uint32_t depth) {
912 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600913}
914
Tony-LunarGb5fae462020-03-05 12:43:25 -0700915void DebugPrintf::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700916 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
917 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
918 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
919 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700920 uint32_t height, uint32_t depth) {
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -0600921 auto cb_state = Get<debug_printf_state::CommandBuffer>(commandBuffer);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600922 cb_state->hasTraceRaysCmd = true;
923}
924
Tony-LunarGb5fae462020-03-05 12:43:25 -0700925void DebugPrintf::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700926 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
927 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
928 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
929 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -0700930 VkDeviceAddress indirectDeviceAddress) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700931 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600932}
933
Tony-LunarGb5fae462020-03-05 12:43:25 -0700934void DebugPrintf::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700935 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
936 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
937 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
938 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -0700939 VkDeviceAddress indirectDeviceAddress) {
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -0600940 auto cb_state = Get<debug_printf_state::CommandBuffer>(commandBuffer);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600941 cb_state->hasTraceRaysCmd = true;
942}
943
Tony-LunarGb5fae462020-03-05 12:43:25 -0700944void DebugPrintf::AllocateDebugPrintfResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Tony-LunarG04717522019-10-17 10:41:17 -0600945 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
946 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
947 return;
948 }
949 VkResult result;
950
951 if (aborted) return;
952
953 std::vector<VkDescriptorSet> desc_sets;
954 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600955 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarG04717522019-10-17 10:41:17 -0600956 assert(result == VK_SUCCESS);
957 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600958 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600959 aborted = true;
960 return;
961 }
962
963 VkDescriptorBufferInfo output_desc_buffer_info = {};
964 output_desc_buffer_info.range = output_buffer_size;
965
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -0600966 auto cb_node = Get<debug_printf_state::CommandBuffer>(cmd_buffer);
Tony-LunarG04717522019-10-17 10:41:17 -0600967 if (!cb_node) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600968 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG04717522019-10-17 10:41:17 -0600969 aborted = true;
970 return;
971 }
972
Nathaniel Cesariobcb79682022-03-31 21:13:52 -0600973 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
974 const auto *pipeline_state = cb_node->lastBound[lv_bind_point].pipeline_state;
975
976 // TODO (ncesario) remove once VK_EXT_graphics_pipeline_library support is added for debug printf
977 if (pipeline_state && pipeline_state->IsGraphicsLibrary()) {
978 ReportSetupProblem(device, "Debug printf does not currently support VK_EXT_graphics_pipeline_library");
979 aborted = true;
980 return;
981 }
982
Tony-LunarG04717522019-10-17 10:41:17 -0600983 // Allocate memory for the output block that the gpu will use to return values for printf
Tony-LunarGb5fae462020-03-05 12:43:25 -0700984 DPFDeviceMemoryBlock output_block = {};
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700985 VkBufferCreateInfo buffer_info = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
986 buffer_info.size = output_buffer_size;
987 buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
988 VmaAllocationCreateInfo alloc_info = {};
989 alloc_info.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
990 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarG04717522019-10-17 10:41:17 -0600991 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600992 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600993 aborted = true;
994 return;
995 }
996
997 // Clear the output block to zeros so that only printf values from the gpu will be present
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700998 uint32_t *data;
999 result = vmaMapMemory(vmaAllocator, output_block.allocation, reinterpret_cast<void **>(&data));
Tony-LunarG04717522019-10-17 10:41:17 -06001000 if (result == VK_SUCCESS) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -07001001 memset(data, 0, output_buffer_size);
Tony-LunarG04717522019-10-17 10:41:17 -06001002 vmaUnmapMemory(vmaAllocator, output_block.allocation);
1003 }
1004
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06001005 auto desc_writes = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarG04717522019-10-17 10:41:17 -06001006 const uint32_t desc_count = 1;
1007
1008 // Write the descriptor
1009 output_desc_buffer_info.buffer = output_block.buffer;
1010 output_desc_buffer_info.offset = 0;
1011
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -06001012 desc_writes.descriptorCount = 1;
1013 desc_writes.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1014 desc_writes.pBufferInfo = &output_desc_buffer_info;
1015 desc_writes.dstSet = desc_sets[0];
1016 desc_writes.dstBinding = 3;
1017 DispatchUpdateDescriptorSets(device, desc_count, &desc_writes, 0, NULL);
Tony-LunarG04717522019-10-17 10:41:17 -06001018
locke-lunargb8d7a7a2020-10-25 16:01:52 -06001019 if (pipeline_state) {
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -07001020 const auto &pipeline_layout = pipeline_state->PipelineLayoutState();
1021 if (pipeline_layout->set_layouts.size() <= desc_set_bind_index) {
1022 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_layout->layout(), desc_set_bind_index, 1,
Tony-LunarG04717522019-10-17 10:41:17 -06001023 desc_sets.data(), 0, nullptr);
1024 }
1025 // Record buffer and memory info in CB state tracking
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06001026 cb_node->buffer_infos.emplace_back(output_block, desc_sets[0], desc_pool, bind_point);
Tony-LunarG04717522019-10-17 10:41:17 -06001027 } else {
Tony-LunarG1dce2392019-10-23 16:49:29 -06001028 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG04717522019-10-17 10:41:17 -06001029 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
1030 aborted = true;
1031 return;
1032 }
1033}
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06001034
1035std::shared_ptr<CMD_BUFFER_STATE> DebugPrintf::CreateCmdBufferState(VkCommandBuffer cb,
1036 const VkCommandBufferAllocateInfo *pCreateInfo,
Jeremy Gebbencd7fa282021-10-27 10:25:32 -06001037 const COMMAND_POOL_STATE *pool) {
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -06001038 return std::static_pointer_cast<CMD_BUFFER_STATE>(
1039 std::make_shared<debug_printf_state::CommandBuffer>(this, cb, pCreateInfo, pool));
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06001040}
1041
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -06001042debug_printf_state::CommandBuffer::CommandBuffer(DebugPrintf *dp, VkCommandBuffer cb,
Jeremy Gebbencd7fa282021-10-27 10:25:32 -06001043 const VkCommandBufferAllocateInfo *pCreateInfo, const COMMAND_POOL_STATE *pool)
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06001044 : CMD_BUFFER_STATE(dp, cb, pCreateInfo, pool) {}
1045
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -06001046void debug_printf_state::CommandBuffer::Reset() {
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -06001047 CMD_BUFFER_STATE::Reset();
1048 auto debug_printf = static_cast<DebugPrintf *>(dev_data);
1049 // Free the device memory and descriptor set(s) associated with a command buffer.
1050 if (debug_printf->aborted) {
1051 return;
1052 }
1053 for (auto &buffer_info : buffer_infos) {
1054 debug_printf->DestroyBuffer(buffer_info);
1055 }
1056 buffer_infos.clear();
1057}