blob: 97f24085023410898d739fd66c37aa34d9b45f2b [file] [log] [blame]
Tony-LunarG7de10e82020-11-24 11:31:55 -07001/* Copyright (c) 2020-2021 The Khronos Group Inc.
2 * Copyright (c) 2020-2021 Valve Corporation
3 * Copyright (c) 2020-2021 LunarG, Inc.
Tony-LunarG1dce2392019-10-23 16:49:29 -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#pragma once
20#include "chassis.h"
21#include "shader_validation.h"
Jeremy Gebben159b3cc2021-06-03 09:09:03 -060022#include "cmd_buffer_state.h"
23
Tony-LunarGb5fae462020-03-05 12:43:25 -070024class UtilDescriptorSetManager {
Tony-LunarG1dce2392019-10-23 16:49:29 -060025 public:
Tony-LunarGb5fae462020-03-05 12:43:25 -070026 UtilDescriptorSetManager(VkDevice device, uint32_t numBindingsInSet);
27 ~UtilDescriptorSetManager();
Tony-LunarG1dce2392019-10-23 16:49:29 -060028
29 VkResult GetDescriptorSet(VkDescriptorPool *desc_pool, VkDescriptorSetLayout ds_layout, VkDescriptorSet *desc_sets);
30 VkResult GetDescriptorSets(uint32_t count, VkDescriptorPool *pool, VkDescriptorSetLayout ds_layout,
31 std::vector<VkDescriptorSet> *desc_sets);
32 void PutBackDescriptorSet(VkDescriptorPool desc_pool, VkDescriptorSet desc_set);
33
34 private:
35 static const uint32_t kItemsPerChunk = 512;
36 struct PoolTracker {
37 uint32_t size;
38 uint32_t used;
39 };
40 VkDevice device;
41 uint32_t numBindingsInSet;
Jeremy Gebbencbf22862021-03-03 12:01:22 -070042 layer_data::unordered_map<VkDescriptorPool, struct PoolTracker> desc_pool_map_;
Tony-LunarG1dce2392019-10-23 16:49:29 -060043};
Tony-LunarGb5fae462020-03-05 12:43:25 -070044struct UtilQueueBarrierCommandInfo {
Tony-LunarG1dce2392019-10-23 16:49:29 -060045 VkCommandPool barrier_command_pool = VK_NULL_HANDLE;
46 VkCommandBuffer barrier_command_buffer = VK_NULL_HANDLE;
47};
Tony-LunarGb5fae462020-03-05 12:43:25 -070048VkResult UtilInitializeVma(VkPhysicalDevice physical_device, VkDevice device, VmaAllocator *pAllocator);
49void UtilPreCallRecordCreateDevice(VkPhysicalDevice gpu, safe_VkDeviceCreateInfo *modified_create_info,
50 VkPhysicalDeviceFeatures supported_features, VkPhysicalDeviceFeatures desired_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -060051template <typename ObjectType>
Tony-LunarGb5fae462020-03-05 12:43:25 -070052void UtilPostCallRecordCreateDevice(const VkDeviceCreateInfo *pCreateInfo, std::vector<VkDescriptorSetLayoutBinding> bindings,
53 ObjectType *object_ptr, VkPhysicalDeviceProperties physical_device_properties) {
Tony-LunarG1dce2392019-10-23 16:49:29 -060054 // If api version 1.1 or later, SetDeviceLoaderData will be in the loader
55 auto chain_info = get_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK);
56 assert(chain_info->u.pfnSetDeviceLoaderData);
57 object_ptr->vkSetDeviceLoaderData = chain_info->u.pfnSetDeviceLoaderData;
58
59 // Some devices have extremely high limits here, so set a reasonable max because we have to pad
60 // the pipeline layout with dummy descriptor set layouts.
61 object_ptr->adjusted_max_desc_sets = physical_device_properties.limits.maxBoundDescriptorSets;
62 object_ptr->adjusted_max_desc_sets = std::min(33U, object_ptr->adjusted_max_desc_sets);
63
64 // We can't do anything if there is only one.
65 // Device probably not a legit Vulkan device, since there should be at least 4. Protect ourselves.
66 if (object_ptr->adjusted_max_desc_sets == 1) {
67 object_ptr->ReportSetupProblem(object_ptr->device, "Device can bind only a single descriptor set.");
68 object_ptr->aborted = true;
69 return;
70 }
71 object_ptr->desc_set_bind_index = object_ptr->adjusted_max_desc_sets - 1;
72
Tony-LunarGb5fae462020-03-05 12:43:25 -070073 VkResult result1 = UtilInitializeVma(object_ptr->physicalDevice, object_ptr->device, &object_ptr->vmaAllocator);
Tony-LunarG1dce2392019-10-23 16:49:29 -060074 assert(result1 == VK_SUCCESS);
Tony-LunarGb5fae462020-03-05 12:43:25 -070075 std::unique_ptr<UtilDescriptorSetManager> desc_set_manager(
76 new UtilDescriptorSetManager(object_ptr->device, static_cast<uint32_t>(bindings.size())));
Tony-LunarG1dce2392019-10-23 16:49:29 -060077
78 const VkDescriptorSetLayoutCreateInfo debug_desc_layout_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, 0,
79 static_cast<uint32_t>(bindings.size()), bindings.data()};
80
81 const VkDescriptorSetLayoutCreateInfo dummy_desc_layout_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, 0, 0,
82 NULL};
83
84 result1 = DispatchCreateDescriptorSetLayout(object_ptr->device, &debug_desc_layout_info, NULL, &object_ptr->debug_desc_layout);
85
86 // This is a layout used to "pad" a pipeline layout to fill in any gaps to the selected bind index.
87 VkResult result2 =
88 DispatchCreateDescriptorSetLayout(object_ptr->device, &dummy_desc_layout_info, NULL, &object_ptr->dummy_desc_layout);
89
90 assert((result1 == VK_SUCCESS) && (result2 == VK_SUCCESS));
91 if ((result1 != VK_SUCCESS) || (result2 != VK_SUCCESS)) {
92 object_ptr->ReportSetupProblem(object_ptr->device, "Unable to create descriptor set layout.");
93 if (result1 == VK_SUCCESS) {
94 DispatchDestroyDescriptorSetLayout(object_ptr->device, object_ptr->debug_desc_layout, NULL);
95 }
96 if (result2 == VK_SUCCESS) {
97 DispatchDestroyDescriptorSetLayout(object_ptr->device, object_ptr->dummy_desc_layout, NULL);
98 }
99 object_ptr->debug_desc_layout = VK_NULL_HANDLE;
100 object_ptr->dummy_desc_layout = VK_NULL_HANDLE;
101 object_ptr->aborted = true;
102 return;
103 }
104 object_ptr->desc_set_manager = std::move(desc_set_manager);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600105}
106template <typename ObjectType>
Tony-LunarGb5fae462020-03-05 12:43:25 -0700107void UtilPreCallRecordDestroyDevice(ObjectType *object_ptr) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600108 for (auto &queue_barrier_command_info_kv : object_ptr->queue_barrier_command_infos) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700109 UtilQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_kv.second;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600110
111 DispatchFreeCommandBuffers(object_ptr->device, queue_barrier_command_info.barrier_command_pool, 1,
112 &queue_barrier_command_info.barrier_command_buffer);
113 queue_barrier_command_info.barrier_command_buffer = VK_NULL_HANDLE;
114
115 DispatchDestroyCommandPool(object_ptr->device, queue_barrier_command_info.barrier_command_pool, NULL);
116 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
117 }
118 object_ptr->queue_barrier_command_infos.clear();
119 if (object_ptr->debug_desc_layout) {
120 DispatchDestroyDescriptorSetLayout(object_ptr->device, object_ptr->debug_desc_layout, NULL);
121 object_ptr->debug_desc_layout = VK_NULL_HANDLE;
122 }
123 if (object_ptr->dummy_desc_layout) {
124 DispatchDestroyDescriptorSetLayout(object_ptr->device, object_ptr->dummy_desc_layout, NULL);
125 object_ptr->dummy_desc_layout = VK_NULL_HANDLE;
126 }
Tony-LunarG1dce2392019-10-23 16:49:29 -0600127}
128
129template <typename ObjectType>
Tony-LunarGb5fae462020-03-05 12:43:25 -0700130void UtilPreCallRecordCreatePipelineLayout(create_pipeline_layout_api_state *cpl_state, ObjectType *object_ptr,
131 const VkPipelineLayoutCreateInfo *pCreateInfo) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600132 // Modify the pipeline layout by:
133 // 1. Copying the caller's descriptor set desc_layouts
134 // 2. Fill in dummy descriptor layouts up to the max binding
135 // 3. Fill in with the debug descriptor layout at the max binding slot
136 cpl_state->new_layouts.reserve(object_ptr->adjusted_max_desc_sets);
137 cpl_state->new_layouts.insert(cpl_state->new_layouts.end(), &pCreateInfo->pSetLayouts[0],
138 &pCreateInfo->pSetLayouts[pCreateInfo->setLayoutCount]);
139 for (uint32_t i = pCreateInfo->setLayoutCount; i < object_ptr->adjusted_max_desc_sets - 1; ++i) {
140 cpl_state->new_layouts.push_back(object_ptr->dummy_desc_layout);
141 }
142 cpl_state->new_layouts.push_back(object_ptr->debug_desc_layout);
143 cpl_state->modified_create_info.pSetLayouts = cpl_state->new_layouts.data();
144 cpl_state->modified_create_info.setLayoutCount = object_ptr->adjusted_max_desc_sets;
145}
146
147template <typename CreateInfo>
148struct CreatePipelineTraits {};
149template <>
150struct CreatePipelineTraits<VkGraphicsPipelineCreateInfo> {
151 using SafeType = safe_VkGraphicsPipelineCreateInfo;
152 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->graphicsPipelineCI; }
153 static uint32_t GetStageCount(const VkGraphicsPipelineCreateInfo &createInfo) { return createInfo.stageCount; }
154 static VkShaderModule GetShaderModule(const VkGraphicsPipelineCreateInfo &createInfo, uint32_t stage) {
155 return createInfo.pStages[stage].module;
156 }
157 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
158 createInfo->pStages[stage].module = shader_module;
159 }
160};
161
162template <>
163struct CreatePipelineTraits<VkComputePipelineCreateInfo> {
164 using SafeType = safe_VkComputePipelineCreateInfo;
165 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->computePipelineCI; }
166 static uint32_t GetStageCount(const VkComputePipelineCreateInfo &createInfo) { return 1; }
167 static VkShaderModule GetShaderModule(const VkComputePipelineCreateInfo &createInfo, uint32_t stage) {
168 return createInfo.stage.module;
169 }
170 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
171 assert(stage == 0);
172 createInfo->stage.module = shader_module;
173 }
174};
175
176template <>
177struct CreatePipelineTraits<VkRayTracingPipelineCreateInfoNV> {
178 using SafeType = safe_VkRayTracingPipelineCreateInfoCommon;
179 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->raytracingPipelineCI; }
180 static uint32_t GetStageCount(const VkRayTracingPipelineCreateInfoNV &createInfo) { return createInfo.stageCount; }
181 static VkShaderModule GetShaderModule(const VkRayTracingPipelineCreateInfoNV &createInfo, uint32_t stage) {
182 return createInfo.pStages[stage].module;
183 }
184 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
185 createInfo->pStages[stage].module = shader_module;
186 }
187};
188
189template <>
190struct CreatePipelineTraits<VkRayTracingPipelineCreateInfoKHR> {
191 using SafeType = safe_VkRayTracingPipelineCreateInfoCommon;
192 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) { return pipeline_state->raytracingPipelineCI; }
193 static uint32_t GetStageCount(const VkRayTracingPipelineCreateInfoKHR &createInfo) { return createInfo.stageCount; }
194 static VkShaderModule GetShaderModule(const VkRayTracingPipelineCreateInfoKHR &createInfo, uint32_t stage) {
195 return createInfo.pStages[stage].module;
196 }
197 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
198 createInfo->pStages[stage].module = shader_module;
199 }
200};
201
202// Examine the pipelines to see if they use the debug descriptor set binding index.
203// If any do, create new non-instrumented shader modules and use them to replace the instrumented
204// shaders in the pipeline. Return the (possibly) modified create infos to the caller.
205template <typename CreateInfo, typename SafeCreateInfo, typename ObjectType>
Tony-LunarGb5fae462020-03-05 12:43:25 -0700206void UtilPreCallRecordPipelineCreations(uint32_t count, const CreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
207 VkPipeline *pPipelines, std::vector<std::shared_ptr<PIPELINE_STATE>> &pipe_state,
208 std::vector<SafeCreateInfo> *new_pipeline_create_infos,
209 const VkPipelineBindPoint bind_point, ObjectType *object_ptr) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600210 using Accessor = CreatePipelineTraits<CreateInfo>;
211 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
212 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
213 return;
214 }
215
216 // Walk through all the pipelines, make a copy of each and flag each pipeline that contains a shader that uses the debug
217 // descriptor set index.
218 for (uint32_t pipeline = 0; pipeline < count; ++pipeline) {
219 uint32_t stageCount = Accessor::GetStageCount(pCreateInfos[pipeline]);
220 new_pipeline_create_infos->push_back(Accessor::GetPipelineCI(pipe_state[pipeline].get()));
221
222 bool replace_shaders = false;
223 if (pipe_state[pipeline]->active_slots.find(object_ptr->desc_set_bind_index) != pipe_state[pipeline]->active_slots.end()) {
224 replace_shaders = true;
225 }
226 // If the app requests all available sets, the pipeline layout was not modified at pipeline layout creation and the already
227 // instrumented shaders need to be replaced with uninstrumented shaders
228 if (pipe_state[pipeline]->pipeline_layout->set_layouts.size() >= object_ptr->adjusted_max_desc_sets) {
229 replace_shaders = true;
230 }
231
232 if (replace_shaders) {
233 for (uint32_t stage = 0; stage < stageCount; ++stage) {
234 const SHADER_MODULE_STATE *shader =
235 object_ptr->GetShaderModuleState(Accessor::GetShaderModule(pCreateInfos[pipeline], stage));
236
Tony-LunarG1dce2392019-10-23 16:49:29 -0600237 VkShaderModule shader_module;
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600238 auto create_info = LvlInitStruct<VkShaderModuleCreateInfo>();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600239 create_info.pCode = shader->words.data();
240 create_info.codeSize = shader->words.size() * sizeof(uint32_t);
241 VkResult result = DispatchCreateShaderModule(object_ptr->device, &create_info, pAllocator, &shader_module);
242 if (result == VK_SUCCESS) {
243 Accessor::SetShaderModule(&(*new_pipeline_create_infos)[pipeline], shader_module, stage);
244 } else {
245 object_ptr->ReportSetupProblem(object_ptr->device,
246 "Unable to replace instrumented shader with non-instrumented one. "
247 "Device could become unstable.");
248 }
249 }
250 }
251 }
252}
253// For every pipeline:
254// - For every shader in a pipeline:
255// - If the shader had to be replaced in PreCallRecord (because the pipeline is using the debug desc set index):
256// - Destroy it since it has been bound into the pipeline by now. This is our only chance to delete it.
257// - Track the shader in the shader_map
258// - Save the shader binary if it contains debug code
259template <typename CreateInfo, typename ObjectType>
Tony-LunarGb5fae462020-03-05 12:43:25 -0700260void UtilPostCallRecordPipelineCreations(const uint32_t count, const CreateInfo *pCreateInfos,
261 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
262 const VkPipelineBindPoint bind_point, ObjectType *object_ptr) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600263 using Accessor = CreatePipelineTraits<CreateInfo>;
264 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
265 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
266 return;
267 }
268 for (uint32_t pipeline = 0; pipeline < count; ++pipeline) {
269 auto pipeline_state = object_ptr->ValidationStateTracker::GetPipelineState(pPipelines[pipeline]);
270 if (nullptr == pipeline_state) continue;
271
272 uint32_t stageCount = 0;
273 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
274 stageCount = pipeline_state->graphicsPipelineCI.stageCount;
275 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
276 stageCount = 1;
277 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
278 stageCount = pipeline_state->raytracingPipelineCI.stageCount;
279 } else {
280 assert(false);
281 }
282
283 for (uint32_t stage = 0; stage < stageCount; ++stage) {
284 if (pipeline_state->active_slots.find(object_ptr->desc_set_bind_index) != pipeline_state->active_slots.end()) {
285 DispatchDestroyShaderModule(object_ptr->device, Accessor::GetShaderModule(pCreateInfos[pipeline], stage),
286 pAllocator);
287 }
288
289 const SHADER_MODULE_STATE *shader_state = nullptr;
290 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
291 shader_state = object_ptr->GetShaderModuleState(pipeline_state->graphicsPipelineCI.pStages[stage].module);
292 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
293 assert(stage == 0);
294 shader_state = object_ptr->GetShaderModuleState(pipeline_state->computePipelineCI.stage.module);
295 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
296 shader_state = object_ptr->GetShaderModuleState(pipeline_state->raytracingPipelineCI.pStages[stage].module);
297 } else {
298 assert(false);
299 }
300
301 std::vector<unsigned int> code;
302 // Save the shader binary
303 // The core_validation ShaderModule tracker saves the binary too, but discards it when the ShaderModule
304 // is destroyed. Applications may destroy ShaderModules after they are placed in a pipeline and before
305 // the pipeline is used, so we have to keep another copy.
306 if (shader_state && shader_state->has_valid_spirv) code = shader_state->words;
307
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600308 object_ptr->shader_map[shader_state->gpu_validation_shader_id].pipeline = pipeline_state->pipeline();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600309 // Be careful to use the originally bound (instrumented) shader here, even if PreCallRecord had to back it
310 // out with a non-instrumented shader. The non-instrumented shader (found in pCreateInfo) was destroyed above.
311 VkShaderModule shader_module = VK_NULL_HANDLE;
312 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
313 shader_module = pipeline_state->graphicsPipelineCI.pStages[stage].module;
314 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
315 assert(stage == 0);
316 shader_module = pipeline_state->computePipelineCI.stage.module;
317 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
318 shader_module = pipeline_state->raytracingPipelineCI.pStages[stage].module;
319 } else {
320 assert(false);
321 }
322 object_ptr->shader_map[shader_state->gpu_validation_shader_id].shader_module = shader_module;
323 object_ptr->shader_map[shader_state->gpu_validation_shader_id].pgm = std::move(code);
324 }
325 }
326}
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600327template <typename CreateInfos, typename SafeCreateInfos>
328void UtilCopyCreatePipelineFeedbackData(const uint32_t count, CreateInfos *pCreateInfos, SafeCreateInfos *pSafeCreateInfos) {
329 for (uint32_t i = 0; i < count; i++) {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -0700330 auto src_feedback_struct = LvlFindInChain<VkPipelineCreationFeedbackCreateInfoEXT>(pSafeCreateInfos[i].pNext);
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600331 if (!src_feedback_struct) return;
332 auto dst_feedback_struct = const_cast<VkPipelineCreationFeedbackCreateInfoEXT *>(
Mark Lobodzinski1f887d32020-12-30 15:31:33 -0700333 LvlFindInChain<VkPipelineCreationFeedbackCreateInfoEXT>(pCreateInfos[i].pNext));
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600334 *dst_feedback_struct->pPipelineCreationFeedback = *src_feedback_struct->pPipelineCreationFeedback;
335 for (uint32_t j = 0; j < src_feedback_struct->pipelineStageCreationFeedbackCount; j++) {
336 dst_feedback_struct->pPipelineStageCreationFeedbacks[j] = src_feedback_struct->pPipelineStageCreationFeedbacks[j];
337 }
338 }
339}
340
Tony-LunarG1dce2392019-10-23 16:49:29 -0600341template <typename ObjectType>
342// For the given command buffer, map its debug data buffers and read their contents for analysis.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700343void UtilProcessInstrumentationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node, ObjectType *object_ptr) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600344 if (cb_node && (cb_node->hasDrawCmd || cb_node->hasTraceRaysCmd || cb_node->hasDispatchCmd)) {
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600345 auto gpu_buffer_list = object_ptr->GetBufferInfo(cb_node);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600346 uint32_t draw_index = 0;
347 uint32_t compute_index = 0;
348 uint32_t ray_trace_index = 0;
349
350 for (auto &buffer_info : gpu_buffer_list) {
351 char *pData;
352
353 uint32_t operation_index = 0;
354 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
355 operation_index = draw_index;
356 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
357 operation_index = compute_index;
358 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
359 operation_index = ray_trace_index;
360 } else {
361 assert(false);
362 }
363
364 VkResult result = vmaMapMemory(object_ptr->vmaAllocator, buffer_info.output_mem_block.allocation, (void **)&pData);
365 if (result == VK_SUCCESS) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600366 object_ptr->AnalyzeAndGenerateMessages(cb_node->commandBuffer(), queue, buffer_info,
Tony-LunarG1dce2392019-10-23 16:49:29 -0600367 operation_index, (uint32_t *)pData);
368 vmaUnmapMemory(object_ptr->vmaAllocator, buffer_info.output_mem_block.allocation);
369 }
370
371 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
372 draw_index++;
373 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
374 compute_index++;
375 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
376 ray_trace_index++;
377 } else {
378 assert(false);
379 }
380 }
381 }
382}
383template <typename ObjectType>
384// Submit a memory barrier on graphics queues.
385// Lazy-create and record the needed command buffer.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700386void UtilSubmitBarrier(VkQueue queue, ObjectType *object_ptr) {
387 auto queue_barrier_command_info_it = object_ptr->queue_barrier_command_infos.emplace(queue, UtilQueueBarrierCommandInfo{});
Tony-LunarG1dce2392019-10-23 16:49:29 -0600388 if (queue_barrier_command_info_it.second) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700389 UtilQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_it.first->second;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600390
391 uint32_t queue_family_index = 0;
392
393 auto queue_state_it = object_ptr->queueMap.find(queue);
394 if (queue_state_it != object_ptr->queueMap.end()) {
395 queue_family_index = queue_state_it->second.queueFamilyIndex;
396 }
397
398 VkResult result = VK_SUCCESS;
399
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600400 auto pool_create_info = LvlInitStruct<VkCommandPoolCreateInfo>();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600401 pool_create_info.queueFamilyIndex = queue_family_index;
402 result = DispatchCreateCommandPool(object_ptr->device, &pool_create_info, nullptr,
403 &queue_barrier_command_info.barrier_command_pool);
404 if (result != VK_SUCCESS) {
405 object_ptr->ReportSetupProblem(object_ptr->device, "Unable to create command pool for barrier CB.");
406 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
407 return;
408 }
409
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600410 auto buffer_alloc_info = LvlInitStruct<VkCommandBufferAllocateInfo>();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600411 buffer_alloc_info.commandPool = queue_barrier_command_info.barrier_command_pool;
412 buffer_alloc_info.commandBufferCount = 1;
413 buffer_alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
414 result = DispatchAllocateCommandBuffers(object_ptr->device, &buffer_alloc_info,
415 &queue_barrier_command_info.barrier_command_buffer);
416 if (result != VK_SUCCESS) {
417 object_ptr->ReportSetupProblem(object_ptr->device, "Unable to create barrier command buffer.");
418 DispatchDestroyCommandPool(object_ptr->device, queue_barrier_command_info.barrier_command_pool, nullptr);
419 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
420 queue_barrier_command_info.barrier_command_buffer = VK_NULL_HANDLE;
421 return;
422 }
423
424 // Hook up command buffer dispatch
425 object_ptr->vkSetDeviceLoaderData(object_ptr->device, queue_barrier_command_info.barrier_command_buffer);
426
427 // Record a global memory barrier to force availability of device memory operations to the host domain.
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600428 auto command_buffer_begin_info = LvlInitStruct<VkCommandBufferBeginInfo>();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600429 result = DispatchBeginCommandBuffer(queue_barrier_command_info.barrier_command_buffer, &command_buffer_begin_info);
430 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600431 auto memory_barrier = LvlInitStruct<VkMemoryBarrier>();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600432 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
433 memory_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
434
435 DispatchCmdPipelineBarrier(queue_barrier_command_info.barrier_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
436 VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &memory_barrier, 0, nullptr, 0, nullptr);
437 DispatchEndCommandBuffer(queue_barrier_command_info.barrier_command_buffer);
438 }
439 }
440
Tony-LunarGb5fae462020-03-05 12:43:25 -0700441 UtilQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_it.first->second;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600442 if (queue_barrier_command_info.barrier_command_buffer != VK_NULL_HANDLE) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600443 auto submit_info = LvlInitStruct<VkSubmitInfo>();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600444 submit_info.commandBufferCount = 1;
445 submit_info.pCommandBuffers = &queue_barrier_command_info.barrier_command_buffer;
446 DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
447 }
448}
Tony-LunarGb5fae462020-03-05 12:43:25 -0700449void UtilGenerateStageMessage(const uint32_t *debug_record, std::string &msg);
450void UtilGenerateCommonMessage(const debug_report_data *report_data, const VkCommandBuffer commandBuffer,
451 const uint32_t *debug_record, const VkShaderModule shader_module_handle,
452 const VkPipeline pipeline_handle, const VkPipelineBindPoint pipeline_bind_point,
453 const uint32_t operation_index, std::string &msg);
454void UtilGenerateSourceMessages(const std::vector<unsigned int> &pgm, const uint32_t *debug_record, bool from_printf,
455 std::string &filename_msg, std::string &source_msg);