blob: 8d6ce8e5c64dfecc613eef42fc8930efdafc7331 [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 Gebben159b3cc2021-06-03 09:09:03 -060025#include "cmd_buffer_state.h"
Tony-LunarG04717522019-10-17 10:41:17 -060026
Tony-LunarG04717522019-10-17 10:41:17 -060027// Perform initializations that can be done at Create Device time.
Jeremy Gebben36a3b832022-03-23 10:54:18 -060028void DebugPrintf::CreateDevice(const VkDeviceCreateInfo *pCreateInfo) {
Jeremy Gebben33717862022-03-28 15:53:56 -060029 if (enabled[gpu_validation]) {
30 ReportSetupProblem(device,
31 "Debug Printf cannot be enabled when gpu assisted validation is enabled. "
32 "Debug Printf disabled.");
33 aborted = true;
34 return;
35 }
Tony-LunarG43416b42019-10-31 16:47:24 -060036 const char *size_string = getLayerOption("khronos_validation.printf_buffer_size");
Jeremy Gebben36a3b832022-03-23 10:54:18 -060037 output_buffer_size = *size_string ? atoi(size_string) : 1024;
Tony-LunarGc99dbef2021-06-14 15:11:50 -060038
39 std::string verbose_string = getLayerOption("khronos_validation.printf_verbose");
40 transform(verbose_string.begin(), verbose_string.end(), verbose_string.begin(), ::tolower);
Jeremy Gebben36a3b832022-03-23 10:54:18 -060041 verbose = verbose_string.length() ? !verbose_string.compare("true") : false;
Tony-LunarGc99dbef2021-06-14 15:11:50 -060042
43 std::string stdout_string = getLayerOption("khronos_validation.printf_to_stdout");
44 transform(stdout_string.begin(), stdout_string.end(), stdout_string.begin(), ::tolower);
Jeremy Gebben36a3b832022-03-23 10:54:18 -060045 use_stdout = stdout_string.length() ? !stdout_string.compare("true") : false;
46 if (getenv("DEBUG_PRINTF_TO_STDOUT")) use_stdout = true;
Tony-LunarG04717522019-10-17 10:41:17 -060047
Jeremy Gebben33717862022-03-28 15:53:56 -060048 // GpuAssistedBase::CreateDevice will set up bindings
49 VkDescriptorSetLayoutBinding binding = {3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
50 VK_SHADER_STAGE_ALL_GRAPHICS | VK_SHADER_STAGE_MESH_BIT_NV |
51 VK_SHADER_STAGE_TASK_BIT_NV | VK_SHADER_STAGE_COMPUTE_BIT |
52 kShaderStageAllRayTracing,
53 NULL};
54 bindings_.push_back(binding);
55
56 GpuAssistedBase::CreateDevice(pCreateInfo);
57
Jeremy Gebben36a3b832022-03-23 10:54:18 -060058 if (phys_dev_props.apiVersion < VK_API_VERSION_1_1) {
Tony-LunarGbbbed672020-03-04 10:51:11 -070059 ReportSetupProblem(device, "Debug Printf requires Vulkan 1.1 or later. Debug Printf disabled.");
Jeremy Gebben36a3b832022-03-23 10:54:18 -060060 aborted = true;
Tony-LunarG04717522019-10-17 10:41:17 -060061 return;
62 }
63
Jeremy Gebben36a3b832022-03-23 10:54:18 -060064 DispatchGetPhysicalDeviceFeatures(physical_device, &supported_features);
Tony-LunarG04717522019-10-17 10:41:17 -060065 if (!supported_features.fragmentStoresAndAtomics || !supported_features.vertexPipelineStoresAndAtomics) {
Tony-LunarG1dce2392019-10-23 16:49:29 -060066 ReportSetupProblem(device,
Tony-LunarGbbbed672020-03-04 10:51:11 -070067 "Debug Printf requires fragmentStoresAndAtomics and vertexPipelineStoresAndAtomics. "
68 "Debug Printf disabled.");
Jeremy Gebben36a3b832022-03-23 10:54:18 -060069 aborted = true;
Tony-LunarG04717522019-10-17 10:41:17 -060070 return;
71 }
Tony-LunarG04717522019-10-17 10:41:17 -060072}
73
74// Free the device memory and descriptor set associated with a command buffer.
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -060075void DebugPrintf::DestroyBuffer(DPFBufferInfo &buffer_info) {
76 vmaDestroyBuffer(vmaAllocator, buffer_info.output_mem_block.buffer, buffer_info.output_mem_block.allocation);
77 if (buffer_info.desc_set != VK_NULL_HANDLE) {
78 desc_set_manager->PutBackDescriptorSet(buffer_info.desc_pool, buffer_info.desc_set);
Tony-LunarG04717522019-10-17 10:41:17 -060079 }
Tony-LunarG04717522019-10-17 10:41:17 -060080}
81
Tony-LunarG04717522019-10-17 10:41:17 -060082// Call the SPIR-V Optimizer to run the instrumentation pass on the shader.
sfricke-samsung7fac88a2022-01-26 11:44:22 -080083bool DebugPrintf::InstrumentShader(const VkShaderModuleCreateInfo *pCreateInfo, std::vector<uint32_t> &new_pgm,
Tony-LunarGb5fae462020-03-05 12:43:25 -070084 uint32_t *unique_shader_id) {
Tony-LunarG04717522019-10-17 10:41:17 -060085 if (aborted) return false;
86 if (pCreateInfo->pCode[0] != spv::MagicNumber) return false;
87
88 // Load original shader SPIR-V
89 uint32_t num_words = static_cast<uint32_t>(pCreateInfo->codeSize / 4);
90 new_pgm.clear();
91 new_pgm.reserve(num_words);
92 new_pgm.insert(new_pgm.end(), &pCreateInfo->pCode[0], &pCreateInfo->pCode[num_words]);
93
94 // Call the optimizer to instrument the shader.
95 // Use the unique_shader_module_id as a shader ID so we can look up its handle later in the shader_map.
96 // If descriptor indexing is enabled, enable length checks and updated descriptor checks
97 using namespace spvtools;
sfricke-samsung45996a42021-09-16 13:45:27 -070098 spv_target_env target_env = PickSpirvEnv(api_version, IsExtEnabled(device_extensions.vk_khr_spirv_1_4));
Tony-LunarGf29f77f2020-08-26 15:48:00 -060099 spvtools::ValidatorOptions val_options;
100 AdjustValidatorOptions(device_extensions, enabled_features, val_options);
101 spvtools::OptimizerOptions opt_options;
102 opt_options.set_run_validator(true);
103 opt_options.set_validator_options(val_options);
Tony-LunarG04717522019-10-17 10:41:17 -0600104 Optimizer optimizer(target_env);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700105 const spvtools::MessageConsumer debug_printf_console_message_consumer =
Tony-LunarG79641702020-07-13 15:43:05 -0600106 [this](spv_message_level_t level, const char *, const spv_position_t &position, const char *message) -> void {
107 switch (level) {
108 case SPV_MSG_FATAL:
109 case SPV_MSG_INTERNAL_ERROR:
110 case SPV_MSG_ERROR:
111 this->LogError(this->device, "UNASSIGNED-Debug-Printf", "Error during shader instrumentation: line %zu: %s",
112 position.index, message);
113 break;
114 default:
115 break;
116 }
117 };
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700118 optimizer.SetMessageConsumer(debug_printf_console_message_consumer);
Tony-LunarG04717522019-10-17 10:41:17 -0600119 optimizer.RegisterPass(CreateInstDebugPrintfPass(desc_set_bind_index, unique_shader_module_id));
Tony-LunarGf29f77f2020-08-26 15:48:00 -0600120 bool pass = optimizer.Run(new_pgm.data(), new_pgm.size(), &new_pgm, opt_options);
Tony-LunarG04717522019-10-17 10:41:17 -0600121 if (!pass) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600122 ReportSetupProblem(device, "Failure to instrument shader. Proceeding with non-instrumented shader.");
Tony-LunarG04717522019-10-17 10:41:17 -0600123 }
124 *unique_shader_id = unique_shader_module_id++;
125 return pass;
126}
127// Create the instrumented shader data to provide to the driver.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700128void DebugPrintf::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
129 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
130 void *csm_state_data) {
Tony-LunarG04717522019-10-17 10:41:17 -0600131 create_shader_module_api_state *csm_state = reinterpret_cast<create_shader_module_api_state *>(csm_state_data);
132 bool pass = InstrumentShader(pCreateInfo, csm_state->instrumented_pgm, &csm_state->unique_shader_id);
133 if (pass) {
134 csm_state->instrumented_create_info.pCode = csm_state->instrumented_pgm.data();
sfricke-samsung7fac88a2022-01-26 11:44:22 -0800135 csm_state->instrumented_create_info.codeSize = csm_state->instrumented_pgm.size() * sizeof(uint32_t);
Tony-LunarG04717522019-10-17 10:41:17 -0600136 }
137}
Tony-LunarG04717522019-10-17 10:41:17 -0600138
139vartype vartype_lookup(char intype) {
140 switch (intype) {
141 case 'd':
142 case 'i':
143 return varsigned;
144 break;
145
146 case 'f':
147 case 'F':
148 case 'a':
149 case 'A':
150 case 'e':
151 case 'E':
152 case 'g':
153 case 'G':
154 return varfloat;
155 break;
156
157 case 'u':
158 case 'x':
159 case 'o':
160 default:
161 return varunsigned;
162 break;
163 }
164}
165
Tony-LunarGa19e31e2020-03-30 13:30:29 -0600166std::vector<DPFSubstring> DebugPrintf::ParseFormatString(const std::string format_string) {
167 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 -0700168 std::vector<DPFSubstring> parsed_strings;
Tony-LunarG04717522019-10-17 10:41:17 -0600169 size_t pos = 0;
170 size_t begin = 0;
171 size_t percent = 0;
172
173 while (begin < format_string.length()) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700174 DPFSubstring substring;
Tony-LunarG04717522019-10-17 10:41:17 -0600175
176 // Find a percent sign
177 pos = percent = format_string.find_first_of('%', pos);
178 if (pos == std::string::npos) {
179 // End of the format string Push the rest of the characters
180 substring.string = format_string.substr(begin, format_string.length());
181 substring.needs_value = false;
182 parsed_strings.push_back(substring);
183 break;
184 }
185 pos++;
186 if (format_string[pos] == '%') {
187 pos++;
188 continue; // %% - skip it
189 }
190 // Find the type of the value
191 pos = format_string.find_first_of(types, pos);
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700192 if (pos == format_string.npos) {
Tony-LunarG04717522019-10-17 10:41:17 -0600193 // This really shouldn't happen with a legal value string
194 pos = format_string.length();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700195 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600196 char tempstring[32];
197 int count = 0;
198 std::string specifier = {};
199
200 if (format_string[pos] == 'v') {
201 // Vector must be of size 2, 3, or 4
202 // and format %v<size><type>
203 specifier = format_string.substr(percent, pos - percent);
204 count = atoi(&format_string[pos + 1]);
205 pos += 2;
206
207 // skip v<count>, handle long
208 specifier.push_back(format_string[pos]);
209 if (format_string[pos + 1] == 'l') {
210 specifier.push_back('l');
211 pos++;
212 }
213
214 // Take the preceding characters, and the percent through the type
215 substring.string = format_string.substr(begin, percent - begin);
216 substring.string += specifier;
217 substring.needs_value = true;
218 substring.type = vartype_lookup(specifier.back());
219 parsed_strings.push_back(substring);
220
221 // Continue with a comma separated list
Frédéric Wangafb89862022-06-21 16:15:29 +0200222 snprintf(tempstring, sizeof(tempstring), ", %s", specifier.c_str());
Tony-LunarG04717522019-10-17 10:41:17 -0600223 substring.string = tempstring;
224 for (int i = 0; i < (count - 1); i++) {
225 parsed_strings.push_back(substring);
226 }
227 } else {
228 // Single non-vector value
229 if (format_string[pos + 1] == 'l') pos++; // Save long size
230 substring.string = format_string.substr(begin, pos - begin + 1);
231 substring.needs_value = true;
232 substring.type = vartype_lookup(format_string[pos]);
233 parsed_strings.push_back(substring);
234 }
235 begin = pos + 1;
236 }
237 }
238 return parsed_strings;
239}
240
sfricke-samsung7fac88a2022-01-26 11:44:22 -0800241std::string DebugPrintf::FindFormatString(std::vector<uint32_t> pgm, uint32_t string_id) {
Tony-LunarG04717522019-10-17 10:41:17 -0600242 std::string format_string;
sfricke-samsungef15e482022-01-26 11:32:49 -0800243 SHADER_MODULE_STATE module_state(pgm);
244 if (module_state.words.size() > 0) {
245 for (const auto &insn : module_state) {
Tony-LunarG04717522019-10-17 10:41:17 -0600246 if (insn.opcode() == spv::OpString) {
247 uint32_t offset = insn.offset();
248 if (pgm[offset + 1] == string_id) {
249 format_string = reinterpret_cast<char *>(&pgm[offset + 2]);
250 break;
251 }
252 }
253 }
254 }
255
256 return format_string;
257}
258
Corentin Wallez171ac5e2020-03-31 16:09:05 +0200259// GCC and clang don't like using variables as format strings in sprintf.
260// #pragma GCC is recognized by both compilers
261#if defined(__GNUC__) || defined(__clang__)
Tony-LunarG04717522019-10-17 10:41:17 -0600262#pragma GCC diagnostic push
263#pragma GCC diagnostic ignored "-Wformat-security"
264#endif
265
Tony-LunarGb5fae462020-03-05 12:43:25 -0700266void snprintf_with_malloc(std::stringstream &shader_message, DPFSubstring substring, size_t needed, void *values) {
Tony-LunarG04717522019-10-17 10:41:17 -0600267 char *buffer = static_cast<char *>(malloc((needed + 1) * sizeof(char))); // Add 1 for terminator
268 if (substring.longval) {
269 snprintf(buffer, needed, substring.string.c_str(), substring.longval);
270 } else if (!substring.needs_value) {
271 snprintf(buffer, needed, substring.string.c_str());
272 } else {
273 switch (substring.type) {
274 case varunsigned:
275 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<uint32_t *>(values) - 1);
276 break;
277
278 case varsigned:
279 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<int32_t *>(values) - 1);
280 break;
281
282 case varfloat:
283 needed = snprintf(buffer, needed, substring.string.c_str(), *static_cast<float *>(values) - 1);
284 break;
285 }
286 }
287 shader_message << buffer;
288 free(buffer);
289}
290
Tony-LunarG7de10e82020-11-24 11:31:55 -0700291void DebugPrintf::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQueue queue, DPFBufferInfo &buffer_info,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700292 uint32_t operation_index, uint32_t *const debug_output_buffer) {
Tony-LunarG04717522019-10-17 10:41:17 -0600293 // Word Content
294 // 0 Size of output record, including this word
295 // 1 Shader ID
296 // 2 Instruction Position
297 // 3 Stage Ordinal
298 // 4 Stage - specific Info Word 0
299 // 5 Stage - specific Info Word 1
300 // 6 Stage - specific Info Word 2
301 // 7 Printf Format String Id
302 // 8 Printf Values Word 0 (optional)
303 // 9 Printf Values Word 1 (optional)
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600304 uint32_t expect = debug_output_buffer[0];
305 if (!expect) return;
Tony-LunarG04717522019-10-17 10:41:17 -0600306
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600307 uint32_t index = 1;
Tony-LunarG04717522019-10-17 10:41:17 -0600308 while (debug_output_buffer[index]) {
Tony-LunarG04717522019-10-17 10:41:17 -0600309 std::stringstream shader_message;
Tony-LunarG04717522019-10-17 10:41:17 -0600310 VkShaderModule shader_module_handle = VK_NULL_HANDLE;
311 VkPipeline pipeline_handle = VK_NULL_HANDLE;
sfricke-samsung7fac88a2022-01-26 11:44:22 -0800312 std::vector<uint32_t> pgm;
Tony-LunarG04717522019-10-17 10:41:17 -0600313
Tony-LunarGb5fae462020-03-05 12:43:25 -0700314 DPFOutputRecord *debug_record = reinterpret_cast<DPFOutputRecord *>(&debug_output_buffer[index]);
Tony-LunarG04717522019-10-17 10:41:17 -0600315 // Lookup the VkShaderModule handle and SPIR-V code used to create the shader, using the unique shader ID value returned
316 // by the instrumented shader.
317 auto it = shader_map.find(debug_record->shader_id);
318 if (it != shader_map.end()) {
319 shader_module_handle = it->second.shader_module;
320 pipeline_handle = it->second.pipeline;
321 pgm = it->second.pgm;
322 }
323 // Search through the shader source for the printf format string for this invocation
324 auto format_string = FindFormatString(pgm, debug_record->format_string_id);
325 // Break the format string into strings with 1 or 0 value
326 auto format_substrings = ParseFormatString(format_string);
327 void *values = static_cast<void *>(&debug_record->values);
328 const uint32_t static_size = 1024;
329 // Sprintf each format substring into a temporary string then add that to the message
330 for (auto &substring : format_substrings) {
331 char temp_string[static_size];
332 size_t needed = 0;
Tony-LunarGef469c92021-05-14 06:33:22 -0600333 std::vector<std::string> format_strings = { "%ul", "%lu", "%lx" };
334 size_t ul_pos = 0;
335 bool print_hex = true;
336 for (auto ul_string : format_strings) {
337 ul_pos = substring.string.find(ul_string);
338 if (ul_pos != std::string::npos) {
339 if (ul_string == "%lu") print_hex = false;
340 break;
341 }
342 }
Tony-LunarG04717522019-10-17 10:41:17 -0600343 if (ul_pos != std::string::npos) {
344 // Unsigned 64 bit value
345 substring.longval = *static_cast<uint64_t *>(values);
346 values = static_cast<uint64_t *>(values) + 1;
Tony-LunarGef469c92021-05-14 06:33:22 -0600347 if (print_hex) {
348 substring.string.replace(ul_pos + 1, 2, PRIx64);
349 } else {
350 substring.string.replace(ul_pos + 1, 2, PRIu64);
351 }
Tony-LunarG04717522019-10-17 10:41:17 -0600352 needed = snprintf(temp_string, static_size, substring.string.c_str(), substring.longval);
353 } else {
354 if (substring.needs_value) {
355 switch (substring.type) {
356 case varunsigned:
357 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<uint32_t *>(values));
358 break;
359
360 case varsigned:
361 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<int32_t *>(values));
362 break;
363
364 case varfloat:
365 needed = snprintf(temp_string, static_size, substring.string.c_str(), *static_cast<float *>(values));
366 break;
367 }
368 values = static_cast<uint32_t *>(values) + 1;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700369 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600370 needed = snprintf(temp_string, static_size, substring.string.c_str());
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700371 }
Tony-LunarG04717522019-10-17 10:41:17 -0600372 }
373
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700374 if (needed < static_size) {
Tony-LunarG04717522019-10-17 10:41:17 -0600375 shader_message << temp_string;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700376 } else {
Tony-LunarG04717522019-10-17 10:41:17 -0600377 // Static buffer not big enough for message, use malloc to get enough
378 snprintf_with_malloc(shader_message, substring, needed, values);
379 }
380 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600381
382 if (verbose) {
383 std::string stage_message;
384 std::string common_message;
385 std::string filename_message;
386 std::string source_message;
Tony-LunarGb5fae462020-03-05 12:43:25 -0700387 UtilGenerateStageMessage(&debug_output_buffer[index], stage_message);
388 UtilGenerateCommonMessage(report_data, command_buffer, &debug_output_buffer[index], shader_module_handle,
Tony-LunarG7de10e82020-11-24 11:31:55 -0700389 pipeline_handle, buffer_info.pipeline_bind_point, operation_index, common_message);
Tony-LunarGb5fae462020-03-05 12:43:25 -0700390 UtilGenerateSourceMessages(pgm, &debug_output_buffer[index], true, filename_message, source_message);
Tony-LunarG43416b42019-10-31 16:47:24 -0600391 if (use_stdout) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600392 std::cout << "UNASSIGNED-DEBUG-PRINTF " << common_message.c_str() << " " << stage_message.c_str() << " "
Tony-LunarGb5fae462020-03-05 12:43:25 -0700393 << shader_message.str().c_str() << " " << filename_message.c_str() << " " << source_message.c_str();
Tony-LunarG43416b42019-10-31 16:47:24 -0600394 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600395 LogInfo(queue, "UNASSIGNED-DEBUG-PRINTF", "%s %s %s %s%s", common_message.c_str(), stage_message.c_str(),
396 shader_message.str().c_str(), filename_message.c_str(), source_message.c_str());
Tony-LunarG43416b42019-10-31 16:47:24 -0600397 }
398 } else {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600399 if (use_stdout) {
Tony-LunarG43416b42019-10-31 16:47:24 -0600400 std::cout << shader_message.str();
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600401 } else {
402 // Don't let LogInfo process any '%'s in the string
403 LogInfo(device, "UNASSIGNED-DEBUG-PRINTF", "%s", shader_message.str().c_str());
404 }
Tony-LunarG43416b42019-10-31 16:47:24 -0600405 }
Tony-LunarG04717522019-10-17 10:41:17 -0600406 index += debug_record->size;
407 }
Tony-LunarG12a7ec32019-11-01 13:00:05 -0600408 if ((index - 1) != expect) {
Tony-LunarG5af54eb2020-03-27 15:32:51 -0600409 LogWarning(device, "UNASSIGNED-DEBUG-PRINTF",
410 "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 -0600411 }
Tony-LunarG04717522019-10-17 10:41:17 -0600412 memset(debug_output_buffer, 0, 4 * (debug_output_buffer[0] + 1));
413}
Tony-LunarG43416b42019-10-31 16:47:24 -0600414
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -0600415// For the given command buffer, map its debug data buffers and read their contents for analysis.
Jeremy Gebben5ca80b32022-04-11 10:58:39 -0600416void debug_printf_state::CommandBuffer::Process(VkQueue queue) {
417 auto *device_state = static_cast<DebugPrintf *>(dev_data);
sjfricke52defd42022-08-08 16:37:46 +0900418 if (has_draw_cmd || has_trace_rays_cmd || has_dispatch_cmd) {
Jeremy Gebben5ca80b32022-04-11 10:58:39 -0600419 auto &gpu_buffer_list = buffer_infos;
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -0600420 uint32_t draw_index = 0;
421 uint32_t compute_index = 0;
422 uint32_t ray_trace_index = 0;
423
424 for (auto &buffer_info : gpu_buffer_list) {
Jeremy Gebben5ca80b32022-04-11 10:58:39 -0600425 char *data;
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -0600426
427 uint32_t operation_index = 0;
428 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
429 operation_index = draw_index;
sjfricke9a209802022-08-03 17:57:40 +0900430 draw_index++;
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -0600431 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
432 operation_index = compute_index;
sjfricke9a209802022-08-03 17:57:40 +0900433 compute_index++;
sjfricke62366d32022-08-01 21:04:10 +0900434 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) {
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -0600435 operation_index = ray_trace_index;
sjfricke9a209802022-08-03 17:57:40 +0900436 ray_trace_index++;
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -0600437 } else {
438 assert(false);
439 }
440
Jeremy Gebben5ca80b32022-04-11 10:58:39 -0600441 VkResult result = vmaMapMemory(device_state->vmaAllocator, buffer_info.output_mem_block.allocation, (void **)&data);
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -0600442 if (result == VK_SUCCESS) {
Jeremy Gebben5ca80b32022-04-11 10:58:39 -0600443 device_state->AnalyzeAndGenerateMessages(commandBuffer(), queue, buffer_info, operation_index, (uint32_t *)data);
444 vmaUnmapMemory(device_state->vmaAllocator, buffer_info.output_mem_block.allocation);
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -0600445 }
Jeremy Gebbenfcfc33c2022-03-28 15:31:29 -0600446 }
447 }
448}
449
Tony-LunarG04717522019-10-17 10:41:17 -0600450#if defined(__GNUC__)
451#pragma GCC diagnostic pop
452#endif
453
Tony-LunarGb5fae462020-03-05 12:43:25 -0700454void DebugPrintf::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
455 uint32_t firstVertex, uint32_t firstInstance) {
456 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600457}
458
Tony-LunarG745150c2021-07-02 15:07:31 -0600459void DebugPrintf::PreCallRecordCmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint32_t drawCount,
460 const VkMultiDrawInfoEXT *pVertexInfo, uint32_t instanceCount,
461 uint32_t firstInstance, uint32_t stride) {
462 for(uint32_t i = 0; i < drawCount; i++) {
463 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
464 }
465}
466
Tony-LunarGb5fae462020-03-05 12:43:25 -0700467void DebugPrintf::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
468 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
469 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600470}
471
Tony-LunarG745150c2021-07-02 15:07:31 -0600472void DebugPrintf::PreCallRecordCmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer, uint32_t drawCount,
473 const VkMultiDrawIndexedInfoEXT *pIndexInfo, uint32_t instanceCount,
474 uint32_t firstInstance, uint32_t stride, const int32_t *pVertexOffset) {
475 for (uint32_t i = 0; i < drawCount; i++) {
476 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
477 }
478}
479
Tony-LunarGb5fae462020-03-05 12:43:25 -0700480void DebugPrintf::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
481 uint32_t stride) {
482 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600483}
484
Tony-LunarGb5fae462020-03-05 12:43:25 -0700485void DebugPrintf::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
486 uint32_t count, uint32_t stride) {
487 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
Tony-LunarG04717522019-10-17 10:41:17 -0600488}
489
Tony-LunarGb5fae462020-03-05 12:43:25 -0700490void DebugPrintf::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
491 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600492}
493
Tony-LunarGb5fae462020-03-05 12:43:25 -0700494void DebugPrintf::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
495 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
Tony-LunarG04717522019-10-17 10:41:17 -0600496}
497
Tony-LunarGd13f9b52020-09-08 15:45:45 -0600498void DebugPrintf::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
499 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
500 uint32_t groupCountZ) {
501 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
502}
503
Tony-LunarG52c8c602020-09-10 16:29:56 -0600504void DebugPrintf::PreCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
505 uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
506 uint32_t groupCountZ) {
507 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
508}
509
Tony-LunarG2fb8ff02020-06-11 12:45:07 -0600510void DebugPrintf::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
511 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
512 uint32_t stride) {
513 ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
514 maxDrawCount, stride);
515 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
516}
517
518void DebugPrintf::PreCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
519 VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
520 uint32_t stride) {
521 ValidationStateTracker::PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
522 maxDrawCount, stride);
523 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
524}
525
526void DebugPrintf::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
527 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
528 uint32_t maxDrawCount, uint32_t stride) {
529 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(commandBuffer, buffer, offset, countBuffer,
530 countBufferOffset, maxDrawCount, stride);
531 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
532}
533
534void DebugPrintf::PreCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
535 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
536 uint32_t maxDrawCount, uint32_t stride) {
537 ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset,
538 maxDrawCount, stride);
539 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
540}
541
Tony-LunarG54176fb2020-12-02 10:47:22 -0700542void DebugPrintf::PreCallRecordCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
543 uint32_t firstInstance, VkBuffer counterBuffer,
544 VkDeviceSize counterBufferOffset, uint32_t counterOffset,
545 uint32_t vertexStride) {
546 ValidationStateTracker::PreCallRecordCmdDrawIndirectByteCountEXT(commandBuffer, instanceCount, firstInstance, counterBuffer,
547 counterBufferOffset, counterOffset, vertexStride);
548 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
549}
550
Tony-LunarG2fb8ff02020-06-11 12:45:07 -0600551void DebugPrintf::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
552 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(commandBuffer, taskCount, firstTask);
553 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
554}
555
556void DebugPrintf::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
557 uint32_t drawCount, uint32_t stride) {
558 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(commandBuffer, buffer, offset, drawCount, stride);
559 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
560}
561
562void DebugPrintf::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
563 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
564 uint32_t maxDrawCount, uint32_t stride) {
565 ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(commandBuffer, buffer, offset, countBuffer,
566 countBufferOffset, maxDrawCount, stride);
567 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
568}
569
Tony-LunarGb5fae462020-03-05 12:43:25 -0700570void DebugPrintf::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
571 VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
572 VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
573 VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
574 VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
575 VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
576 uint32_t width, uint32_t height, uint32_t depth) {
577 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
578}
579
Tony-LunarGb5fae462020-03-05 12:43:25 -0700580void DebugPrintf::PreCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700581 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
582 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
583 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
584 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable, uint32_t width,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700585 uint32_t height, uint32_t depth) {
586 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600587}
588
Tony-LunarGb5fae462020-03-05 12:43:25 -0700589void DebugPrintf::PreCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
sourav parmarcd5fb182020-07-17 12:58:44 -0700590 const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
591 const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
592 const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
593 const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
Shannon McPherson54e1f892020-11-27 11:04:19 -0700594 VkDeviceAddress indirectDeviceAddress) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700595 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600596}
597
sfricke-samsungf91881c2022-03-31 01:12:00 -0500598void DebugPrintf::PreCallRecordCmdTraceRaysIndirect2KHR(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress) {
599 AllocateDebugPrintfResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR);
600}
601
Tony-LunarGb5fae462020-03-05 12:43:25 -0700602void DebugPrintf::AllocateDebugPrintfResources(const VkCommandBuffer cmd_buffer, const VkPipelineBindPoint bind_point) {
Tony-LunarG04717522019-10-17 10:41:17 -0600603 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
sjfricke62366d32022-08-01 21:04:10 +0900604 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR) {
Tony-LunarG04717522019-10-17 10:41:17 -0600605 return;
606 }
607 VkResult result;
608
609 if (aborted) return;
610
611 std::vector<VkDescriptorSet> desc_sets;
612 VkDescriptorPool desc_pool = VK_NULL_HANDLE;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600613 result = desc_set_manager->GetDescriptorSets(1, &desc_pool, debug_desc_layout, &desc_sets);
Tony-LunarG04717522019-10-17 10:41:17 -0600614 assert(result == VK_SUCCESS);
615 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600616 ReportSetupProblem(device, "Unable to allocate descriptor sets. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600617 aborted = true;
618 return;
619 }
620
621 VkDescriptorBufferInfo output_desc_buffer_info = {};
622 output_desc_buffer_info.range = output_buffer_size;
623
Jeremy Gebben04697b02022-03-23 16:18:12 -0600624 auto cb_node = GetWrite<debug_printf_state::CommandBuffer>(cmd_buffer);
Tony-LunarG04717522019-10-17 10:41:17 -0600625 if (!cb_node) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600626 ReportSetupProblem(device, "Unrecognized command buffer");
Tony-LunarG04717522019-10-17 10:41:17 -0600627 aborted = true;
628 return;
629 }
630
Nathaniel Cesariobcb79682022-03-31 21:13:52 -0600631 const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
632 const auto *pipeline_state = cb_node->lastBound[lv_bind_point].pipeline_state;
633
634 // TODO (ncesario) remove once VK_EXT_graphics_pipeline_library support is added for debug printf
635 if (pipeline_state && pipeline_state->IsGraphicsLibrary()) {
636 ReportSetupProblem(device, "Debug printf does not currently support VK_EXT_graphics_pipeline_library");
637 aborted = true;
638 return;
639 }
640
Tony-LunarG04717522019-10-17 10:41:17 -0600641 // Allocate memory for the output block that the gpu will use to return values for printf
Tony-LunarGb5fae462020-03-05 12:43:25 -0700642 DPFDeviceMemoryBlock output_block = {};
sjfrickee9b39372022-05-22 13:02:17 +0900643 VkBufferCreateInfo buffer_info = LvlInitStruct<VkBufferCreateInfo>();
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700644 buffer_info.size = output_buffer_size;
645 buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
646 VmaAllocationCreateInfo alloc_info = {};
Tony-LunarGef497962022-04-19 08:48:52 -0600647 alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700648 result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &output_block.buffer, &output_block.allocation, nullptr);
Tony-LunarG04717522019-10-17 10:41:17 -0600649 if (result != VK_SUCCESS) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600650 ReportSetupProblem(device, "Unable to allocate device memory. Device could become unstable.");
Tony-LunarG04717522019-10-17 10:41:17 -0600651 aborted = true;
652 return;
653 }
654
655 // Clear the output block to zeros so that only printf values from the gpu will be present
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700656 uint32_t *data;
657 result = vmaMapMemory(vmaAllocator, output_block.allocation, reinterpret_cast<void **>(&data));
Tony-LunarG04717522019-10-17 10:41:17 -0600658 if (result == VK_SUCCESS) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700659 memset(data, 0, output_buffer_size);
Tony-LunarG04717522019-10-17 10:41:17 -0600660 vmaUnmapMemory(vmaAllocator, output_block.allocation);
661 }
662
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600663 auto desc_writes = LvlInitStruct<VkWriteDescriptorSet>();
Tony-LunarG04717522019-10-17 10:41:17 -0600664 const uint32_t desc_count = 1;
665
666 // Write the descriptor
667 output_desc_buffer_info.buffer = output_block.buffer;
668 output_desc_buffer_info.offset = 0;
669
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600670 desc_writes.descriptorCount = 1;
671 desc_writes.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
672 desc_writes.pBufferInfo = &output_desc_buffer_info;
673 desc_writes.dstSet = desc_sets[0];
674 desc_writes.dstBinding = 3;
675 DispatchUpdateDescriptorSets(device, desc_count, &desc_writes, 0, NULL);
Tony-LunarG04717522019-10-17 10:41:17 -0600676
locke-lunargb8d7a7a2020-10-25 16:01:52 -0600677 if (pipeline_state) {
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700678 const auto &pipeline_layout = pipeline_state->PipelineLayoutState();
679 if (pipeline_layout->set_layouts.size() <= desc_set_bind_index) {
680 DispatchCmdBindDescriptorSets(cmd_buffer, bind_point, pipeline_layout->layout(), desc_set_bind_index, 1,
Tony-LunarG04717522019-10-17 10:41:17 -0600681 desc_sets.data(), 0, nullptr);
682 }
683 // Record buffer and memory info in CB state tracking
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600684 cb_node->buffer_infos.emplace_back(output_block, desc_sets[0], desc_pool, bind_point);
Tony-LunarG04717522019-10-17 10:41:17 -0600685 } else {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600686 ReportSetupProblem(device, "Unable to find pipeline state");
Tony-LunarG04717522019-10-17 10:41:17 -0600687 vmaDestroyBuffer(vmaAllocator, output_block.buffer, output_block.allocation);
688 aborted = true;
689 return;
690 }
691}
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600692
693std::shared_ptr<CMD_BUFFER_STATE> DebugPrintf::CreateCmdBufferState(VkCommandBuffer cb,
694 const VkCommandBufferAllocateInfo *pCreateInfo,
Jeremy Gebbencd7fa282021-10-27 10:25:32 -0600695 const COMMAND_POOL_STATE *pool) {
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -0600696 return std::static_pointer_cast<CMD_BUFFER_STATE>(
697 std::make_shared<debug_printf_state::CommandBuffer>(this, cb, pCreateInfo, pool));
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600698}
699
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -0600700debug_printf_state::CommandBuffer::CommandBuffer(DebugPrintf *dp, VkCommandBuffer cb,
Jeremy Gebbencd7fa282021-10-27 10:25:32 -0600701 const VkCommandBufferAllocateInfo *pCreateInfo, const COMMAND_POOL_STATE *pool)
Jeremy Gebben5ca80b32022-04-11 10:58:39 -0600702 : gpu_utils_state::CommandBuffer(dp, cb, pCreateInfo, pool) {}
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600703
Jeremy Gebben37c5c5d2022-03-21 07:16:03 -0600704void debug_printf_state::CommandBuffer::Reset() {
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600705 CMD_BUFFER_STATE::Reset();
706 auto debug_printf = static_cast<DebugPrintf *>(dev_data);
707 // Free the device memory and descriptor set(s) associated with a command buffer.
708 if (debug_printf->aborted) {
709 return;
710 }
711 for (auto &buffer_info : buffer_infos) {
712 debug_printf->DestroyBuffer(buffer_info);
713 }
714 buffer_infos.clear();
715}