blob: 5b47827d082e6743aa015e41fee6b85940b55c14 [file] [log] [blame]
sfricke-samsungef15e482022-01-26 11:32:49 -08001/* Copyright (c) 2020-2022 The Khronos Group Inc.
2 * Copyright (c) 2020-2022 Valve Corporation
3 * Copyright (c) 2020-2022 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"
Jeremy Gebbend177d922021-10-28 13:42:10 -060023class QUEUE_STATE;
Jeremy Gebben159b3cc2021-06-03 09:09:03 -060024
Tony-LunarGb5fae462020-03-05 12:43:25 -070025class UtilDescriptorSetManager {
Tony-LunarG1dce2392019-10-23 16:49:29 -060026 public:
Tony-LunarGb5fae462020-03-05 12:43:25 -070027 UtilDescriptorSetManager(VkDevice device, uint32_t numBindingsInSet);
28 ~UtilDescriptorSetManager();
Tony-LunarG1dce2392019-10-23 16:49:29 -060029
30 VkResult GetDescriptorSet(VkDescriptorPool *desc_pool, VkDescriptorSetLayout ds_layout, VkDescriptorSet *desc_sets);
31 VkResult GetDescriptorSets(uint32_t count, VkDescriptorPool *pool, VkDescriptorSetLayout ds_layout,
32 std::vector<VkDescriptorSet> *desc_sets);
33 void PutBackDescriptorSet(VkDescriptorPool desc_pool, VkDescriptorSet desc_set);
34
35 private:
36 static const uint32_t kItemsPerChunk = 512;
37 struct PoolTracker {
38 uint32_t size;
39 uint32_t used;
40 };
41 VkDevice device;
42 uint32_t numBindingsInSet;
Jeremy Gebbencbf22862021-03-03 12:01:22 -070043 layer_data::unordered_map<VkDescriptorPool, struct PoolTracker> desc_pool_map_;
Tony-LunarG1dce2392019-10-23 16:49:29 -060044};
Tony-LunarGb5fae462020-03-05 12:43:25 -070045struct UtilQueueBarrierCommandInfo {
Tony-LunarG1dce2392019-10-23 16:49:29 -060046 VkCommandPool barrier_command_pool = VK_NULL_HANDLE;
47 VkCommandBuffer barrier_command_buffer = VK_NULL_HANDLE;
48};
Tony-LunarGb5fae462020-03-05 12:43:25 -070049VkResult UtilInitializeVma(VkPhysicalDevice physical_device, VkDevice device, VmaAllocator *pAllocator);
50void UtilPreCallRecordCreateDevice(VkPhysicalDevice gpu, safe_VkDeviceCreateInfo *modified_create_info,
51 VkPhysicalDeviceFeatures supported_features, VkPhysicalDeviceFeatures desired_features);
Tony-LunarG1dce2392019-10-23 16:49:29 -060052template <typename ObjectType>
Tony-LunarGb5fae462020-03-05 12:43:25 -070053void UtilPostCallRecordCreateDevice(const VkDeviceCreateInfo *pCreateInfo, std::vector<VkDescriptorSetLayoutBinding> bindings,
54 ObjectType *object_ptr, VkPhysicalDeviceProperties physical_device_properties) {
Tony-LunarG1dce2392019-10-23 16:49:29 -060055 // If api version 1.1 or later, SetDeviceLoaderData will be in the loader
56 auto chain_info = get_chain_info(pCreateInfo, VK_LOADER_DATA_CALLBACK);
57 assert(chain_info->u.pfnSetDeviceLoaderData);
58 object_ptr->vkSetDeviceLoaderData = chain_info->u.pfnSetDeviceLoaderData;
59
60 // Some devices have extremely high limits here, so set a reasonable max because we have to pad
61 // the pipeline layout with dummy descriptor set layouts.
62 object_ptr->adjusted_max_desc_sets = physical_device_properties.limits.maxBoundDescriptorSets;
63 object_ptr->adjusted_max_desc_sets = std::min(33U, object_ptr->adjusted_max_desc_sets);
64
65 // We can't do anything if there is only one.
66 // Device probably not a legit Vulkan device, since there should be at least 4. Protect ourselves.
67 if (object_ptr->adjusted_max_desc_sets == 1) {
68 object_ptr->ReportSetupProblem(object_ptr->device, "Device can bind only a single descriptor set.");
69 object_ptr->aborted = true;
70 return;
71 }
72 object_ptr->desc_set_bind_index = object_ptr->adjusted_max_desc_sets - 1;
73
Jeremy Gebben14499e82022-03-17 11:03:10 -060074 VkResult result1 = UtilInitializeVma(object_ptr->physical_device, object_ptr->device, &object_ptr->vmaAllocator);
Tony-LunarG1dce2392019-10-23 16:49:29 -060075 assert(result1 == VK_SUCCESS);
Tony-LunarGb5fae462020-03-05 12:43:25 -070076 std::unique_ptr<UtilDescriptorSetManager> desc_set_manager(
77 new UtilDescriptorSetManager(object_ptr->device, static_cast<uint32_t>(bindings.size())));
Tony-LunarG1dce2392019-10-23 16:49:29 -060078
79 const VkDescriptorSetLayoutCreateInfo debug_desc_layout_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, 0,
80 static_cast<uint32_t>(bindings.size()), bindings.data()};
81
82 const VkDescriptorSetLayoutCreateInfo dummy_desc_layout_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, NULL, 0, 0,
83 NULL};
84
85 result1 = DispatchCreateDescriptorSetLayout(object_ptr->device, &debug_desc_layout_info, NULL, &object_ptr->debug_desc_layout);
86
87 // This is a layout used to "pad" a pipeline layout to fill in any gaps to the selected bind index.
88 VkResult result2 =
89 DispatchCreateDescriptorSetLayout(object_ptr->device, &dummy_desc_layout_info, NULL, &object_ptr->dummy_desc_layout);
90
91 assert((result1 == VK_SUCCESS) && (result2 == VK_SUCCESS));
92 if ((result1 != VK_SUCCESS) || (result2 != VK_SUCCESS)) {
93 object_ptr->ReportSetupProblem(object_ptr->device, "Unable to create descriptor set layout.");
94 if (result1 == VK_SUCCESS) {
95 DispatchDestroyDescriptorSetLayout(object_ptr->device, object_ptr->debug_desc_layout, NULL);
96 }
97 if (result2 == VK_SUCCESS) {
98 DispatchDestroyDescriptorSetLayout(object_ptr->device, object_ptr->dummy_desc_layout, NULL);
99 }
100 object_ptr->debug_desc_layout = VK_NULL_HANDLE;
101 object_ptr->dummy_desc_layout = VK_NULL_HANDLE;
102 object_ptr->aborted = true;
103 return;
104 }
105 object_ptr->desc_set_manager = std::move(desc_set_manager);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600106}
107template <typename ObjectType>
Tony-LunarGb5fae462020-03-05 12:43:25 -0700108void UtilPreCallRecordDestroyDevice(ObjectType *object_ptr) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600109 for (auto &queue_barrier_command_info_kv : object_ptr->queue_barrier_command_infos) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700110 UtilQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_kv.second;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600111
112 DispatchFreeCommandBuffers(object_ptr->device, queue_barrier_command_info.barrier_command_pool, 1,
113 &queue_barrier_command_info.barrier_command_buffer);
114 queue_barrier_command_info.barrier_command_buffer = VK_NULL_HANDLE;
115
116 DispatchDestroyCommandPool(object_ptr->device, queue_barrier_command_info.barrier_command_pool, NULL);
117 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
118 }
119 object_ptr->queue_barrier_command_infos.clear();
120 if (object_ptr->debug_desc_layout) {
121 DispatchDestroyDescriptorSetLayout(object_ptr->device, object_ptr->debug_desc_layout, NULL);
122 object_ptr->debug_desc_layout = VK_NULL_HANDLE;
123 }
124 if (object_ptr->dummy_desc_layout) {
125 DispatchDestroyDescriptorSetLayout(object_ptr->device, object_ptr->dummy_desc_layout, NULL);
126 object_ptr->dummy_desc_layout = VK_NULL_HANDLE;
127 }
Tony-LunarG1dce2392019-10-23 16:49:29 -0600128}
129
130template <typename ObjectType>
Tony-LunarGb5fae462020-03-05 12:43:25 -0700131void UtilPreCallRecordCreatePipelineLayout(create_pipeline_layout_api_state *cpl_state, ObjectType *object_ptr,
132 const VkPipelineLayoutCreateInfo *pCreateInfo) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600133 // Modify the pipeline layout by:
134 // 1. Copying the caller's descriptor set desc_layouts
135 // 2. Fill in dummy descriptor layouts up to the max binding
136 // 3. Fill in with the debug descriptor layout at the max binding slot
137 cpl_state->new_layouts.reserve(object_ptr->adjusted_max_desc_sets);
138 cpl_state->new_layouts.insert(cpl_state->new_layouts.end(), &pCreateInfo->pSetLayouts[0],
139 &pCreateInfo->pSetLayouts[pCreateInfo->setLayoutCount]);
140 for (uint32_t i = pCreateInfo->setLayoutCount; i < object_ptr->adjusted_max_desc_sets - 1; ++i) {
141 cpl_state->new_layouts.push_back(object_ptr->dummy_desc_layout);
142 }
143 cpl_state->new_layouts.push_back(object_ptr->debug_desc_layout);
144 cpl_state->modified_create_info.pSetLayouts = cpl_state->new_layouts.data();
145 cpl_state->modified_create_info.setLayoutCount = object_ptr->adjusted_max_desc_sets;
146}
147
148template <typename CreateInfo>
149struct CreatePipelineTraits {};
150template <>
151struct CreatePipelineTraits<VkGraphicsPipelineCreateInfo> {
152 using SafeType = safe_VkGraphicsPipelineCreateInfo;
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700153 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) {
154 return pipeline_state->GetUnifiedCreateInfo().graphics;
155 }
Tony-LunarG1dce2392019-10-23 16:49:29 -0600156 static uint32_t GetStageCount(const VkGraphicsPipelineCreateInfo &createInfo) { return createInfo.stageCount; }
157 static VkShaderModule GetShaderModule(const VkGraphicsPipelineCreateInfo &createInfo, uint32_t stage) {
158 return createInfo.pStages[stage].module;
159 }
160 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
161 createInfo->pStages[stage].module = shader_module;
162 }
163};
164
165template <>
166struct CreatePipelineTraits<VkComputePipelineCreateInfo> {
167 using SafeType = safe_VkComputePipelineCreateInfo;
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700168 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) {
169 return pipeline_state->GetUnifiedCreateInfo().compute;
170 }
Tony-LunarG1dce2392019-10-23 16:49:29 -0600171 static uint32_t GetStageCount(const VkComputePipelineCreateInfo &createInfo) { return 1; }
172 static VkShaderModule GetShaderModule(const VkComputePipelineCreateInfo &createInfo, uint32_t stage) {
173 return createInfo.stage.module;
174 }
175 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
176 assert(stage == 0);
177 createInfo->stage.module = shader_module;
178 }
179};
180
181template <>
182struct CreatePipelineTraits<VkRayTracingPipelineCreateInfoNV> {
183 using SafeType = safe_VkRayTracingPipelineCreateInfoCommon;
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700184 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) {
185 return pipeline_state->GetUnifiedCreateInfo().raytracing;
186 }
Tony-LunarG1dce2392019-10-23 16:49:29 -0600187 static uint32_t GetStageCount(const VkRayTracingPipelineCreateInfoNV &createInfo) { return createInfo.stageCount; }
188 static VkShaderModule GetShaderModule(const VkRayTracingPipelineCreateInfoNV &createInfo, uint32_t stage) {
189 return createInfo.pStages[stage].module;
190 }
191 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
192 createInfo->pStages[stage].module = shader_module;
193 }
194};
195
196template <>
197struct CreatePipelineTraits<VkRayTracingPipelineCreateInfoKHR> {
198 using SafeType = safe_VkRayTracingPipelineCreateInfoCommon;
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700199 static const SafeType &GetPipelineCI(const PIPELINE_STATE *pipeline_state) {
200 return pipeline_state->GetUnifiedCreateInfo().raytracing;
201 }
Tony-LunarG1dce2392019-10-23 16:49:29 -0600202 static uint32_t GetStageCount(const VkRayTracingPipelineCreateInfoKHR &createInfo) { return createInfo.stageCount; }
203 static VkShaderModule GetShaderModule(const VkRayTracingPipelineCreateInfoKHR &createInfo, uint32_t stage) {
204 return createInfo.pStages[stage].module;
205 }
206 static void SetShaderModule(SafeType *createInfo, VkShaderModule shader_module, uint32_t stage) {
207 createInfo->pStages[stage].module = shader_module;
208 }
209};
210
211// Examine the pipelines to see if they use the debug descriptor set binding index.
212// If any do, create new non-instrumented shader modules and use them to replace the instrumented
213// shaders in the pipeline. Return the (possibly) modified create infos to the caller.
214template <typename CreateInfo, typename SafeCreateInfo, typename ObjectType>
Tony-LunarGb5fae462020-03-05 12:43:25 -0700215void UtilPreCallRecordPipelineCreations(uint32_t count, const CreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
216 VkPipeline *pPipelines, std::vector<std::shared_ptr<PIPELINE_STATE>> &pipe_state,
217 std::vector<SafeCreateInfo> *new_pipeline_create_infos,
218 const VkPipelineBindPoint bind_point, ObjectType *object_ptr) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600219 using Accessor = CreatePipelineTraits<CreateInfo>;
220 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
221 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
222 return;
223 }
224
225 // Walk through all the pipelines, make a copy of each and flag each pipeline that contains a shader that uses the debug
226 // descriptor set index.
227 for (uint32_t pipeline = 0; pipeline < count; ++pipeline) {
228 uint32_t stageCount = Accessor::GetStageCount(pCreateInfos[pipeline]);
229 new_pipeline_create_infos->push_back(Accessor::GetPipelineCI(pipe_state[pipeline].get()));
Nathaniel Cesariobcb79682022-03-31 21:13:52 -0600230 const auto &pipe = pipe_state[pipeline];
Tony-LunarG1dce2392019-10-23 16:49:29 -0600231
Nathaniel Cesariobcb79682022-03-31 21:13:52 -0600232 if (!pipe->IsGraphicsLibrary()) {
233 bool replace_shaders = false;
234 if (pipe->active_slots.find(object_ptr->desc_set_bind_index) != pipe->active_slots.end()) {
235 replace_shaders = true;
236 }
237 // If the app requests all available sets, the pipeline layout was not modified at pipeline layout creation and the
238 // already instrumented shaders need to be replaced with uninstrumented shaders
239 const auto pipeline_layout = pipe->PipelineLayoutState();
240 if (pipeline_layout->set_layouts.size() >= object_ptr->adjusted_max_desc_sets) {
241 replace_shaders = true;
242 }
Tony-LunarG1dce2392019-10-23 16:49:29 -0600243
Nathaniel Cesariobcb79682022-03-31 21:13:52 -0600244 if (replace_shaders) {
245 for (uint32_t stage = 0; stage < stageCount; ++stage) {
246 const auto module_state =
247 object_ptr->template Get<SHADER_MODULE_STATE>(Accessor::GetShaderModule(pCreateInfos[pipeline], stage));
Tony-LunarG1dce2392019-10-23 16:49:29 -0600248
Nathaniel Cesariobcb79682022-03-31 21:13:52 -0600249 VkShaderModule shader_module;
250 auto create_info = LvlInitStruct<VkShaderModuleCreateInfo>();
251 create_info.pCode = module_state->words.data();
252 create_info.codeSize = module_state->words.size() * sizeof(uint32_t);
253 VkResult result = DispatchCreateShaderModule(object_ptr->device, &create_info, pAllocator, &shader_module);
254 if (result == VK_SUCCESS) {
255 Accessor::SetShaderModule(&(*new_pipeline_create_infos)[pipeline], shader_module, stage);
256 } else {
257 object_ptr->ReportSetupProblem(object_ptr->device,
258 "Unable to replace instrumented shader with non-instrumented one. "
259 "Device could become unstable.");
260 }
Tony-LunarG1dce2392019-10-23 16:49:29 -0600261 }
262 }
263 }
264 }
265}
266// For every pipeline:
267// - For every shader in a pipeline:
268// - If the shader had to be replaced in PreCallRecord (because the pipeline is using the debug desc set index):
269// - Destroy it since it has been bound into the pipeline by now. This is our only chance to delete it.
270// - Track the shader in the shader_map
271// - Save the shader binary if it contains debug code
272template <typename CreateInfo, typename ObjectType>
Tony-LunarGb5fae462020-03-05 12:43:25 -0700273void UtilPostCallRecordPipelineCreations(const uint32_t count, const CreateInfo *pCreateInfos,
aitor-lunarg3c145292022-03-25 17:30:11 +0100274 const VkAllocationCallbacks *pAllocator, const VkPipeline *pPipelines,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700275 const VkPipelineBindPoint bind_point, ObjectType *object_ptr) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600276 using Accessor = CreatePipelineTraits<CreateInfo>;
277 if (bind_point != VK_PIPELINE_BIND_POINT_GRAPHICS && bind_point != VK_PIPELINE_BIND_POINT_COMPUTE &&
278 bind_point != VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
279 return;
280 }
281 for (uint32_t pipeline = 0; pipeline < count; ++pipeline) {
Jeremy Gebbenb20a8242021-11-05 15:14:43 -0600282 auto pipeline_state = object_ptr->template Get<PIPELINE_STATE>(pPipelines[pipeline]);
Nathaniel Cesariobcb79682022-03-31 21:13:52 -0600283 if (!pipeline_state || pipeline_state->IsGraphicsLibrary()) continue;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600284
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700285 const uint32_t stageCount = static_cast<uint32_t>(pipeline_state->stage_state.size());
286 assert(stageCount > 0);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600287
288 for (uint32_t stage = 0; stage < stageCount; ++stage) {
289 if (pipeline_state->active_slots.find(object_ptr->desc_set_bind_index) != pipeline_state->active_slots.end()) {
290 DispatchDestroyShaderModule(object_ptr->device, Accessor::GetShaderModule(pCreateInfos[pipeline], stage),
291 pAllocator);
292 }
293
sfricke-samsungef15e482022-01-26 11:32:49 -0800294 std::shared_ptr<const SHADER_MODULE_STATE> module_state;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600295 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700296 module_state = object_ptr->template Get<SHADER_MODULE_STATE>(
297 pipeline_state->GetUnifiedCreateInfo().graphics.pStages[stage].module);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600298 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
299 assert(stage == 0);
sfricke-samsungef15e482022-01-26 11:32:49 -0800300 module_state =
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700301 object_ptr->template Get<SHADER_MODULE_STATE>(pipeline_state->GetUnifiedCreateInfo().compute.stage.module);
302 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
303 module_state = object_ptr->template Get<SHADER_MODULE_STATE>(
304 pipeline_state->GetUnifiedCreateInfo().raytracing.pStages[stage].module);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600305 } else {
306 assert(false);
307 }
308
309 std::vector<unsigned int> code;
310 // Save the shader binary
311 // The core_validation ShaderModule tracker saves the binary too, but discards it when the ShaderModule
312 // is destroyed. Applications may destroy ShaderModules after they are placed in a pipeline and before
313 // the pipeline is used, so we have to keep another copy.
sfricke-samsungef15e482022-01-26 11:32:49 -0800314 if (module_state && module_state->has_valid_spirv) code = module_state->words;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600315
sfricke-samsungef15e482022-01-26 11:32:49 -0800316 object_ptr->shader_map[module_state->gpu_validation_shader_id].pipeline = pipeline_state->pipeline();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600317 // Be careful to use the originally bound (instrumented) shader here, even if PreCallRecord had to back it
318 // out with a non-instrumented shader. The non-instrumented shader (found in pCreateInfo) was destroyed above.
319 VkShaderModule shader_module = VK_NULL_HANDLE;
320 if (bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700321 shader_module = pipeline_state->GetUnifiedCreateInfo().graphics.pStages[stage].module;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600322 } else if (bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
323 assert(stage == 0);
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700324 shader_module = pipeline_state->GetUnifiedCreateInfo().compute.stage.module;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600325 } else if (bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
Nathaniel Cesario3fd4f762022-02-16 16:07:06 -0700326 shader_module = pipeline_state->GetUnifiedCreateInfo().raytracing.pStages[stage].module;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600327 } else {
328 assert(false);
329 }
sfricke-samsungef15e482022-01-26 11:32:49 -0800330 object_ptr->shader_map[module_state->gpu_validation_shader_id].shader_module = shader_module;
331 object_ptr->shader_map[module_state->gpu_validation_shader_id].pgm = std::move(code);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600332 }
333 }
334}
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600335template <typename CreateInfos, typename SafeCreateInfos>
336void UtilCopyCreatePipelineFeedbackData(const uint32_t count, CreateInfos *pCreateInfos, SafeCreateInfos *pSafeCreateInfos) {
337 for (uint32_t i = 0; i < count; i++) {
Mark Lobodzinski1f887d32020-12-30 15:31:33 -0700338 auto src_feedback_struct = LvlFindInChain<VkPipelineCreationFeedbackCreateInfoEXT>(pSafeCreateInfos[i].pNext);
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600339 if (!src_feedback_struct) return;
340 auto dst_feedback_struct = const_cast<VkPipelineCreationFeedbackCreateInfoEXT *>(
Mark Lobodzinski1f887d32020-12-30 15:31:33 -0700341 LvlFindInChain<VkPipelineCreationFeedbackCreateInfoEXT>(pCreateInfos[i].pNext));
Tony-LunarGc876c6e2020-09-09 15:19:43 -0600342 *dst_feedback_struct->pPipelineCreationFeedback = *src_feedback_struct->pPipelineCreationFeedback;
343 for (uint32_t j = 0; j < src_feedback_struct->pipelineStageCreationFeedbackCount; j++) {
344 dst_feedback_struct->pPipelineStageCreationFeedbacks[j] = src_feedback_struct->pPipelineStageCreationFeedbacks[j];
345 }
346 }
347}
348
Tony-LunarG1dce2392019-10-23 16:49:29 -0600349template <typename ObjectType>
350// For the given command buffer, map its debug data buffers and read their contents for analysis.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700351void UtilProcessInstrumentationBuffer(VkQueue queue, CMD_BUFFER_STATE *cb_node, ObjectType *object_ptr) {
Tony-LunarG1dce2392019-10-23 16:49:29 -0600352 if (cb_node && (cb_node->hasDrawCmd || cb_node->hasTraceRaysCmd || cb_node->hasDispatchCmd)) {
Jeremy Gebbenf6bb4bb2021-08-11 15:41:09 -0600353 auto gpu_buffer_list = object_ptr->GetBufferInfo(cb_node);
Tony-LunarG1dce2392019-10-23 16:49:29 -0600354 uint32_t draw_index = 0;
355 uint32_t compute_index = 0;
356 uint32_t ray_trace_index = 0;
357
358 for (auto &buffer_info : gpu_buffer_list) {
359 char *pData;
360
361 uint32_t operation_index = 0;
362 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
363 operation_index = draw_index;
364 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
365 operation_index = compute_index;
366 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
367 operation_index = ray_trace_index;
368 } else {
369 assert(false);
370 }
371
372 VkResult result = vmaMapMemory(object_ptr->vmaAllocator, buffer_info.output_mem_block.allocation, (void **)&pData);
373 if (result == VK_SUCCESS) {
Jeremy Gebben14b0d1a2021-05-15 20:15:41 -0600374 object_ptr->AnalyzeAndGenerateMessages(cb_node->commandBuffer(), queue, buffer_info,
Tony-LunarG1dce2392019-10-23 16:49:29 -0600375 operation_index, (uint32_t *)pData);
376 vmaUnmapMemory(object_ptr->vmaAllocator, buffer_info.output_mem_block.allocation);
377 }
378
379 if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_GRAPHICS) {
380 draw_index++;
381 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_COMPUTE) {
382 compute_index++;
383 } else if (buffer_info.pipeline_bind_point == VK_PIPELINE_BIND_POINT_RAY_TRACING_NV) {
384 ray_trace_index++;
385 } else {
386 assert(false);
387 }
388 }
389 }
390}
391template <typename ObjectType>
392// Submit a memory barrier on graphics queues.
393// Lazy-create and record the needed command buffer.
Tony-LunarGb5fae462020-03-05 12:43:25 -0700394void UtilSubmitBarrier(VkQueue queue, ObjectType *object_ptr) {
395 auto queue_barrier_command_info_it = object_ptr->queue_barrier_command_infos.emplace(queue, UtilQueueBarrierCommandInfo{});
Tony-LunarG1dce2392019-10-23 16:49:29 -0600396 if (queue_barrier_command_info_it.second) {
Tony-LunarGb5fae462020-03-05 12:43:25 -0700397 UtilQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_it.first->second;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600398
399 uint32_t queue_family_index = 0;
400
Jeremy Gebben9f537102021-10-05 16:37:12 -0600401 auto queue_state = object_ptr->ValidationStateTracker::template Get<QUEUE_STATE>(queue);
Jeremy Gebbend177d922021-10-28 13:42:10 -0600402 if (queue_state) {
403 queue_family_index = queue_state->queueFamilyIndex;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600404 }
405
406 VkResult result = VK_SUCCESS;
407
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600408 auto pool_create_info = LvlInitStruct<VkCommandPoolCreateInfo>();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600409 pool_create_info.queueFamilyIndex = queue_family_index;
410 result = DispatchCreateCommandPool(object_ptr->device, &pool_create_info, nullptr,
411 &queue_barrier_command_info.barrier_command_pool);
412 if (result != VK_SUCCESS) {
413 object_ptr->ReportSetupProblem(object_ptr->device, "Unable to create command pool for barrier CB.");
414 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
415 return;
416 }
417
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600418 auto buffer_alloc_info = LvlInitStruct<VkCommandBufferAllocateInfo>();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600419 buffer_alloc_info.commandPool = queue_barrier_command_info.barrier_command_pool;
420 buffer_alloc_info.commandBufferCount = 1;
421 buffer_alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
422 result = DispatchAllocateCommandBuffers(object_ptr->device, &buffer_alloc_info,
423 &queue_barrier_command_info.barrier_command_buffer);
424 if (result != VK_SUCCESS) {
425 object_ptr->ReportSetupProblem(object_ptr->device, "Unable to create barrier command buffer.");
426 DispatchDestroyCommandPool(object_ptr->device, queue_barrier_command_info.barrier_command_pool, nullptr);
427 queue_barrier_command_info.barrier_command_pool = VK_NULL_HANDLE;
428 queue_barrier_command_info.barrier_command_buffer = VK_NULL_HANDLE;
429 return;
430 }
431
432 // Hook up command buffer dispatch
433 object_ptr->vkSetDeviceLoaderData(object_ptr->device, queue_barrier_command_info.barrier_command_buffer);
434
435 // Record a global memory barrier to force availability of device memory operations to the host domain.
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600436 auto command_buffer_begin_info = LvlInitStruct<VkCommandBufferBeginInfo>();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600437 result = DispatchBeginCommandBuffer(queue_barrier_command_info.barrier_command_buffer, &command_buffer_begin_info);
438 if (result == VK_SUCCESS) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600439 auto memory_barrier = LvlInitStruct<VkMemoryBarrier>();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600440 memory_barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
441 memory_barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
442
443 DispatchCmdPipelineBarrier(queue_barrier_command_info.barrier_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
444 VK_PIPELINE_STAGE_HOST_BIT, 0, 1, &memory_barrier, 0, nullptr, 0, nullptr);
445 DispatchEndCommandBuffer(queue_barrier_command_info.barrier_command_buffer);
446 }
447 }
448
Tony-LunarGb5fae462020-03-05 12:43:25 -0700449 UtilQueueBarrierCommandInfo &queue_barrier_command_info = queue_barrier_command_info_it.first->second;
Tony-LunarG1dce2392019-10-23 16:49:29 -0600450 if (queue_barrier_command_info.barrier_command_buffer != VK_NULL_HANDLE) {
Nathaniel Cesariofc6291e2021-04-06 00:22:15 -0600451 auto submit_info = LvlInitStruct<VkSubmitInfo>();
Tony-LunarG1dce2392019-10-23 16:49:29 -0600452 submit_info.commandBufferCount = 1;
453 submit_info.pCommandBuffers = &queue_barrier_command_info.barrier_command_buffer;
454 DispatchQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
455 }
456}
Tony-LunarGb5fae462020-03-05 12:43:25 -0700457void UtilGenerateStageMessage(const uint32_t *debug_record, std::string &msg);
458void UtilGenerateCommonMessage(const debug_report_data *report_data, const VkCommandBuffer commandBuffer,
459 const uint32_t *debug_record, const VkShaderModule shader_module_handle,
460 const VkPipeline pipeline_handle, const VkPipelineBindPoint pipeline_bind_point,
461 const uint32_t operation_index, std::string &msg);
sfricke-samsung7fac88a2022-01-26 11:44:22 -0800462void UtilGenerateSourceMessages(const std::vector<uint32_t> &pgm, const uint32_t *debug_record, bool from_printf,
Tony-LunarGb5fae462020-03-05 12:43:25 -0700463 std::string &filename_msg, std::string &source_msg);