blob: a0b5f6cb984b1321f0e3a9bc5478bb75706854da [file] [log] [blame]
Tony-LunarGb5fae462020-03-05 12:43:25 -07001/* Copyright (c) 2020 The Khronos Group Inc.
2 * Copyright (c) 2020 Valve Corporation
3 * Copyright (c) 2020 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"
25
Tony-LunarG04717522019-10-17 10:41:17 -060026static const VkShaderStageFlags kShaderStageAllRayTracing =
27 VK_SHADER_STAGE_ANY_HIT_BIT_NV | VK_SHADER_STAGE_CALLABLE_BIT_NV | VK_SHADER_STAGE_CLOSEST_HIT_BIT_NV |
28 VK_SHADER_STAGE_INTERSECTION_BIT_NV | VK_SHADER_STAGE_MISS_BIT_NV | VK_SHADER_STAGE_RAYGEN_BIT_NV;
29
Tony-LunarG5af54eb2020-03-27 15:32:51 -060030// Convenience function for reporting problems with setting up Debug Printf.
Tony-LunarG1dce2392019-10-23 16:49:29 -060031template <typename T>
Tony-LunarGb5fae462020-03-05 12:43:25 -070032void DebugPrintf::ReportSetupProblem(T object, const char *const specific_message) const {
Tony-LunarG5af54eb2020-03-27 15:32:51 -060033 LogError(object, "UNASSIGNED-DEBUG-PRINTF ", "Detail: (%s)", specific_message);
Tony-LunarG04717522019-10-17 10:41:17 -060034}
35
36// Turn on necessary device features.
Tony-LunarGb5fae462020-03-05 12:43:25 -070037void DebugPrintf::PreCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *create_info,
38 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice,
39 safe_VkDeviceCreateInfo *modified_create_info) {
Tony-LunarG04717522019-10-17 10:41:17 -060040 DispatchGetPhysicalDeviceFeatures(gpu, &supported_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -060041 VkPhysicalDeviceFeatures features = {};
42 features.vertexPipelineStoresAndAtomics = true;
43 features.fragmentStoresAndAtomics = true;
Tony-LunarGb5fae462020-03-05 12:43:25 -070044 UtilPreCallRecordCreateDevice(gpu, modified_create_info, supported_features, features);
Tony-LunarG04717522019-10-17 10:41:17 -060045}
Tony-LunarG1dce2392019-10-23 16:49:29 -060046
Tony-LunarG04717522019-10-17 10:41:17 -060047// Perform initializations that can be done at Create Device time.
Tony-LunarGb5fae462020-03-05 12:43:25 -070048void DebugPrintf::PostCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
49 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -060050 ValidationStateTracker::PostCallRecordCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice, result);
51
52 ValidationObject *device_object = GetLayerDataPtr(get_dispatch_key(*pDevice), layer_data_map);
53 ValidationObject *validation_data = GetValidationObject(device_object->object_dispatch, this->container_type);
Tony-LunarGb5fae462020-03-05 12:43:25 -070054 DebugPrintf *device_debug_printf = static_cast<DebugPrintf *>(validation_data);
55 device_debug_printf->physicalDevice = physicalDevice;
56 device_debug_printf->device = *pDevice;
Tony-LunarG43416b42019-10-31 16:47:24 -060057
58 const char *size_string = getLayerOption("khronos_validation.printf_buffer_size");
Tony-LunarGb5fae462020-03-05 12:43:25 -070059 device_debug_printf->output_buffer_size = *size_string ? atoi(size_string) : 1024;
Tony-LunarG43416b42019-10-31 16:47:24 -060060 const char *verbose_string = getLayerOption("khronos_validation.printf_verbose");
Tony-LunarGb5fae462020-03-05 12:43:25 -070061 device_debug_printf->verbose = *verbose_string ? !strcmp(verbose_string, "true") : false;
Tony-LunarG43416b42019-10-31 16:47:24 -060062 const char *stdout_string = getLayerOption("khronos_validation.printf_to_stdout");
Tony-LunarGb5fae462020-03-05 12:43:25 -070063 device_debug_printf->use_stdout = *stdout_string ? !strcmp(stdout_string, "true") : false;
64 if (getenv("DEBUG_PRINTF_TO_STDOUT")) device_debug_printf->use_stdout = true;
Tony-LunarG04717522019-10-17 10:41:17 -060065
Tony-LunarGb5fae462020-03-05 12:43:25 -070066 if (device_debug_printf->phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Tony-LunarGbbbed672020-03-04 10:51:11 -070067 ReportSetupProblem(device, "Debug Printf requires Vulkan 1.1 or later. Debug Printf disabled.");
Tony-LunarGb5fae462020-03-05 12:43:25 -070068 device_debug_printf->aborted = true;
Tony-LunarG04717522019-10-17 10:41:17 -060069 return;
70 }
71
72 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Tony-LunarG1dce2392019-10-23 16:49:29 -060073 ReportSetupProblem(device,
Tony-LunarGbbbed672020-03-04 10:51:11 -070074 "Debug Printf requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
75 "Debug Printf disabled.");
Tony-LunarGb5fae462020-03-05 12:43:25 -070076 device_debug_printf->aborted = true;
Tony-LunarG04717522019-10-17 10:41:17 -060077 return;
78 }
Tony-LunarG9586e732020-03-04 10:50:30 -070079
80 if (enabled.gpu_validation) {
81 ReportSetupProblem(device,
82 "Debug Printf cannot be enabled when gpu assisted validation is enabled. "
83 "Debug Printf disabled.");
Tony-LunarGb5fae462020-03-05 12:43:25 -070084 device_debug_printf->aborted = true;
Tony-LunarG9586e732020-03-04 10:50:30 -070085 return;
86 }
87
Tony-LunarG1dce2392019-10-23 16:49:29 -060088 std::vector<VkDescriptorSetLayoutBinding> bindings;
89 VkDescriptorSetLayoutBinding binding = {3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
90 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_COMPUTE_BIT | kShaderStageAllRayTracing,
91 NULL};
92 bindings.push_back(binding);
Tony-LunarGb5fae462020-03-05 12:43:25 -070093 UtilPostCallRecordCreateDevice(pCreateInfo, bindings, device_debug_printf, device_debug_printf->phys_dev_props);
Tony-LunarG04717522019-10-17 10:41:17 -060094}
95
Tony-LunarGb5fae462020-03-05 12:43:25 -070096void DebugPrintf::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
97 UtilPreCallRecordDestroyDevice(this);
Tony-LunarG04717522019-10-17 10:41:17 -060098}
99
100// 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 -0700101void DebugPrintf::PreCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
102 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
103 void *cpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600104 if (aborted) {
105 return;
106 }
107
108 create_pipeline_layout_api_state *cpl_state = reinterpret_cast<create_pipeline_layout_api_state *>(cpl_state_data);
109
110 if (cpl_state->modified_create_info.setLayoutCount >= adjusted_max_desc_sets) {
111 std::ostringstream strm;
112 strm << "Pipeline Layout conflict with validation's descriptor set at slot " << desc_set_bind_index << ". "
Tony-LunarGbbbed672020-03-04 10:51:11 -0700113 << "Application has too many descriptor sets in the pipeline layout to continue with debug printf. "
Tony-LunarG04717522019-10-17 10:41:17 -0600114 << "Not modifying the pipeline layout. "
115 << "Instrumented shaders are replaced with non-instrumented shaders.";
Tony-LunarG1dce2392019-10-23 16:49:29 -0600116 ReportSetupProblem(device, strm.str().c_str());
Tony-LunarG04717522019-10-17 10:41:17 -0600117 } else {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700118 UtilPreCallRecordCreatePipelineLayout(cpl_state, this, pCreateInfo);
Tony-LunarG04717522019-10-17 10:41:17 -0600119 }
120}
121
Tony-LunarGb5fae462020-03-05 12:43:25 -0700122void DebugPrintf::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
123 const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout,
124 VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -0600125 ValidationStateTracker::PostCallRecordCreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout, result);
126 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600127 ReportSetupProblem(device, "Unable to create pipeline layout. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600128 aborted = true;
129 }
130}
131
132// Free the device memory and descriptor set associated with a command buffer.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700133void DebugPrintf::ResetCommandBuffer(VkCommandBuffer commandBuffer) {
Tony-LunarG04717522019-10-17 10:41:17 -0600134 if (aborted) {
135 return;
136 }
Tony-LunarGb5fae462020-03-05 12:43:25 -0700137 auto debug_printf_buffer_list = GetBufferInfo(commandBuffer);
138 for (auto buffer_info : debug_printf_buffer_list) {
Tony-LunarG04717522019-10-17 10:41:17 -0600139 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
140 if (buffer_info.desc_set != VK_NULL_HANDLE) {
141 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
142 }
143 }
144 command_buffer_map.erase(commandBuffer);
145}
146
147// Just gives a warning about a possible deadlock.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700148bool DebugPrintf::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
149 VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
150 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
151 uint32_t bufferMemoryBarrierCount,
152 const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
153 const VkImageMemoryBarrier *pImageMemoryBarriers) const {
Tony-LunarG04717522019-10-17 10:41:17 -0600154 if (srcStageMask & VK_PIPELINE_STAGE_HOST_BIT) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600155 ReportSetupProblem(commandBuffer,
156 "CmdWaitEvents recorded with VK_PIPELINE_STAGE_HOST_BIT set. "
Tony-LunarGbbbed672020-03-04 10:51:11 -0700157 "Debug Printf waits on queue completion. "
Tony-LunarG1dce2392019-10-23 16:49:29 -0600158 "This wait could block the host's signaling of this event, resulting in deadlock.");
Tony-LunarG04717522019-10-17 10:41:17 -0600159 }
160 return false;
161}
162
Tony-LunarGb5fae462020-03-05 12:43:25 -0700163void DebugPrintf::PreCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
164 const VkGraphicsPipelineCreateInfo *pCreateInfos,
165 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
166 void *cgpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600167 std::vector<safe_VkGraphicsPipelineCreateInfo> new_pipeline_create_infos;
168 create_graphics_pipeline_api_state *cgpl_state = reinterpret_cast<create_graphics_pipeline_api_state *>(cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700169 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, cgpl_state->pipe_state,
170 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600171 cgpl_state->printf_create_infos = new_pipeline_create_infos;
172 cgpl_state->pCreateInfos = reinterpret_cast<VkGraphicsPipelineCreateInfo *>(cgpl_state->printf_create_infos.data());
173}
174
Tony-LunarGb5fae462020-03-05 12:43:25 -0700175void DebugPrintf::PreCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
176 const VkComputePipelineCreateInfo *pCreateInfos,
177 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
178 void *ccpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600179 std::vector<safe_VkComputePipelineCreateInfo> new_pipeline_create_infos;
180 auto *ccpl_state = reinterpret_cast<create_compute_pipeline_api_state *>(ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700181 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, ccpl_state->pipe_state,
182 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600183 ccpl_state->printf_create_infos = new_pipeline_create_infos;
184 ccpl_state->pCreateInfos = reinterpret_cast<VkComputePipelineCreateInfo *>(ccpl_state->gpu_create_infos.data());
185}
186
Tony-LunarGb5fae462020-03-05 12:43:25 -0700187void DebugPrintf::PreCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
188 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
189 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
190 void *crtpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600191 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
192 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700193 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
194 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600195 crtpl_state->printf_create_infos = new_pipeline_create_infos;
196 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoNV *>(crtpl_state->gpu_create_infos.data());
197}
198
Tony-LunarGb5fae462020-03-05 12:43:25 -0700199void DebugPrintf::PreCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
200 const VkRayTracingPipelineCreateInfoKHR *pCreateInfos,
201 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
202 void *crtpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600203 std::vector<safe_VkRayTracingPipelineCreateInfoCommon> new_pipeline_create_infos;
204 auto *crtpl_state = reinterpret_cast<create_ray_tracing_pipeline_khr_api_state *>(crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700205 UtilPreCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, crtpl_state->pipe_state,
206 &new_pipeline_create_infos, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600207 crtpl_state->gpu_create_infos = new_pipeline_create_infos;
208 crtpl_state->pCreateInfos = reinterpret_cast<VkRayTracingPipelineCreateInfoKHR *>(crtpl_state->gpu_create_infos.data());
209}
Tony-LunarG04717522019-10-17 10:41:17 -0600210
Tony-LunarGb5fae462020-03-05 12:43:25 -0700211void DebugPrintf::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
212 const VkGraphicsPipelineCreateInfo *pCreateInfos,
213 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
214 VkResult result, void *cgpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600215 ValidationStateTracker::PostCallRecordCreateGraphicsPipelines(device, pipelineCache, count, pCreateInfos, pAllocator,
216 pPipelines, result, cgpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700217 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_GRAPHICS, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600218}
219
Tony-LunarGb5fae462020-03-05 12:43:25 -0700220void DebugPrintf::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
221 const VkComputePipelineCreateInfo *pCreateInfos,
222 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
223 VkResult result, void *ccpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600224 ValidationStateTracker::PostCallRecordCreateComputePipelines(device, pipelineCache, count, pCreateInfos, pAllocator, pPipelines,
225 result, ccpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700226 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_COMPUTE, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600227}
228
Tony-LunarGb5fae462020-03-05 12:43:25 -0700229void DebugPrintf::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
230 const VkRayTracingPipelineCreateInfoNV *pCreateInfos,
231 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
232 VkResult result, void *crtpl_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600233 ValidationStateTracker::PostCallRecordCreateRayTracingPipelinesNV(device, pipelineCache, count, pCreateInfos, pAllocator,
234 pPipelines, result, crtpl_state_data);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700235 UtilPostCallRecordPipelineCreations(count, pCreateInfos, pAllocator, pPipelines, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600236}
237
238// Remove all the shader trackers associated with this destroyed pipeline.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700239void DebugPrintf::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
Tony-LunarG04717522019-10-17 10:41:17 -0600240 for (auto it = shader_map.begin(); it != shader_map.end();) {
241 if (it->second.pipeline == pipeline) {
242 it = shader_map.erase(it);
243 } else {
244 ++it;
245 }
246 }
247 ValidationStateTracker::PreCallRecordDestroyPipeline(device, pipeline, pAllocator);
248}
249// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700250bool DebugPrintf::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<unsigned int> &new_pgm,
251 uint32_t *unique_shader_id) {
Tony-LunarG04717522019-10-17 10:41:17 -0600252 if (aborted) return false;
253 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
254
255 // Load original shader SPIR-V
256 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
257 new_pgm.clear();
258 new_pgm.reserve(num_words);
259 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
260
261 // Call the optimizer to instrument the shader.
262 // Use the unique_shader_module_id as a shader ID so we can look up its handle later in the shader_map.
263 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
264 using namespace spvtools;
265 spv_target_env target_env = SPV_ENV_VULKAN_1_1;
266 Optimizer optimizer(target_env);
267 optimizer.RegisterPass(CreateInstDebugPrintfPass(desc_set_bind_index, unique_shader_module_id));
268 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm);
269 if (!pass) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600270 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Tony-LunarG04717522019-10-17 10:41:17 -0600271 }
272 *unique_shader_id = unique_shader_module_id++;
273 return pass;
274}
275// Create the instrumented shader data to provide to the driver.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700276void DebugPrintf::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
277 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
278 void *csm_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600279 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
280 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
281 if (pass) {
282 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
283 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(unsigned int);
284 }
285}
Tony-LunarG04717522019-10-17 10:41:17 -0600286
287vartype vartype_lookup(char intype) {
288 switch (intype) {
289 case 'd':
290 case 'i':
291 return varsigned;
292 break;
293
294 case 'f':
295 case 'F':
296 case 'a':
297 case 'A':
298 case 'e':
299 case 'E':
300 case 'g':
301 case 'G':
302 return varfloat;
303 break;
304
305 case 'u':
306 case 'x':
307 case 'o':
308 default:
309 return varunsigned;
310 break;
311 }
312}
313
Tony-LunarGa19e31e2020-03-30 13:30:29 -0600314std::vector<DPFSubstring> DebugPrintf::ParseFormatString(const std::string format_string) {
315 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 -0700316 std::vector<DPFSubstring> parsed_strings;
Tony-LunarG04717522019-10-17 10:41:17 -0600317 size_t pos = 0;
318 size_t begin = 0;
319 size_t percent = 0;
320
321 while (begin < format_string.length()) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700322 DPFSubstring substring;
Tony-LunarG04717522019-10-17 10:41:17 -0600323
324 // Find a percent sign
325 pos = percent = format_string.find_first_of('%', pos);
326 if (pos == std::string::npos) {
327 // End of the format string Push the rest of the characters
328 substring.string = format_string.substr(begin, format_string.length());
329 substring.needs_value = false;
330 parsed_strings.push_back(substring);
331 break;
332 }
333 pos++;
334 if (format_string[pos] == '%') {
335 pos++;
336 continue; // %% - skip it
337 }
338 // Find the type of the value
339 pos = format_string.find_first_of(types, pos);
340 if (pos == format_string.npos)
341 // This really shouldn't happen with a legal value string
342 pos = format_string.length();
343 else {
344 char tempstring[32];
345 int count = 0;
346 std::string specifier = {};
347
348 if (format_string[pos] == 'v') {
349 // Vector must be of size 2, 3, or 4
350 // and format %v<size><type>
351 specifier = format_string.substr(percent, pos - percent);
352 count = atoi(&format_string[pos + 1]);
353 pos += 2;
354
355 // skip v<count>, handle long
356 specifier.push_back(format_string[pos]);
357 if (format_string[pos + 1] == 'l') {
358 specifier.push_back('l');
359 pos++;
360 }
361
362 // Take the preceding characters, and the percent through the type
363 substring.string = format_string.substr(begin, percent - begin);
364 substring.string += specifier;
365 substring.needs_value = true;
366 substring.type = vartype_lookup(specifier.back());
367 parsed_strings.push_back(substring);
368
369 // Continue with a comma separated list
370 sprintf(tempstring, ", %s", specifier.c_str());
371 substring.string = tempstring;
372 for (int i = 0; i < (count - 1); i++) {
373 parsed_strings.push_back(substring);
374 }
375 } else {
376 // Single non-vector value
377 if (format_string[pos + 1] == 'l') pos++; // Save long size
378 substring.string = format_string.substr(begin, pos - begin + 1);
379 substring.needs_value = true;
380 substring.type = vartype_lookup(format_string[pos]);
381 parsed_strings.push_back(substring);
382 }
383 begin = pos + 1;
384 }
385 }
386 return parsed_strings;
387}
388
Tony-LunarGb5fae462020-03-05 12:43:25 -0700389std::string DebugPrintf::FindFormatString(std::vector<unsigned int> pgm, uint32_t string_id) {
Tony-LunarG04717522019-10-17 10:41:17 -0600390 std::string format_string;
391 SHADER_MODULE_STATE shader;
392 shader.words = pgm;
393 if (shader.words.size() > 0) {
394 for (auto insn : shader) {
395 if (insn.opcode() == spv::OpString) {
396 uint32_t offset = insn.offset();
397 if (pgm[offset + 1] == string_id) {
398 format_string = reinterpret_cast<char *>(&pgm[offset + 2]);
399 break;
400 }
401 }
402 }
403 }
404
405 return format_string;
406}
407
Corentin Wallez171ac5e2020-03-31 16:09:05 +0200408// GCC and clang don't like using variables as format strings in sprintf.
409// #pragma GCC is recognized by both compilers
410#if defined(__GNUC__) || defined(__clang__)
Tony-LunarG04717522019-10-17 10:41:17 -0600411#pragma GCC diagnostic push
412#pragma GCC diagnostic ignored "-Wformat-security"
413#endif
414
Tony-LunarGb5fae462020-03-05 12:43:25 -0700415void snprintf_with_malloc(std::stringstream &shader_message, DPFSubstring substring, size_t needed, void *values) {
Tony-LunarG04717522019-10-17 10:41:17 -0600416 char *buffer = static_cast<char *>(malloc((needed + 1) * sizeof(char))); // Add 1 for terminator
417 if (substring.longval) {
418 snprintf(buffer, needed, substring.string.c_str(), substring.longval);
419 } else if (!substring.needs_value) {
420 snprintf(buffer, needed, substring.string.c_str());
421 } else {
422 switch (substring.type) {
423 case varunsigned:
424 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<uint32_t *>(values) - 1);
425 break;
426
427 case varsigned:
428 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<int32_t *>(values) - 1);
429 break;
430
431 case varfloat:
432 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<float *>(values) - 1);
433 break;
434 }
435 }
436 shader_message << buffer;
437 free(buffer);
438}
439
Tony-LunarGb5fae462020-03-05 12:43:25 -0700440void DebugPrintf::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, VkPipelineBindPoint pipeline_bind_point,
441 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Tony-LunarG04717522019-10-17 10:41:17 -0600442 // Word Content
443 // 0 Size of output record, including this word
444 // 1 Shader ID
445 // 2 Instruction Position
446 // 3 Stage Ordinal
447 // 4 Stage - specific Info Word 0
448 // 5 Stage - specific Info Word 1
449 // 6 Stage - specific Info Word 2
450 // 7 Printf Format String Id
451 // 8 Printf Values Word 0 (optional)
452 // 9 Printf Values Word 1 (optional)
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600453 uint32_t expect = debug_output_buffer[0];
454 if (!expect) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600455
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600456 uint32_t index = 1;
Tony-LunarG04717522019-10-17 10:41:17 -0600457 while (debug_output_buffer[index]) {
Tony-LunarG04717522019-10-17 10:41:17 -0600458 std::stringstream shader_message;
Tony-LunarG04717522019-10-17 10:41:17 -0600459 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
460 VkPipeline pipeline_handle = VK_NULL_HANDLE;
461 std::vector<unsigned int> pgm;
462
Tony-LunarGb5fae462020-03-05 12:43:25 -0700463 DPFOutputRecord *debug_record = reinterpret_cast<DPFOutputRecord *>(&debug_output_buffer[index]);
Tony-LunarG04717522019-10-17 10:41:17 -0600464 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
465 // by the instrumented shader.
466 auto it = shader_map.find(debug_record->shader_id);
467 if (it != shader_map.end()) {
468 shader_module_handle = it->second.shader_module;
469 pipeline_handle = it->second.pipeline;
470 pgm = it->second.pgm;
471 }
472 // Search through the shader source for the printf format string for this invocation
473 auto format_string = FindFormatString(pgm, debug_record->format_string_id);
474 // Break the format string into strings with 1 or 0 value
475 auto format_substrings = ParseFormatString(format_string);
476 void *values = static_cast<void *>(&debug_record->values);
477 const uint32_t static_size = 1024;
478 // Sprintf each format substring into a temporary string then add that to the message
479 for (auto &substring : format_substrings) {
480 char temp_string[static_size];
481 size_t needed = 0;
482 const size_t ul_pos = substring.string.find("%ul");
483 if (ul_pos != std::string::npos) {
484 // Unsigned 64 bit value
485 substring.longval = *static_cast<uint64_t *>(values);
486 values = static_cast<uint64_t *>(values) + 1;
487 substring.string.replace(ul_pos + 1, 2, PRIx64);
488 needed = snprintf(temp_string, static_size, substring.string.c_str(), substring.longval);
489 } else {
490 if (substring.needs_value) {
491 switch (substring.type) {
492 case varunsigned:
493 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<uint32_t *>(values));
494 break;
495
496 case varsigned:
497 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<int32_t *>(values));
498 break;
499
500 case varfloat:
501 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<float *>(values));
502 break;
503 }
504 values = static_cast<uint32_t *>(values) + 1;
505 } else
506 needed = snprintf(temp_string, static_size, substring.string.c_str());
507 }
508
509 if (needed < static_size)
510 shader_message << temp_string;
511 else {
512 // Static buffer not big enough for message, use malloc to get enough
513 snprintf_with_malloc(shader_message, substring, needed, values);
514 }
515 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600516
517 if (verbose) {
518 std::string stage_message;
519 std::string common_message;
520 std::string filename_message;
521 std::string source_message;
Tony-LunarGb5fae462020-03-05 12:43:25 -0700522 UtilGenerateStageMessage(&debug_output_buffer[index], stage_message);
523 UtilGenerateCommonMessage(report_data, command_buffer, &debug_output_buffer[index], shader_module_handle,
524 pipeline_handle, pipeline_bind_point, operation_index, common_message);
525 UtilGenerateSourceMessages(pgm, &debug_output_buffer[index], true, filename_message, source_message);
Tony-LunarG43416b42019-10-31 16:47:24 -0600526 if (use_stdout) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600527 std::cout << "UNASSIGNED-DEBUG-PRINTF " << common_message.c_str() << " " << stage_message.c_str() << " "
Tony-LunarGb5fae462020-03-05 12:43:25 -0700528 << shader_message.str().c_str() << " " << filename_message.c_str() << " " << source_message.c_str();
Tony-LunarG43416b42019-10-31 16:47:24 -0600529 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600530 LogInfo(queue, "UNASSIGNED-DEBUG-PRINTF", "%s %s %s %s%s", common_message.c_str(), stage_message.c_str(),
531 shader_message.str().c_str(), filename_message.c_str(), source_message.c_str());
Tony-LunarG43416b42019-10-31 16:47:24 -0600532 }
533 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600534 if (use_stdout) {
Tony-LunarG43416b42019-10-31 16:47:24 -0600535 std::cout << shader_message.str();
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600536 } else {
537 // Don't let LogInfo process any '%'s in the string
538 LogInfo(device, "UNASSIGNED-DEBUG-PRINTF", "%s", shader_message.str().c_str());
539 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600540 }
Tony-LunarG04717522019-10-17 10:41:17 -0600541 index += debug_record->size;
542 }
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600543 if ((index - 1) != expect) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600544 LogWarning(device, "UNASSIGNED-DEBUG-PRINTF",
545 "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 -0600546 }
Tony-LunarG04717522019-10-17 10:41:17 -0600547 memset(debug_output_buffer, 0, 4 * (debug_output_buffer[0] + 1));
548}
Tony-LunarG43416b42019-10-31 16:47:24 -0600549
Tony-LunarG04717522019-10-17 10:41:17 -0600550#if defined(__GNUC__)
551#pragma GCC diagnostic pop
552#endif
553
Tony-LunarG04717522019-10-17 10:41:17 -0600554// Issue a memory barrier to make GPU-written data available to host.
555// Wait for the queue to complete execution.
556// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700557void DebugPrintf::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
558 VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -0600559 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
560
Mark Lobodzinski09379db2020-05-07 08:22:01 -0600561 if (aborted || (result != VK_SUCCESS)) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600562 bool buffers_present = false;
563 // Don't QueueWaitIdle if there's nothing to process
564 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
565 const VkSubmitInfo *submit = &pSubmits[submit_idx];
566 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
567 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600568 if (GetBufferInfo(cb_node->commandBuffer).size()) buffers_present = true;
Tony-LunarG04717522019-10-17 10:41:17 -0600569 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600570 if (GetBufferInfo(secondaryCmdBuffer->commandBuffer).size()) buffers_present = true;
Tony-LunarG04717522019-10-17 10:41:17 -0600571 }
572 }
573 }
574 if (!buffers_present) return;
575
Tony-LunarGb5fae462020-03-05 12:43:25 -0700576 UtilSubmitBarrier(queue, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600577
578 DispatchQueueWaitIdle(queue);
579
580 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
581 const VkSubmitInfo *submit = &pSubmits[submit_idx];
582 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
583 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700584 UtilProcessInstrumentationBuffer(queue, cb_node, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600585 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700586 UtilProcessInstrumentationBuffer(queue, secondaryCmdBuffer, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600587 }
588 }
589 }
590}
591
Tony-LunarGb5fae462020-03-05 12:43:25 -0700592void DebugPrintf::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
593 uint32_t firstVertex, uint32_t firstInstance) {
594 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600595}
596
Tony-LunarGb5fae462020-03-05 12:43:25 -0700597void DebugPrintf::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
598 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
599 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600600}
601
Tony-LunarGb5fae462020-03-05 12:43:25 -0700602void DebugPrintf::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
603 uint32_t stride) {
604 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600605}
606
Tony-LunarGb5fae462020-03-05 12:43:25 -0700607void DebugPrintf::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
608 uint32_t count, uint32_t stride) {
609 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600610}
611
Tony-LunarGb5fae462020-03-05 12:43:25 -0700612void DebugPrintf::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
613 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600614}
615
Tony-LunarGb5fae462020-03-05 12:43:25 -0700616void DebugPrintf::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
617 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600618}
619
Tony-LunarGb5fae462020-03-05 12:43:25 -0700620void DebugPrintf::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
621 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
622 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
623 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
624 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
625 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
626 uint32_t width, uint32_t height, uint32_t depth) {
627 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
628}
629
630void DebugPrintf::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
Tony-LunarG04717522019-10-17 10:41:17 -0600631 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
632 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
633 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
634 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
635 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
636 uint32_t width, uint32_t height, uint32_t depth) {
Tony-LunarG04717522019-10-17 10:41:17 -0600637 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
638 cb_state->hasTraceRaysCmd = true;
639}
640
Tony-LunarGb5fae462020-03-05 12:43:25 -0700641void DebugPrintf::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
642 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
643 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
644 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
645 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, uint32_t width,
646 uint32_t height, uint32_t depth) {
647 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600648}
649
Tony-LunarGb5fae462020-03-05 12:43:25 -0700650void DebugPrintf::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
651 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
652 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
653 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
654 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, uint32_t width,
655 uint32_t height, uint32_t depth) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600656 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
657 cb_state->hasTraceRaysCmd = true;
658}
659
Tony-LunarGb5fae462020-03-05 12:43:25 -0700660void DebugPrintf::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
661 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
662 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
663 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
664 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, VkBuffer buffer,
665 VkDeviceSize offset) {
666 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600667}
668
Tony-LunarGb5fae462020-03-05 12:43:25 -0700669void DebugPrintf::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
670 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
671 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
672 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
673 const VkStridedBufferRegionKHR *pCallableShaderBindingTable,
674 VkBuffer buffer, VkDeviceSize offset) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600675 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
676 cb_state->hasTraceRaysCmd = true;
677}
678
Tony-LunarGb5fae462020-03-05 12:43:25 -0700679void DebugPrintf::AllocateDebugPrintfResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Tony-LunarG04717522019-10-17 10:41:17 -0600680 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
681 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
682 return;
683 }
684 VkResult result;
685
686 if (aborted) return;
687
688 std::vector<VkDescriptorSet> desc_sets;
689 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600690 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarG04717522019-10-17 10:41:17 -0600691 assert(result == VK_SUCCESS);
692 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600693 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600694 aborted = true;
695 return;
696 }
697
698 VkDescriptorBufferInfo output_desc_buffer_info = {};
699 output_desc_buffer_info.range = output_buffer_size;
700
701 auto cb_node = GetCBState(cmd_buffer);
702 if (!cb_node) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600703 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG04717522019-10-17 10:41:17 -0600704 aborted = true;
705 return;
706 }
707
708 // Allocate memory for the output block that the gpu will use to return values for printf
Tony-LunarGb5fae462020-03-05 12:43:25 -0700709 DPFDeviceMemoryBlock output_block = {};
Tony-LunarG04717522019-10-17 10:41:17 -0600710 VkBufferCreateInfo bufferInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
711 bufferInfo.size = output_buffer_size;
712 bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
713 VmaAllocationCreateInfo allocInfo = {};
714 allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
715 result = vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &output_block.buffer, &output_block.allocation, nullptr);
716 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600717 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600718 aborted = true;
719 return;
720 }
721
722 // Clear the output block to zeros so that only printf values from the gpu will be present
723 uint32_t *pData;
724 result = vmaMapMemory(vmaAllocator, output_block.allocation, (void **)&pData);
725 if (result == VK_SUCCESS) {
726 memset(pData, 0, output_buffer_size);
727 vmaUnmapMemory(vmaAllocator, output_block.allocation);
728 }
729
730 VkWriteDescriptorSet desc_writes[1] = {};
731 const uint32_t desc_count = 1;
732
733 // Write the descriptor
734 output_desc_buffer_info.buffer = output_block.buffer;
735 output_desc_buffer_info.offset = 0;
736
737 desc_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
738 desc_writes[0].descriptorCount = 1;
739 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
740 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
741 desc_writes[0].dstSet = desc_sets[0];
742 desc_writes[0].dstBinding = 3;
743 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
744
745 auto iter = cb_node->lastBound.find(bind_point); // find() allows read-only access to cb_state
746 if (iter != cb_node->lastBound.end()) {
747 auto pipeline_state = iter->second.pipeline_state;
748 if (pipeline_state && (pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index)) {
749 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout, desc_set_bind_index, 1,
750 desc_sets.data(), 0, nullptr);
751 }
752 // Record buffer and memory info in CB state tracking
Tony-LunarG1dce2392019-10-23 16:49:29 -0600753 GetBufferInfo(cmd_buffer).emplace_back(output_block, desc_sets[0], desc_pool, bind_point);
Tony-LunarG04717522019-10-17 10:41:17 -0600754 } else {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600755 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG04717522019-10-17 10:41:17 -0600756 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
757 aborted = true;
758 return;
759 }
760}