-
Notifications
You must be signed in to change notification settings - Fork 479
gpuav: Select pipeline to instrument post creation #12291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |||
| #include <vulkan/vulkan_core.h> | ||||
| #include <cstdint> | ||||
|
|
||||
| #include "containers/container_utils.h" | ||||
| #include "error_message/error_location.h" | ||||
| #include "generated/vk_extension_helper.h" | ||||
| #include "generated/dispatch_functions.h" | ||||
|
|
@@ -405,6 +406,120 @@ void GpuShaderInstrumentor::PreCallRecordCreatePipelineLayout(VkDevice device, c | |||
| } | ||||
| } | ||||
|
|
||||
| void GpuShaderInstrumentor::PreCallRecordSetDebugUtilsObjectNameEXT(VkDevice device, const VkDebugUtilsObjectNameInfoEXT* pNameInfo, | ||||
| const RecordObject& record_obj) { | ||||
| if (!gpuav_settings.select_instrumented_shaders) { | ||||
| return; | ||||
| } | ||||
|
|
||||
| if (!gpuav_settings.IsSpirvModified()) { | ||||
| return; | ||||
| } | ||||
| if (pNameInfo->objectType != VK_OBJECT_TYPE_PIPELINE || !pNameInfo->pObjectName) { | ||||
| return; | ||||
| } | ||||
|
|
||||
| if (!gpuav_settings.MatchesAnyShaderSelectionRegex(pNameInfo->pObjectName)) { | ||||
| return; | ||||
| } | ||||
|
|
||||
| if (disabled[handle_wrapping]) { | ||||
| InternalError(LogObjectList(), record_obj.location, | ||||
| "For GPU-AV selective pipeline instrumentation post creation to work, handle wrapping needs to be enabled."); | ||||
| return; | ||||
| } | ||||
|
|
||||
| VkPipeline wrapped_pipeline = CastFromUint64<VkPipeline>(pNameInfo->objectHandle); | ||||
| auto pipeline_state = Get<vvl::Pipeline>(wrapped_pipeline); | ||||
| ASSERT_AND_RETURN(pipeline_state); | ||||
|
|
||||
| if (pipeline_state->instrumentation_data.was_instrumented) { | ||||
| return; | ||||
| } | ||||
|
|
||||
| if (!NeedPipelineCreationShaderInstrumentation(*pipeline_state, record_obj.location)) { | ||||
| return; | ||||
| } | ||||
|
|
||||
| // The pipeline was selected by name, not by individual shader name, so force all its shaders to be instrumented | ||||
| for (const auto& stage_state : pipeline_state->stage_states) { | ||||
| if (stage_state.module_state && stage_state.module_state->VkHandle() != VK_NULL_HANDLE) { | ||||
| selected_instrumented_shaders.insert(stage_state.module_state->VkHandle()); | ||||
| } | ||||
| } | ||||
|
|
||||
| VkPipeline instrumented_pipeline = VK_NULL_HANDLE; | ||||
| // Can't instrument ray tracing pipeline post creation, | ||||
| // As corresponding shader binding tables may have already been created. | ||||
| if (pipeline_state->linking_shaders == 0 && | ||||
|
arno-lunarg marked this conversation as resolved.
|
||||
| IsValueIn(pipeline_state->pipeline_type, {VK_PIPELINE_BIND_POINT_GRAPHICS, VK_PIPELINE_BIND_POINT_COMPUTE})) { | ||||
|
arno-lunarg marked this conversation as resolved.
|
||||
| std::vector<chassis::ShaderInstrumentationMetadata> shader_instrumentation_metadata; | ||||
| if (pipeline_state->pipeline_type == VK_PIPELINE_BIND_POINT_GRAPHICS) { | ||||
| vku::safe_VkGraphicsPipelineCreateInfo new_pipeline_ci(pipeline_state->GraphicsCreateInfo()); | ||||
| new_pipeline_ci.flags &= ~VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT; | ||||
| const bool success = PreCallRecordPipelineCreationShaderInstrumentation( | ||||
| nullptr, *pipeline_state, new_pipeline_ci, uint32_t(pipeline_state->stage_states.size()), record_obj.location, | ||||
| shader_instrumentation_metadata); | ||||
| if (!success) { | ||||
| InternalError(device, record_obj.location, "Failed to instrument graphics pipeline in SetDebugUtilsObjectNameEXT."); | ||||
| return; | ||||
| } | ||||
|
|
||||
| const VkResult result = | ||||
| DispatchCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, new_pipeline_ci.ptr(), nullptr, &instrumented_pipeline); | ||||
| if (result != VK_SUCCESS || instrumented_pipeline == VK_NULL_HANDLE) { | ||||
| InternalError(device, record_obj.location, | ||||
| "Failed to create instrumented graphics pipeline in SetDebugUtilsObjectNameEXT."); | ||||
| return; | ||||
| } | ||||
| } else if (pipeline_state->pipeline_type == VK_PIPELINE_BIND_POINT_COMPUTE) { | ||||
| vku::safe_VkComputePipelineCreateInfo new_pipeline_ci(pipeline_state->ComputeCreateInfo()); | ||||
| new_pipeline_ci.flags &= ~VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT; | ||||
| const bool success = PreCallRecordPipelineCreationShaderInstrumentation( | ||||
| nullptr, *pipeline_state, new_pipeline_ci, uint32_t(pipeline_state->stage_states.size()), record_obj.location, | ||||
| shader_instrumentation_metadata); | ||||
| if (!success) { | ||||
| InternalError(device, record_obj.location, "Failed to instrument compute pipeline in SetDebugUtilsObjectNameEXT."); | ||||
| return; | ||||
| } | ||||
|
|
||||
| const VkResult result = | ||||
| DispatchCreateComputePipelines(device, VK_NULL_HANDLE, 1, new_pipeline_ci.ptr(), nullptr, &instrumented_pipeline); | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is broken and I crash locally running any test
the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes issues here, for some reason it did not explode on me, I conflated wrapped and unwrapped handles.... Having a hard time... wrapping my head around this problem EDIT: I had self validation on, with handle wrapping, it was saving me from crashes |
||||
| if (result != VK_SUCCESS || instrumented_pipeline == VK_NULL_HANDLE) { | ||||
| InternalError(device, record_obj.location, | ||||
| "Failed to create instrumented compute pipeline in SetDebugUtilsObjectNameEXT."); | ||||
| return; | ||||
| } | ||||
| } | ||||
|
|
||||
| PostCallRecordPipelineCreationShaderInstrumentation(*pipeline_state, uint32_t(pipeline_state->stage_states.size()), | ||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this seems wrong, you are missing in the old
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given how we use this stored pipeline handle, it's actually necessary to store the uninstrumented, "old", Vulkan-ValidationLayers/layers/gpuav/instrumentation/post_process_descriptor_indexing.cpp Line 196 in 2258223
to then access pipeline stages. |
||||
| shader_instrumentation_metadata); | ||||
| } else { | ||||
| vku::safe_VkGraphicsPipelineCreateInfo new_pipeline_ci(pipeline_state->GraphicsCreateInfo()); | ||||
| const bool success = | ||||
| PreCallRecordPipelineCreationShaderInstrumentationGPL(nullptr, *pipeline_state, new_pipeline_ci, record_obj.location); | ||||
| if (!success) { | ||||
| InternalError(device, record_obj.location, | ||||
| "Failed to instrument graphics pipeline library in SetDebugUtilsObjectNameEXT."); | ||||
| return; | ||||
| } | ||||
|
|
||||
| const VkResult result = | ||||
| DispatchCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, new_pipeline_ci.ptr(), nullptr, &instrumented_pipeline); | ||||
| if (result != VK_SUCCESS || instrumented_pipeline == VK_NULL_HANDLE) { | ||||
| InternalError(device, record_obj.location, | ||||
| "Failed to create instrumented graphics pipeline in SetDebugUtilsObjectNameEXT."); | ||||
| return; | ||||
| } | ||||
| } | ||||
|
|
||||
| auto layer_data = vvl::GetDispatchDevice(device); | ||||
| ASSERT_AND_RETURN(layer_data); | ||||
| const VkPipeline old_pipeline = layer_data->Replace(pipeline_state->VkHandle(), instrumented_pipeline); | ||||
| gpuav::PipelineSubState& pipeline_sub_state = SubState(*pipeline_state); | ||||
| pipeline_sub_state.AddHandleToDestroy(old_pipeline); | ||||
| } | ||||
|
|
||||
| void GpuShaderInstrumentor::PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, | ||||
| const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule, | ||||
| const RecordObject& record_obj, | ||||
|
|
@@ -739,6 +854,10 @@ void GpuShaderInstrumentor::PreCallRecordCreateRayTracingPipelinesKHR( | |||
| continue; | ||||
| } | ||||
|
|
||||
| if (!IsPipelineSelectedForInstrumentation(pCreateInfos[i].pNext, VK_NULL_HANDLE, create_info_loc)) { | ||||
| continue; | ||||
|
arno-lunarg marked this conversation as resolved.
|
||||
| } | ||||
|
|
||||
| auto& shader_instrumentation_metadata = chassis_state.shader_instrumentations_metadata[i]; | ||||
|
|
||||
| // Ray tracing pipelines can be made of libraries, but contrary to GPL instrumentation is not postponed | ||||
|
|
@@ -1117,20 +1236,26 @@ void GpuShaderInstrumentor::BuildDescriptorSetLayoutInfo(const vvl::DescriptorSe | |||
| } | ||||
| } | ||||
|
|
||||
| bool GpuShaderInstrumentor::IsPipelineSelectedForInstrumentation(VkPipeline pipeline, const Location& loc) { | ||||
| bool GpuShaderInstrumentor::IsPipelineSelectedForInstrumentation(const void* pipeline_ci_pnext, VkPipeline pipeline, | ||||
| const Location& loc) { | ||||
| if (!gpuav_settings.select_instrumented_shaders) { | ||||
| return true; | ||||
| } | ||||
|
|
||||
| bool should_instrument_pipeline = false; | ||||
| { | ||||
| std::string pipeline_debug_name; | ||||
| { | ||||
| if (auto debug = vku::FindStructInPNextChain<VkDebugUtilsObjectNameInfoEXT>(pipeline_ci_pnext)) { | ||||
| if (debug->pObjectName) { | ||||
| pipeline_debug_name = debug->pObjectName; | ||||
| } | ||||
| } else if (pipeline != VK_NULL_HANDLE) { | ||||
| std::unique_lock<std::mutex> lock(debug_report->debug_output_mutex); | ||||
| pipeline_debug_name = debug_report->GetUtilsObjectNameNoLock(HandleToUint64(pipeline)); | ||||
| } | ||||
|
|
||||
| should_instrument_pipeline = gpuav_settings.MatchesAnyShaderSelectionRegex(pipeline_debug_name); | ||||
| if (!pipeline_debug_name.empty()) { | ||||
| should_instrument_pipeline = gpuav_settings.MatchesAnyShaderSelectionRegex(pipeline_debug_name); | ||||
| } | ||||
| } | ||||
| if (should_instrument_pipeline) { | ||||
| LogInfo("GPU-AV::Selective shader instrumentation", LogObjectList(), loc, "(%s) will be instrumented for validation.", | ||||
|
|
@@ -1237,6 +1362,9 @@ bool GpuShaderInstrumentor::PreCallRecordPipelineCreationShaderInstrumentation( | |||
| // Can set this once for all shaders in the pipeline | ||||
| BuildDescriptorSetLayoutInfo(pipeline_state, interface.instrumentation_dsl); | ||||
|
|
||||
| bool is_pipeline_selected_for_instrumentation = | ||||
| IsPipelineSelectedForInstrumentation(modified_pipeline_ci.pNext, VK_NULL_HANDLE, loc); | ||||
|
|
||||
| for (uint32_t stage_state_i = 0; stage_state_i < stages_count; ++stage_state_i) { | ||||
| const auto& stage_state = pipeline_state.stage_states[stage_state_i]; | ||||
| auto modified_module_state = std::const_pointer_cast<vvl::ShaderModule>(stage_state.module_state); | ||||
|
|
@@ -1259,8 +1387,9 @@ bool GpuShaderInstrumentor::PreCallRecordPipelineCreationShaderInstrumentation( | |||
| const_cast<vku::safe_VkShaderModuleCreateInfo*>(reinterpret_cast<const vku::safe_VkShaderModuleCreateInfo*>( | ||||
| vku::FindStructInPNextChain<VkShaderModuleCreateInfo>(stage_ci.pNext))); | ||||
|
|
||||
| if (!IsShaderSelectedForInstrumentation(modified_shader_module_ci, modified_module_state->VkHandle(), | ||||
| loc.dot(vvl::Field::pStages, stage_state_i).dot(vvl::Field::module))) { | ||||
| if (!(is_pipeline_selected_for_instrumentation || | ||||
| IsShaderSelectedForInstrumentation(modified_shader_module_ci, modified_module_state->VkHandle(), | ||||
| loc.dot(vvl::Field::pStages, stage_state_i).dot(vvl::Field::module)))) { | ||||
| continue; | ||||
| } | ||||
| } | ||||
|
|
@@ -1416,10 +1545,15 @@ bool GpuShaderInstrumentor::PreCallRecordPipelineCreationShaderInstrumentationGP | |||
| // creation process no matter caching state. | ||||
| new_lib_ci.flags &= ~VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT; | ||||
| bool is_library_instrumented = false; | ||||
|
|
||||
| // If pipeline library is selected for instrumentation, force instrumentation of all its shaders | ||||
| const bool force_pipeline_instrumentation = | ||||
| IsPipelineSelectedForInstrumentation(modified_lib->VkHandle(), loc.dot(vvl::Field::pLibraries, modified_lib_i)); | ||||
| bool is_pipeline_selected_for_instrumentation = IsPipelineSelectedForInstrumentation( | ||||
| modified_pipeline_ci.pNext, modified_lib->VkHandle(), loc.dot(vvl::Field::pLibraries, modified_lib_i)); | ||||
| // Case where pipeline is instrumented post creation. Otherwise, pipeline handle has yet to be created! | ||||
| // currently only useful when this function is called in PreCallRecordSetDebugUtilsObjectNameEXT | ||||
| if (linked_pipeline_state.VkHandle() != VK_NULL_HANDLE) { | ||||
| is_pipeline_selected_for_instrumentation |= | ||||
| IsPipelineSelectedForInstrumentation(modified_pipeline_ci.pNext, linked_pipeline_state.VkHandle(), loc); | ||||
| } | ||||
|
|
||||
| for (uint32_t stage_state_i = 0; stage_state_i < static_cast<uint32_t>(modified_lib->stage_states.size()); | ||||
| ++stage_state_i) { | ||||
|
|
@@ -1457,9 +1591,9 @@ bool GpuShaderInstrumentor::PreCallRecordPipelineCreationShaderInstrumentationGP | |||
| vku::FindStructInPNextChain<VkShaderModuleCreateInfo>(modified_stage_ci->pNext))); | ||||
|
|
||||
| // TODO - this is in need of testing, when only selecting various library as well as selecting everything | ||||
| if (!force_pipeline_instrumentation && | ||||
| !IsShaderSelectedForInstrumentation(modified_shader_module_ci, modified_module_state->VkHandle(), | ||||
| loc.dot(vvl::Field::pStages, stage_state_i).dot(vvl::Field::module))) { | ||||
| if (!(is_pipeline_selected_for_instrumentation || | ||||
| IsShaderSelectedForInstrumentation(modified_shader_module_ci, modified_module_state->VkHandle(), | ||||
| loc.dot(vvl::Field::pStages, stage_state_i).dot(vvl::Field::module)))) { | ||||
| continue; | ||||
| } | ||||
|
|
||||
|
|
||||
Uh oh!
There was an error while loading. Please reload this page.