KhronosGroup / KhronosGroup/Vulkan-ValidationLayers
SPIR-V validation generates a wrong warning when outputting in fragment shader via a struct
- Dominant language
- C++
- Stars
- 1k
- Forks
- 504
- Avg merge
- 11h 35m
- Merged PRs (30d)
- 224
Description
**Environment:**
- OS: Arch Linux x86_64
- GPU and driver version: AMD RX 9070 XT
- SDK or header version if building from repo:
- Options enabled (synchronization, best practices, etc.):
**Describe the Issue**
When using a SPIR-V shader generated by a tool I'm working on, I get a validation warning that I believe is incorrect.
I believe writing to a member of a struct of storage class Output, with a decoration
of a valid location, is valid SPIR-V as per the Location and Output decoration [spec](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Decoration).
**Expected behavior**
The layer should be able to tell that an OpStore through an OpAccessChain stores the value in an output interface correctly
**Valid Usage ID**
```
Validation Warning: [ Undefined-Value-ShaderFragmentOutputMismatch ] | MessageID = 0xe5642923
vkCreateGraphicsPipelines(): pCreateInfos[0] Inside [EntryPoint "fragment", VK_SHADER_STAGE_FRAGMENT_BIT], it writes to [Output variable "FsOut" is a struct with 1 members] with a numeric type of (none) but VkSubpassDescription::pColorAttachments[0] pointing at VkRenderPassCreateInfo::pAttachment
s[0] is created with VK_FORMAT_B8G8R8A8_UNORM (numeric type of FLOAT) which does not match and the resulting values written will be undefined.
Spec information at https://docs.vulkan.org/spec/latest/chapters/interfaces.html#interfaces-fragmentoutput
Objects: 1
[0] VkShaderModule 0x310000000031
```
**Additional context**
SPIR-V that causes the error
```
; SPIR-V
; Version: 1.0
; Generator: Khronos; 0
; Bound: 47
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Vertex %5 "vertex" %7 %8 %gl_Position
OpEntryPoint Fragment %6 "fragment" %9 %10
OpExecutionMode %6 OriginUpperLeft
OpSource Unknown 0
OpMemberName %VsIn 0 "position"
OpMemberName %VsIn 1 "color"
OpName %VsIn "VsIn"
OpMemberName %FsOut 0 "color"
OpName %FsOut "FsOut"
OpMemberName %ShaderLink 0 "color"
OpName %ShaderLink "ShaderLink"
OpMemberDecorate %VsIn 0 Offset 0
OpMemberDecorate %VsIn 1 Offset 16
OpDecorate %VsIn Block
OpMemberDecorate %VsIn 0 Location 0
OpMemberDecorate %VsIn 1 Location 1
OpMemberDecorate %FsOut 0 Offset 0
OpDecorate %FsOut Block
OpMemberDecorate %FsOut 0 Location 0
OpMemberDecorate %ShaderLink 0 Offset 0
OpDecorate %ShaderLink Block
OpMemberDecorate %ShaderLink 0 Location 0
OpDecorate %gl_Position BuiltIn Position
%void = OpTypeVoid
%bool = OpTypeBool
%int = OpTypeInt 32 1
%uint = OpTypeInt 32 0
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%gl_Position = OpVariable %_ptr_Output_v4float Output
%int_0 = OpConstant %int 0
%int_1 = OpConstant %int 1
%_ptr_Function_v4float = OpTypePointer Function %v4float
%_ptr_Input_v4float = OpTypePointer Input %v4float
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
%VsIn = OpTypeStruct %v4float %v4float
%_ptr_Function_VsIn = OpTypePointer Function %VsIn
%_ptr_Input_VsIn = OpTypePointer Input %VsIn
%_ptr_Output_VsIn = OpTypePointer Output %VsIn
%_ptr_Uniform_VsIn = OpTypePointer Uniform %VsIn
%FsOut = OpTypeStruct %v4float
%_ptr_Function_FsOut = OpTypePointer Function %FsOut
%_ptr_Input_FsOut = OpTypePointer Input %FsOut
%_ptr_Output_FsOut = OpTypePointer Output %FsOut
%_ptr_Uniform_FsOut = OpTypePointer Uniform %FsOut
%ShaderLink = OpTypeStruct %v4float
%_ptr_Function_ShaderLink = OpTypePointer Function %ShaderLink
%_ptr_Input_ShaderLink = OpTypePointer Input %ShaderLink
%_ptr_Output_ShaderLink = OpTypePointer Output %ShaderLink
%_ptr_Uniform_ShaderLink = OpTypePointer Uniform %ShaderLink
%50 = OpTypeFunction %void
%7 = OpVariable %_ptr_Input_VsIn Input
%8 = OpVariable %_ptr_Output_ShaderLink Output
%9 = OpVariable %_ptr_Input_ShaderLink Input
%10 = OpVariable %_ptr_Output_FsOut Output
%5 = OpFunction %void None %50
%51 = OpLabel
%52 = OpAccessChain %_ptr_Output_v4float %8 %int_0
%54 = OpAccessChain %_ptr_Input_v4float %7 %int_1
%56 = OpLoad %v4float %54
OpStore %52 %56
%57 = OpAccessChain %_ptr_Input_v4float %7 %int_0
%58 = OpLoad %v4float %57
OpStore %gl_Position %58
OpReturn
OpFunctionEnd
%6 = OpFunction %void None %50
%59 = OpLabel
%60 = OpAccessChain %_ptr_Output_v4float %10 %int_0
%61 = OpAccessChain %_ptr_Input_v4float %9 %int_0
%62 = OpLoad %v4float %61
OpStore %60 %62
OpReturn
OpFunctionEnd
```
Contributor guide
Assessment
This issue has not been assessed yet.