KhronosGroup / Vulkan-ValidationLayers

Vulkan Validation Layers (VVL)
https://vulkan.lunarg.com/doc/sdk/latest/linux/khronos_validation_layer.html
Other
738 stars 398 forks source link

GPU-Assisted seem to be checking the wrong descriptor set when binding sets before pipeline #7737

Closed AlexRouSg closed 4 months ago

AlexRouSg commented 5 months ago

Environment:

Describe the Issue

The following code triggers VUID-vkCmdDraw-viewType-07752.

vkCmdBindDescriptorSets();
vkCmdBindPipeline();
vkCmdDraw() ;// draw that uses 2D textures

vkCmdBindDescriptorSets();
vkCmdBindPipeline();
vkCmdDraw(); // draw that uses 3D textures

However swapping the order of vkCmdBindDescriptorSets and vkCmdBindPipeline does not.

vkCmdBindPipeline();
vkCmdBindDescriptorSets();
vkCmdDraw() ;// draw that uses 2D textures

vkCmdBindPipeline();
vkCmdBindDescriptorSets();
vkCmdDraw(); // draw that uses 3D textures

Removing the first draw call and related binding cmds that only uses 2D textures also does not trigger this VUID.

Expected behavior This VUID should not trigger as I have verified the SPIRV manually that the second draw call does not contain a OpTypeImage 2D nor does renderdoc detect a 3D texture being bound to the first draw call.

Valid Usage ID VUID-vkCmdDraw-viewType-07752

ImageView type is VK_IMAGE_VIEW_TYPE_3D but the OpTypeImage has ( Dim = 2D )

Additional Info: Might be relevant but I am also using dynamic rendering + graphics pipeline library

spencer-lunarg commented 5 months ago

@AlexRouSg we do shader instrumentation to detect if the texture is accessed or not. Can you provide the SPIR-V as it will be helpful to see if the bug is how we are instrumenting it

AlexRouSg commented 5 months ago

@spencer-lunarg I have tested with a very minimal frag shader and here it is, this is the first draw call with 2D textures, the second one is the same but sub 2D with 3D

frag ``` ; SPIR-V ; Version: 1.6 ; Generator: Google Shaderc over Glslang; 11 ; Bound: 34 ; Schema: 0 OpCapability Shader %2 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %main "main" %outColor %t %inUV %_ OpExecutionMode %main OriginUpperLeft %1 = OpString "water.frag" OpSource GLSL 450 %1 "#version 450 #pragma shader_stage(fragment) #extension GL_EXT_scalar_block_layout : enable layout(constant_id = 0) const float foo = 1; layout(location = 0) in vec2 inUV; layout(location = 0) out vec4 outColor; layout(set = 0, binding = 0, scalar) uniform restrict Camera { layout(row_major) mat4 pv; layout(row_major) mat4 invPV; }; layout(set = 1, binding = 0) uniform sampler2D t; void main() { outColor = texture(t, vec2(inUV.s, inUV.t)); } " OpSourceExtension "GL_EXT_scalar_block_layout" OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" OpSourceExtension "GL_GOOGLE_include_directive" OpName %main "main" OpName %outColor "outColor" OpName %t "t" OpName %inUV "inUV" OpName %foo "foo" OpName %Camera "Camera" OpMemberName %Camera 0 "pv" OpMemberName %Camera 1 "invPV" OpName %_ "" OpModuleProcessed "entry-point main" OpModuleProcessed "client vulkan100" OpModuleProcessed "target-env spirv1.6" OpModuleProcessed "target-env vulkan1.3" OpModuleProcessed "entry-point main" OpDecorate %outColor Location 0 OpDecorate %t DescriptorSet 1 OpDecorate %t Binding 0 OpDecorate %inUV Location 0 OpDecorate %foo SpecId 0 OpMemberDecorate %Camera 0 RowMajor OpMemberDecorate %Camera 0 Offset 0 OpMemberDecorate %Camera 0 MatrixStride 16 OpMemberDecorate %Camera 1 RowMajor OpMemberDecorate %Camera 1 Offset 64 OpMemberDecorate %Camera 1 MatrixStride 16 OpDecorate %Camera Block OpDecorate %_ DescriptorSet 0 OpDecorate %_ Binding 0 %void = OpTypeVoid %4 = OpTypeFunction %void %float = OpTypeFloat 32 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float %outColor = OpVariable %_ptr_Output_v4float Output %11 = OpTypeImage %float 2D 0 0 0 1 Unknown %12 = OpTypeSampledImage %11 %_ptr_UniformConstant_12 = OpTypePointer UniformConstant %12 %t = OpVariable %_ptr_UniformConstant_12 UniformConstant %v2float = OpTypeVector %float 2 %_ptr_Input_v2float = OpTypePointer Input %v2float %inUV = OpVariable %_ptr_Input_v2float Input %uint = OpTypeInt 32 0 %uint_0 = OpConstant %uint 0 %_ptr_Input_float = OpTypePointer Input %float %uint_1 = OpConstant %uint 1 %foo = OpSpecConstant %float 1 %mat4v4float = OpTypeMatrix %v4float 4 %Camera = OpTypeStruct %mat4v4float %mat4v4float %_ptr_Uniform_Camera = OpTypePointer Uniform %Camera %_ = OpVariable %_ptr_Uniform_Camera Uniform OpLine %1 18 11 %main = OpFunction %void None %4 %6 = OpLabel OpLine %1 19 0 %15 = OpLoad %12 %t %22 = OpAccessChain %_ptr_Input_float %inUV %uint_0 %23 = OpLoad %float %22 %25 = OpAccessChain %_ptr_Input_float %inUV %uint_1 %26 = OpLoad %float %25 %27 = OpCompositeConstruct %v2float %23 %26 %28 = OpImageSampleImplicitLod %v4float %15 %27 OpStore %outColor %28 OpReturn OpFunctionEnd ```

vert shader is nothing interesting, just a fullscreen triangle

vert ``` ; SPIR-V ; Version: 1.6 ; Generator: Google Shaderc over Glslang; 11 ; Bound: 42 ; Schema: 0 OpCapability Shader %2 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Vertex %main "main" %outUV %gl_VertexIndex %_ %1 = OpString "fullscreen.vert" OpSource GLSL 450 %1 "#version 450 #pragma shader_stage(vertex) layout(location = 0) out vec2 outUV; out gl_PerVertex { vec4 gl_Position; }; void main() { outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); gl_Position = vec4(outUV * 2.0f + -1.0f, 0.0f, 1.0f); } " OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" OpSourceExtension "GL_GOOGLE_include_directive" OpName %main "main" OpName %outUV "outUV" OpName %gl_VertexIndex "gl_VertexIndex" OpName %gl_PerVertex "gl_PerVertex" OpMemberName %gl_PerVertex 0 "gl_Position" OpName %_ "" OpModuleProcessed "entry-point main" OpModuleProcessed "client vulkan100" OpModuleProcessed "target-env spirv1.6" OpModuleProcessed "target-env vulkan1.3" OpModuleProcessed "entry-point main" OpDecorate %outUV Location 0 OpDecorate %gl_VertexIndex BuiltIn VertexIndex OpMemberDecorate %gl_PerVertex 0 BuiltIn Position OpDecorate %gl_PerVertex Block %void = OpTypeVoid %4 = OpTypeFunction %void %float = OpTypeFloat 32 %v2float = OpTypeVector %float 2 %_ptr_Output_v2float = OpTypePointer Output %v2float %outUV = OpVariable %_ptr_Output_v2float Output %int = OpTypeInt 32 1 %_ptr_Input_int = OpTypePointer Input %int %gl_VertexIndex = OpVariable %_ptr_Input_int Input %int_1 = OpConstant %int 1 %int_2 = OpConstant %int 2 %v4float = OpTypeVector %float 4 %gl_PerVertex = OpTypeStruct %v4float %_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex %_ = OpVariable %_ptr_Output_gl_PerVertex Output %int_0 = OpConstant %int 0 %float_2 = OpConstant %float 2 %float_n1 = OpConstant %float -1 %float_0 = OpConstant %float 0 %float_1 = OpConstant %float 1 %_ptr_Output_v4float = OpTypePointer Output %v4float OpLine %1 10 11 %main = OpFunction %void None %4 %6 = OpLabel OpLine %1 11 0 %14 = OpLoad %int %gl_VertexIndex %16 = OpShiftLeftLogical %int %14 %int_1 %18 = OpBitwiseAnd %int %16 %int_2 %19 = OpConvertSToF %float %18 %20 = OpLoad %int %gl_VertexIndex %21 = OpBitwiseAnd %int %20 %int_2 %22 = OpConvertSToF %float %21 %23 = OpCompositeConstruct %v2float %19 %22 OpStore %outUV %23 OpLine %1 13 0 %29 = OpLoad %v2float %outUV %31 = OpVectorTimesScalar %v2float %29 %float_2 %33 = OpCompositeConstruct %v2float %float_n1 %float_n1 %34 = OpFAdd %v2float %31 %33 %37 = OpCompositeExtract %float %34 0 %38 = OpCompositeExtract %float %34 1 %39 = OpCompositeConstruct %v4float %37 %38 %float_0 %float_1 %41 = OpAccessChain %_ptr_Output_v4float %_ %int_0 OpStore %41 %39 OpReturn OpFunctionEnd ```
spencer-lunarg commented 5 months ago

this is perfect! Thanks @AlexRouSg

We have a big PR refactoring a lot in GPU-AV but will take a look into this after that lands

spencer-lunarg commented 4 months ago

update - have test to reproduce, this is only for GPU-AV and works fine with normal core checks

narrowed it down to

vkCmdBindPipeline(); // 2D
vkCmdBindDescriptorSets();
vkCmdBindPipeline(); // 3D
vkCmdDraw(); // draw that uses 3D textures

causes the error, about to dive into it more, but wanted to log progress