blob: e8bc5d29f3ee0b14bf1146deef939664f5fb9bf0 [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
408// GCC doesn't like using variables as format strings in sprintf
409#if defined(__GNUC__)
410#pragma GCC diagnostic push
411#pragma GCC diagnostic ignored "-Wformat-security"
412#endif
413
Tony-LunarGb5fae462020-03-05 12:43:25 -0700414void snprintf_with_malloc(std::stringstream &shader_message, DPFSubstring substring, size_t needed, void *values) {
Tony-LunarG04717522019-10-17 10:41:17 -0600415 char *buffer = static_cast<char *>(malloc((needed + 1) * sizeof(char))); // Add 1 for terminator
416 if (substring.longval) {
417 snprintf(buffer, needed, substring.string.c_str(), substring.longval);
418 } else if (!substring.needs_value) {
419 snprintf(buffer, needed, substring.string.c_str());
420 } else {
421 switch (substring.type) {
422 case varunsigned:
423 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<uint32_t *>(values) - 1);
424 break;
425
426 case varsigned:
427 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<int32_t *>(values) - 1);
428 break;
429
430 case varfloat:
431 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<float *>(values) - 1);
432 break;
433 }
434 }
435 shader_message << buffer;
436 free(buffer);
437}
438
Tony-LunarGb5fae462020-03-05 12:43:25 -0700439void DebugPrintf::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, VkPipelineBindPoint pipeline_bind_point,
440 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Tony-LunarG04717522019-10-17 10:41:17 -0600441 // Word Content
442 // 0 Size of output record, including this word
443 // 1 Shader ID
444 // 2 Instruction Position
445 // 3 Stage Ordinal
446 // 4 Stage - specific Info Word 0
447 // 5 Stage - specific Info Word 1
448 // 6 Stage - specific Info Word 2
449 // 7 Printf Format String Id
450 // 8 Printf Values Word 0 (optional)
451 // 9 Printf Values Word 1 (optional)
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600452 uint32_t expect = debug_output_buffer[0];
453 if (!expect) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600454
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600455 uint32_t index = 1;
Tony-LunarG04717522019-10-17 10:41:17 -0600456 while (debug_output_buffer[index]) {
Tony-LunarG04717522019-10-17 10:41:17 -0600457 std::stringstream shader_message;
Tony-LunarG04717522019-10-17 10:41:17 -0600458 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
459 VkPipeline pipeline_handle = VK_NULL_HANDLE;
460 std::vector<unsigned int> pgm;
461
Tony-LunarGb5fae462020-03-05 12:43:25 -0700462 DPFOutputRecord *debug_record = reinterpret_cast<DPFOutputRecord *>(&debug_output_buffer[index]);
Tony-LunarG04717522019-10-17 10:41:17 -0600463 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
464 // by the instrumented shader.
465 auto it = shader_map.find(debug_record->shader_id);
466 if (it != shader_map.end()) {
467 shader_module_handle = it->second.shader_module;
468 pipeline_handle = it->second.pipeline;
469 pgm = it->second.pgm;
470 }
471 // Search through the shader source for the printf format string for this invocation
472 auto format_string = FindFormatString(pgm, debug_record->format_string_id);
473 // Break the format string into strings with 1 or 0 value
474 auto format_substrings = ParseFormatString(format_string);
475 void *values = static_cast<void *>(&debug_record->values);
476 const uint32_t static_size = 1024;
477 // Sprintf each format substring into a temporary string then add that to the message
478 for (auto &substring : format_substrings) {
479 char temp_string[static_size];
480 size_t needed = 0;
481 const size_t ul_pos = substring.string.find("%ul");
482 if (ul_pos != std::string::npos) {
483 // Unsigned 64 bit value
484 substring.longval = *static_cast<uint64_t *>(values);
485 values = static_cast<uint64_t *>(values) + 1;
486 substring.string.replace(ul_pos + 1, 2, PRIx64);
487 needed = snprintf(temp_string, static_size, substring.string.c_str(), substring.longval);
488 } else {
489 if (substring.needs_value) {
490 switch (substring.type) {
491 case varunsigned:
492 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<uint32_t *>(values));
493 break;
494
495 case varsigned:
496 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<int32_t *>(values));
497 break;
498
499 case varfloat:
500 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<float *>(values));
501 break;
502 }
503 values = static_cast<uint32_t *>(values) + 1;
504 } else
505 needed = snprintf(temp_string, static_size, substring.string.c_str());
506 }
507
508 if (needed < static_size)
509 shader_message << temp_string;
510 else {
511 // Static buffer not big enough for message, use malloc to get enough
512 snprintf_with_malloc(shader_message, substring, needed, values);
513 }
514 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600515
516 if (verbose) {
517 std::string stage_message;
518 std::string common_message;
519 std::string filename_message;
520 std::string source_message;
Tony-LunarGb5fae462020-03-05 12:43:25 -0700521 UtilGenerateStageMessage(&debug_output_buffer[index], stage_message);
522 UtilGenerateCommonMessage(report_data, command_buffer, &debug_output_buffer[index], shader_module_handle,
523 pipeline_handle, pipeline_bind_point, operation_index, common_message);
524 UtilGenerateSourceMessages(pgm, &debug_output_buffer[index], true, filename_message, source_message);
Tony-LunarG43416b42019-10-31 16:47:24 -0600525 if (use_stdout) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600526 std::cout << "UNASSIGNED-DEBUG-PRINTF " << common_message.c_str() << " " << stage_message.c_str() << " "
Tony-LunarGb5fae462020-03-05 12:43:25 -0700527 << shader_message.str().c_str() << " " << filename_message.c_str() << " " << source_message.c_str();
Tony-LunarG43416b42019-10-31 16:47:24 -0600528 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600529 LogInfo(queue, "UNASSIGNED-DEBUG-PRINTF", "%s %s %s %s%s", common_message.c_str(), stage_message.c_str(),
530 shader_message.str().c_str(), filename_message.c_str(), source_message.c_str());
Tony-LunarG43416b42019-10-31 16:47:24 -0600531 }
532 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600533 if (use_stdout) {
Tony-LunarG43416b42019-10-31 16:47:24 -0600534 std::cout << shader_message.str();
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600535 } else {
536 // Don't let LogInfo process any '%'s in the string
537 LogInfo(device, "UNASSIGNED-DEBUG-PRINTF", "%s", shader_message.str().c_str());
538 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600539 }
Tony-LunarG04717522019-10-17 10:41:17 -0600540 index += debug_record->size;
541 }
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600542 if ((index - 1) != expect) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600543 LogWarning(device, "UNASSIGNED-DEBUG-PRINTF",
544 "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 -0600545 }
Tony-LunarG04717522019-10-17 10:41:17 -0600546 memset(debug_output_buffer, 0, 4 * (debug_output_buffer[0] + 1));
547}
Tony-LunarG43416b42019-10-31 16:47:24 -0600548
Tony-LunarG04717522019-10-17 10:41:17 -0600549#if defined(__GNUC__)
550#pragma GCC diagnostic pop
551#endif
552
Tony-LunarG04717522019-10-17 10:41:17 -0600553// Issue a memory barrier to make GPU-written data available to host.
554// Wait for the queue to complete execution.
555// Check the debug buffers for all the command buffers that were submitted.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700556void DebugPrintf::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
557 VkResult result) {
Tony-LunarG04717522019-10-17 10:41:17 -0600558 ValidationStateTracker::PostCallRecordQueueSubmit(queue, submitCount, pSubmits, fence, result);
559
560 if (aborted) return;
561 bool buffers_present = false;
562 // Don't QueueWaitIdle if there's nothing to process
563 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
564 const VkSubmitInfo *submit = &pSubmits[submit_idx];
565 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
566 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600567 if (GetBufferInfo(cb_node->commandBuffer).size()) buffers_present = true;
Tony-LunarG04717522019-10-17 10:41:17 -0600568 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600569 if (GetBufferInfo(secondaryCmdBuffer->commandBuffer).size()) buffers_present = true;
Tony-LunarG04717522019-10-17 10:41:17 -0600570 }
571 }
572 }
573 if (!buffers_present) return;
574
Tony-LunarGb5fae462020-03-05 12:43:25 -0700575 UtilSubmitBarrier(queue, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600576
577 DispatchQueueWaitIdle(queue);
578
579 for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
580 const VkSubmitInfo *submit = &pSubmits[submit_idx];
581 for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
582 auto cb_node = GetCBState(submit->pCommandBuffers[i]);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700583 UtilProcessInstrumentationBuffer(queue, cb_node, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600584 for (auto secondaryCmdBuffer : cb_node->linkedCommandBuffers) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700585 UtilProcessInstrumentationBuffer(queue, secondaryCmdBuffer, this);
Tony-LunarG04717522019-10-17 10:41:17 -0600586 }
587 }
588 }
589}
590
Tony-LunarGb5fae462020-03-05 12:43:25 -0700591void DebugPrintf::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
592 uint32_t firstVertex, uint32_t firstInstance) {
593 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600594}
595
Tony-LunarGb5fae462020-03-05 12:43:25 -0700596void DebugPrintf::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
597 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
598 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600599}
600
Tony-LunarGb5fae462020-03-05 12:43:25 -0700601void DebugPrintf::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
602 uint32_t stride) {
603 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600604}
605
Tony-LunarGb5fae462020-03-05 12:43:25 -0700606void DebugPrintf::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
607 uint32_t count, uint32_t stride) {
608 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600609}
610
Tony-LunarGb5fae462020-03-05 12:43:25 -0700611void DebugPrintf::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
612 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600613}
614
Tony-LunarGb5fae462020-03-05 12:43:25 -0700615void DebugPrintf::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
616 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600617}
618
Tony-LunarGb5fae462020-03-05 12:43:25 -0700619void DebugPrintf::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
620 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
621 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
622 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
623 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
624 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
625 uint32_t width, uint32_t height, uint32_t depth) {
626 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
627}
628
629void DebugPrintf::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
Tony-LunarG04717522019-10-17 10:41:17 -0600630 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
631 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
632 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
633 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
634 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
635 uint32_t width, uint32_t height, uint32_t depth) {
Tony-LunarG04717522019-10-17 10:41:17 -0600636 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
637 cb_state->hasTraceRaysCmd = true;
638}
639
Tony-LunarGb5fae462020-03-05 12:43:25 -0700640void DebugPrintf::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
641 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
642 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
643 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
644 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, uint32_t width,
645 uint32_t height, uint32_t depth) {
646 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600647}
648
Tony-LunarGb5fae462020-03-05 12:43:25 -0700649void DebugPrintf::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
650 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
651 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
652 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
653 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, uint32_t width,
654 uint32_t height, uint32_t depth) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600655 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
656 cb_state->hasTraceRaysCmd = true;
657}
658
Tony-LunarGb5fae462020-03-05 12:43:25 -0700659void DebugPrintf::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
660 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
661 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
662 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
663 const VkStridedBufferRegionKHR *pCallableShaderBindingTable, VkBuffer buffer,
664 VkDeviceSize offset) {
665 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600666}
667
Tony-LunarGb5fae462020-03-05 12:43:25 -0700668void DebugPrintf::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
669 const VkStridedBufferRegionKHR *pRaygenShaderBindingTable,
670 const VkStridedBufferRegionKHR *pMissShaderBindingTable,
671 const VkStridedBufferRegionKHR *pHitShaderBindingTable,
672 const VkStridedBufferRegionKHR *pCallableShaderBindingTable,
673 VkBuffer buffer, VkDeviceSize offset) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600674 CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
675 cb_state->hasTraceRaysCmd = true;
676}
677
Tony-LunarGb5fae462020-03-05 12:43:25 -0700678void DebugPrintf::AllocateDebugPrintfResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Tony-LunarG04717522019-10-17 10:41:17 -0600679 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
680 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
681 return;
682 }
683 VkResult result;
684
685 if (aborted) return;
686
687 std::vector<VkDescriptorSet> desc_sets;
688 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600689 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarG04717522019-10-17 10:41:17 -0600690 assert(result == VK_SUCCESS);
691 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600692 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600693 aborted = true;
694 return;
695 }
696
697 VkDescriptorBufferInfo output_desc_buffer_info = {};
698 output_desc_buffer_info.range = output_buffer_size;
699
700 auto cb_node = GetCBState(cmd_buffer);
701 if (!cb_node) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600702 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG04717522019-10-17 10:41:17 -0600703 aborted = true;
704 return;
705 }
706
707 // Allocate memory for the output block that the gpu will use to return values for printf
Tony-LunarGb5fae462020-03-05 12:43:25 -0700708 DPFDeviceMemoryBlock output_block = {};
Tony-LunarG04717522019-10-17 10:41:17 -0600709 VkBufferCreateInfo bufferInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
710 bufferInfo.size = output_buffer_size;
711 bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
712 VmaAllocationCreateInfo allocInfo = {};
713 allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU;
714 result = vmaCreateBuffer(vmaAllocator, &bufferInfo, &allocInfo, &output_block.buffer, &output_block.allocation, nullptr);
715 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600716 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600717 aborted = true;
718 return;
719 }
720
721 // Clear the output block to zeros so that only printf values from the gpu will be present
722 uint32_t *pData;
723 result = vmaMapMemory(vmaAllocator, output_block.allocation, (void **)&pData);
724 if (result == VK_SUCCESS) {
725 memset(pData, 0, output_buffer_size);
726 vmaUnmapMemory(vmaAllocator, output_block.allocation);
727 }
728
729 VkWriteDescriptorSet desc_writes[1] = {};
730 const uint32_t desc_count = 1;
731
732 // Write the descriptor
733 output_desc_buffer_info.buffer = output_block.buffer;
734 output_desc_buffer_info.offset = 0;
735
736 desc_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
737 desc_writes[0].descriptorCount = 1;
738 desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
739 desc_writes[0].pBufferInfo = &output_desc_buffer_info;
740 desc_writes[0].dstSet = desc_sets[0];
741 desc_writes[0].dstBinding = 3;
742 DispatchUpdateDescriptorSets(device, desc_count, desc_writes, 0, NULL);
743
744 auto iter = cb_node->lastBound.find(bind_point); // find() allows read-only access to cb_state
745 if (iter != cb_node->lastBound.end()) {
746 auto pipeline_state = iter->second.pipeline_state;
747 if (pipeline_state && (pipeline_state->pipeline_layout->set_layouts.size() <= desc_set_bind_index)) {
748 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_state->pipeline_layout->layout, desc_set_bind_index, 1,
749 desc_sets.data(), 0, nullptr);
750 }
751 // Record buffer and memory info in CB state tracking
Tony-LunarG1dce2392019-10-23 16:49:29 -0600752 GetBufferInfo(cmd_buffer).emplace_back(output_block, desc_sets[0], desc_pool, bind_point);
Tony-LunarG04717522019-10-17 10:41:17 -0600753 } else {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600754 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG04717522019-10-17 10:41:17 -0600755 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
756 aborted = true;
757 return;
758 }
759}