Skip to content

Commit b5f924b

Browse files
gpuav: Dont crash if trying Scoped GPU-AV with RT Pipelines
1 parent 2ea16de commit b5f924b

3 files changed

Lines changed: 243 additions & 13 deletions

File tree

layers/gpuav/instrumentation/gpuav_shader_instrumentor.cpp

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ void GpuShaderInstrumentor::SetupClassicDescriptor(const Location& loc) {
114114
result = DispatchCreatePipelineLayout(device, &debug_pipeline_layout_info, nullptr,
115115
&instrumentation_pipeline_layout_[vvl::DescriptorModeClassic]);
116116
if (result != VK_SUCCESS) {
117-
InternalError(device, loc, "vkCreateDescriptorSetLayout failed for internal pipeline layout");
117+
InternalError(device, loc, "vkCreatePipelineLayout failed for internal pipeline layout");
118118
Cleanup();
119119
return;
120120
}
@@ -169,7 +169,7 @@ void GpuShaderInstrumentor::SetupDescriptorBuffers(const Location& loc) {
169169
result = DispatchCreatePipelineLayout(device, &debug_pipeline_layout_db_info, nullptr,
170170
&instrumentation_pipeline_layout_[vvl::DescriptorModeBuffer]);
171171
if (result != VK_SUCCESS) {
172-
InternalError(device, loc, "vkCreateDescriptorSetLayout failed for internal pipeline layout for descriptor buffer");
172+
InternalError(device, loc, "vkCreatePipelineLayout failed for internal pipeline layout for descriptor buffer");
173173
Cleanup();
174174
return;
175175
}
@@ -211,12 +211,12 @@ void GpuShaderInstrumentor::FinishDeviceSetup(const VkDeviceCreateInfo* pCreateI
211211
if (!modified_features.fragmentStoresAndAtomics) {
212212
InternalError(
213213
device, loc,
214-
"GPU Shader Instrumentation requires fragmentStoresAndAtomics to allow witting out data inside the fragment shader.");
214+
"GPU Shader Instrumentation requires fragmentStoresAndAtomics to allow writing out data inside the fragment shader.");
215215
return;
216216
}
217217
if (!modified_features.vertexPipelineStoresAndAtomics) {
218218
InternalError(device, loc,
219-
"GPU Shader Instrumentation requires vertexPipelineStoresAndAtomics to allow witting out data inside the "
219+
"GPU Shader Instrumentation requires vertexPipelineStoresAndAtomics to allow writing out data inside the "
220220
"vertex shader.");
221221
return;
222222
}
@@ -227,7 +227,7 @@ void GpuShaderInstrumentor::FinishDeviceSetup(const VkDeviceCreateInfo* pCreateI
227227
return;
228228
}
229229
if (!modified_features.bufferDeviceAddress) {
230-
InternalError(device, loc, "GPU Shader Instrumentation requires bufferDeviceAddress to manage witting out of the shader.");
230+
InternalError(device, loc, "GPU Shader Instrumentation requires bufferDeviceAddress to manage writing out of the shader.");
231231
return;
232232
}
233233
if (!modified_features.scalarBlockLayout) {
@@ -377,9 +377,9 @@ void GpuShaderInstrumentor::PreCallRecordCreatePipelineLayout(VkDevice device, c
377377
if (chassis_state.modified_create_info.setLayoutCount > instrumentation_desc_set_bind_index_) {
378378
std::ostringstream strm;
379379
strm << "pCreateInfo::setLayoutCount (" << chassis_state.modified_create_info.setLayoutCount
380-
<< ") will conflicts with validation's descriptor set at slot " << instrumentation_desc_set_bind_index_ << ". "
380+
<< ") will conflict with validation's descriptor set at slot " << instrumentation_desc_set_bind_index_ << ". "
381381
<< "This Pipeline Layout has too many descriptor sets that will not allow GPU shader instrumentation to be setup "
382-
"for pipelines created with it, therefore no validation error will be repored for them by GPU-AV at runtime.";
382+
"for pipelines created with it, therefore no validation error will be reported for them by GPU-AV at runtime.";
383383
InternalWarning(device, record_obj.location, strm.str().c_str());
384384
} else {
385385
vvl::DescriptorMode mode = SelectDescriptorModeFromDSL(pCreateInfo->setLayoutCount, pCreateInfo->pSetLayouts);
@@ -452,11 +452,17 @@ void GpuShaderInstrumentor::PreCallRecordSetDebugUtilsObjectNameEXT(VkDevice dev
452452
}
453453
}
454454

455-
VkPipeline instrumented_pipeline = VK_NULL_HANDLE;
456455
// Can't instrument ray tracing pipeline post creation,
457456
// As corresponding shader binding tables may have already been created.
458-
if (pipeline_state->linking_shaders == 0 &&
459-
IsValueIn(pipeline_state->pipeline_type, {VK_PIPELINE_BIND_POINT_GRAPHICS, VK_PIPELINE_BIND_POINT_COMPUTE})) {
457+
if (!IsValueIn(pipeline_state->pipeline_type, {VK_PIPELINE_BIND_POINT_GRAPHICS, VK_PIPELINE_BIND_POINT_COMPUTE})) {
458+
InternalWarning(device, record_obj.location,
459+
"Only graphics and compute pipelines can be instrumented after they are created, this pipeline will "
460+
"not be instrumented. Set the name before creating the pipeline to have it selected.");
461+
return;
462+
}
463+
464+
VkPipeline instrumented_pipeline = VK_NULL_HANDLE;
465+
if (pipeline_state->linking_shaders == 0) {
460466
std::vector<chassis::ShaderInstrumentationMetadata> shader_instrumentation_metadata;
461467
if (pipeline_state->pipeline_type == VK_PIPELINE_BIND_POINT_GRAPHICS) {
462468
vku::safe_VkGraphicsPipelineCreateInfo new_pipeline_ci(pipeline_state->GraphicsCreateInfo());
@@ -703,9 +709,9 @@ void GpuShaderInstrumentor::PreCallRecordCreateShadersEXT(VkDevice device, uint3
703709
if (new_create_info.setLayoutCount > instrumentation_desc_set_bind_index_) {
704710
std::ostringstream strm;
705711
strm << "pCreateInfos[" << i << "]::setLayoutCount (" << new_create_info.setLayoutCount
706-
<< ") will conflicts with validation's descriptor set at slot " << instrumentation_desc_set_bind_index_ << ". "
712+
<< ") will conflict with validation's descriptor set at slot " << instrumentation_desc_set_bind_index_ << ". "
707713
<< "This Shader Object has too many descriptor sets that will not allow GPU shader instrumentation to be setup "
708-
"for VkShaderEXT created with it, therefore no validation error will be repored for them by GPU-AV at "
714+
"for VkShaderEXT created with it, therefore no validation error will be reported for them by GPU-AV at "
709715
"runtime.";
710716
InternalWarning(device, record_obj.location, strm.str().c_str());
711717
}

tests/unit/gpu_av_ray_tracing.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4400,3 +4400,45 @@ TEST_F(NegativeGpuAVRayTracing, OpReportIntersectionKHRHitKindOutOfRange) {
44004400
ASSERT_GT(debug_buffer_ptr[0], 0u) << "Intersection shader was never invoked";
44014401
debug_buffer.Memory().Unmap();
44024402
}
4403+
4404+
TEST_F(NegativeGpuAVRayTracing, SelectInstrumentedPipelineRegex) {
4405+
TEST_DESCRIPTION("Currently not possible, but need to ensure we do not crash");
4406+
SetTargetApiVersion(VK_API_VERSION_1_2);
4407+
AddRequiredExtensions(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
4408+
AddRequiredExtensions(VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME);
4409+
AddRequiredFeature(vkt::Feature::rayTracingPipeline);
4410+
AddRequiredFeature(vkt::Feature::accelerationStructure);
4411+
AddRequiredFeature(vkt::Feature::bufferDeviceAddress);
4412+
4413+
std::vector<VkLayerSettingEXT> layer_settings(2);
4414+
layer_settings[0] = {OBJECT_LAYER_NAME, "gpuav_select_instrumented_shaders", VK_LAYER_SETTING_TYPE_BOOL32_EXT, 1, &kVkTrue};
4415+
std::array<const char*, 1> shader_regexes = {{"ray_tracing_pipeline_foo"}};
4416+
layer_settings[1] = {OBJECT_LAYER_NAME, "gpuav_shaders_to_instrument", VK_LAYER_SETTING_TYPE_STRING_EXT, size32(shader_regexes),
4417+
shader_regexes.data()};
4418+
4419+
VkLayerSettingsCreateInfoEXT layer_setting_ci = vku::InitStructHelper();
4420+
layer_setting_ci.settingCount = size32(layer_settings);
4421+
layer_setting_ci.pSettings = layer_settings.data();
4422+
4423+
VkValidationFeaturesEXT validation_features = GetGpuAvValidationFeatures();
4424+
validation_features.pNext = &layer_setting_ci;
4425+
RETURN_IF_SKIP(InitFrameworkForRayTracingTest(&validation_features));
4426+
if (!CanEnableGpuAV(*this)) {
4427+
GTEST_SKIP() << "Requirements for GPU-AV are not met";
4428+
}
4429+
RETURN_IF_SKIP(InitState());
4430+
4431+
vkt::rt::Pipeline pipeline(*this, m_device);
4432+
pipeline.SetGlslRayGenShader(kRayTracingMinimalGlsl);
4433+
pipeline.AddBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 0);
4434+
pipeline.CreateDescriptorSet();
4435+
pipeline.Build();
4436+
4437+
VkDebugUtilsObjectNameInfoEXT name_info = vku::InitStructHelper();
4438+
name_info.objectType = VK_OBJECT_TYPE_PIPELINE;
4439+
name_info.pObjectName = "ray_tracing_pipeline_foo";
4440+
name_info.objectHandle = uint64_t(pipeline.Handle().handle());
4441+
m_errorMonitor->SetDesiredWarning("Only graphics and compute pipelines can be instrumented after they are created");
4442+
vk::SetDebugUtilsObjectNameEXT(device(), &name_info);
4443+
m_errorMonitor->VerifyFound();
4444+
}

tests/unit/gpu_av_shader_debug_info.cpp

Lines changed: 183 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2822,4 +2822,186 @@ TEST_F(NegativeGpuAVShaderDebugInfo, HeapMultipleDraws) {
28222822
m_errorMonitor->SetDesiredError("Bad-Draw");
28232823
m_default_queue->SubmitAndWait(m_command_buffer);
28242824
m_errorMonitor->VerifyFound();
2825-
}
2825+
}
2826+
2827+
TEST_F(NegativeGpuAVShaderDebugInfo, GraphicsPipelineLibraryReusedLibrary) {
2828+
TEST_DESCRIPTION("Make sure the source is found when a library already instrumented by a previous link is re-linked");
2829+
AddRequiredExtensions(VK_EXT_GRAPHICS_PIPELINE_LIBRARY_EXTENSION_NAME);
2830+
AddRequiredFeature(vkt::Feature::graphicsPipelineLibrary);
2831+
RETURN_IF_SKIP(InitGpuVUBufferDeviceAddress());
2832+
InitRenderTarget();
2833+
2834+
const char* vs_source = R"glsl(
2835+
#version 450
2836+
#extension GL_EXT_buffer_reference : enable
2837+
layout(buffer_reference, std430) readonly buffer IndexBuffer {
2838+
int indices[];
2839+
};
2840+
layout(set = 0, binding = 0) readonly buffer foo {
2841+
IndexBuffer data;
2842+
int x;
2843+
};
2844+
vec2 vertices[3];
2845+
void main() {
2846+
vertices[0] = vec2(-1.0, -1.0);
2847+
vertices[1] = vec2(1.0, -1.0);
2848+
vertices[2] = vec2(0.0, 1.0);
2849+
gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0, 1.0);
2850+
if (data.indices[0] == 42) {
2851+
gl_Position = vec4(0.0);
2852+
}
2853+
}
2854+
)glsl";
2855+
2856+
const char* fs_source = R"(
2857+
OpCapability Shader
2858+
OpCapability PhysicalStorageBufferAddresses
2859+
%2 = OpExtInstImport "GLSL.std.450"
2860+
OpMemoryModel PhysicalStorageBuffer64 GLSL450
2861+
OpEntryPoint Fragment %main "main" %uFragColor %_
2862+
OpExecutionMode %main OriginUpperLeft
2863+
%1 = OpString "bad.frag"
2864+
OpSource GLSL 450 %1 "#version 450
2865+
#extension GL_EXT_buffer_reference : enable
2866+
layout(buffer_reference, std430) readonly buffer IndexBuffer {
2867+
int indices[];
2868+
};
2869+
layout(set = 0, binding = 0) readonly buffer foo {
2870+
IndexBuffer data;
2871+
int x;
2872+
};
2873+
layout(location = 0) out vec4 uFragColor;
2874+
void main() {
2875+
uFragColor = vec4(float(data.indices[16]));
2876+
}
2877+
"
2878+
OpSourceExtension "GL_EXT_buffer_reference"
2879+
OpName %main "main"
2880+
OpName %uFragColor "uFragColor"
2881+
OpName %foo "foo"
2882+
OpMemberName %foo 0 "data"
2883+
OpMemberName %foo 1 "x"
2884+
OpName %IndexBuffer "IndexBuffer"
2885+
OpMemberName %IndexBuffer 0 "indices"
2886+
OpName %_ ""
2887+
OpDecorate %uFragColor Location 0
2888+
OpDecorate %foo Block
2889+
OpMemberDecorate %foo 0 NonWritable
2890+
OpMemberDecorate %foo 0 Offset 0
2891+
OpMemberDecorate %foo 1 NonWritable
2892+
OpMemberDecorate %foo 1 Offset 8
2893+
OpDecorate %_runtimearr_int ArrayStride 4
2894+
OpDecorate %IndexBuffer Block
2895+
OpMemberDecorate %IndexBuffer 0 NonWritable
2896+
OpMemberDecorate %IndexBuffer 0 Offset 0
2897+
OpDecorate %_ NonWritable
2898+
OpDecorate %_ Binding 0
2899+
OpDecorate %_ DescriptorSet 0
2900+
%void = OpTypeVoid
2901+
%4 = OpTypeFunction %void
2902+
%float = OpTypeFloat 32
2903+
%v4float = OpTypeVector %float 4
2904+
%_ptr_Output_v4float = OpTypePointer Output %v4float
2905+
%uFragColor = OpVariable %_ptr_Output_v4float Output
2906+
OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_IndexBuffer PhysicalStorageBuffer
2907+
%int = OpTypeInt 32 1
2908+
%foo = OpTypeStruct %_ptr_PhysicalStorageBuffer_IndexBuffer %int
2909+
%_runtimearr_int = OpTypeRuntimeArray %int
2910+
%IndexBuffer = OpTypeStruct %_runtimearr_int
2911+
%_ptr_PhysicalStorageBuffer_IndexBuffer = OpTypePointer PhysicalStorageBuffer %IndexBuffer
2912+
%_ptr_StorageBuffer_foo = OpTypePointer StorageBuffer %foo
2913+
%_ = OpVariable %_ptr_StorageBuffer_foo StorageBuffer
2914+
%int_0 = OpConstant %int 0
2915+
%_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_IndexBuffer = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_IndexBuffer
2916+
%int_16 = OpConstant %int 16
2917+
%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int
2918+
OpLine %1 11 11
2919+
%main = OpFunction %void None %4
2920+
%6 = OpLabel
2921+
OpLine %1 12 0
2922+
%20 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_IndexBuffer %_ %int_0
2923+
%21 = OpLoad %_ptr_PhysicalStorageBuffer_IndexBuffer %20
2924+
%24 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %21 %int_0 %int_16
2925+
%25 = OpLoad %int %24 Aligned 4
2926+
%26 = OpConvertSToF %float %25
2927+
%27 = OpCompositeConstruct %v4float %26 %26 %26 %26
2928+
OpStore %uFragColor %27
2929+
OpLine %1 13 0
2930+
OpReturn
2931+
OpFunctionEnd
2932+
)";
2933+
2934+
VkShaderObj vs(*m_device, vs_source, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_2);
2935+
VkShaderObj good_fs(*m_device, kFragmentMinimalGlsl, VK_SHADER_STAGE_FRAGMENT_BIT);
2936+
VkShaderObj bad_fs(*m_device, fs_source, VK_SHADER_STAGE_FRAGMENT_BIT, SPV_ENV_VULKAN_1_2, SPV_SOURCE_ASM);
2937+
2938+
OneOffDescriptorSet descriptor_set(m_device, {{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_ALL, nullptr}});
2939+
const vkt::PipelineLayout pipeline_layout(*m_device, {&descriptor_set.layout_});
2940+
2941+
vkt::Buffer block_buffer(*m_device, 16, 0, vkt::device_address);
2942+
vkt::Buffer in_buffer(*m_device, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, kHostVisibleMemProps);
2943+
auto data = static_cast<VkDeviceAddress*>(in_buffer.Memory().Map());
2944+
data[0] = block_buffer.Address();
2945+
descriptor_set.WriteDescriptorBufferInfo(0, in_buffer, 0, VK_WHOLE_SIZE, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
2946+
descriptor_set.UpdateDescriptorSets();
2947+
2948+
CreatePipelineHelper vertex_input_lib(*this);
2949+
vertex_input_lib.InitVertexInputLibInfo();
2950+
vertex_input_lib.CreateGraphicsPipeline(false);
2951+
2952+
VkViewport viewport = {0, 0, 1, 1, 0, 1};
2953+
VkRect2D scissor = {{0, 0}, {1, 1}};
2954+
2955+
CreatePipelineHelper pre_raster_lib(*this);
2956+
pre_raster_lib.InitPreRasterLibInfo(&vs.GetStageCreateInfo());
2957+
pre_raster_lib.vp_state_ci_.pViewports = &viewport;
2958+
pre_raster_lib.vp_state_ci_.pScissors = &scissor;
2959+
pre_raster_lib.gp_ci_.layout = pipeline_layout;
2960+
pre_raster_lib.CreateGraphicsPipeline();
2961+
2962+
CreatePipelineHelper good_frag_shader_lib(*this);
2963+
good_frag_shader_lib.InitFragmentLibInfo(&good_fs.GetStageCreateInfo());
2964+
good_frag_shader_lib.gp_ci_.layout = pipeline_layout;
2965+
good_frag_shader_lib.CreateGraphicsPipeline(false);
2966+
2967+
CreatePipelineHelper bad_frag_shader_lib(*this);
2968+
bad_frag_shader_lib.InitFragmentLibInfo(&bad_fs.GetStageCreateInfo());
2969+
bad_frag_shader_lib.gp_ci_.layout = pipeline_layout;
2970+
bad_frag_shader_lib.CreateGraphicsPipeline(false);
2971+
2972+
CreatePipelineHelper frag_out_lib(*this);
2973+
frag_out_lib.InitFragmentOutputLibInfo();
2974+
frag_out_lib.CreateGraphicsPipeline(false);
2975+
2976+
VkPipeline good_libraries[4] = {vertex_input_lib, pre_raster_lib, good_frag_shader_lib, frag_out_lib};
2977+
VkPipelineLibraryCreateInfoKHR good_link_info = vku::InitStructHelper();
2978+
good_link_info.libraryCount = size32(good_libraries);
2979+
good_link_info.pLibraries = good_libraries;
2980+
2981+
VkGraphicsPipelineCreateInfo good_exe_pipe_ci = vku::InitStructHelper(&good_link_info);
2982+
good_exe_pipe_ci.layout = pipeline_layout;
2983+
vkt::Pipeline good_exe_pipe(*m_device, good_exe_pipe_ci);
2984+
2985+
VkPipeline bad_libraries[4] = {vertex_input_lib, pre_raster_lib, bad_frag_shader_lib, frag_out_lib};
2986+
VkPipelineLibraryCreateInfoKHR bad_link_info = vku::InitStructHelper();
2987+
bad_link_info.libraryCount = size32(bad_libraries);
2988+
bad_link_info.pLibraries = bad_libraries;
2989+
2990+
VkGraphicsPipelineCreateInfo bad_exe_pipe_ci = vku::InitStructHelper(&bad_link_info);
2991+
bad_exe_pipe_ci.layout = pipeline_layout;
2992+
vkt::Pipeline bad_exe_pipe(*m_device, bad_exe_pipe_ci);
2993+
2994+
m_command_buffer.Begin();
2995+
m_command_buffer.BeginRenderPass(m_renderPassBeginInfo);
2996+
vk::CmdBindPipeline(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bad_exe_pipe);
2997+
vk::CmdBindDescriptorSets(m_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set.set_, 0,
2998+
nullptr);
2999+
vk::CmdDraw(m_command_buffer, 3, 1, 0, 0);
3000+
m_command_buffer.EndRenderPass();
3001+
m_command_buffer.End();
3002+
3003+
// VUID-RuntimeSpirv-PhysicalStorageBuffer64-11819
3004+
m_errorMonitor->SetDesiredError("Shader validation error occurred at bad.frag:12");
3005+
m_default_queue->SubmitAndWait(m_command_buffer);
3006+
m_errorMonitor->VerifyFound();
3007+
}

0 commit comments

Comments
 (0)