- 
                Notifications
    
You must be signed in to change notification settings  - Fork 365
 
Fix mesh shader per primitive spirv annotation #8821
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: master
Are you sure you want to change the base?
Fix mesh shader per primitive spirv annotation #8821
Conversation
104ff64    to
    adfe43d      
    Compare
  
    There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The perprimitive modifier is fine. We should make sure to include more tests.
        
          
                tests/spirv/mesh-primitive.slang
              
                Outdated
          
        
      | 
               | 
          ||
| [shader("fragment")] | ||
| FragmentOut entry_fragment(in nointerpolation Primitive prim) | ||
| FragmentOut entry_fragment(in perprimitive Primitive prim) | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have test to make sure this works on:
- Directly on entry point parameters.
 - Directly on global parameters.
 - Indirectly on nested struct fields.
 - Array types parameters.
 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I added an array type and it seems to also get the location wrong (or I misunderstand how it's supposed to work) on the fragment shader input. :')
          
 Yeah tests sound good. Along the way I also noticed that PerPrimitiveEXT is also not applied to mesh shader outputs decorated with SV_CullPrimitive. Which violates VUID-CullPrimitiveEXT-CullPrimitiveEXT-07038 So I guess a pass over all the tests here is in order.  | 
    
734c36d    to
    f062ba8      
    Compare
  
    | 
           The tests are expanded now, however I'm not sure I understand how  Secondly, in expanding the tests it seems that either I've missed something, or the location annotations are not being respected properly in my test code.  Finally,   | 
    
        
          
                source/slang/slang-emit-spirv.cpp
              
                Outdated
          
        
      | getID(varInst)); | ||
| } | ||
| 
               | 
          ||
| // HACK: Not sure how this should function? | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like we need to duplicate isIntegralScalarOrCompositeType and have a utility function named isIntegralOrLogicalScalarOrCompositeType that returns true for bool scalars and vectors. And then we make needFlatDecorationForBuiltinVar call isIntegralOrLogicalScalarOrCompositeType instead, so that isFlat will be true for the CullPrimitive builtin. That way we can get rid of this special case logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, sorry for the back and forth, I've updated the PR again (including the test), but I'm not sure I've understood you correctly here.
I run into a problem with the difference between the same builtin being used as an input or as an output. The cull flag is only used as a mesh output, so that case is straightforward. But if this is applied to other builtins, it gets weird. For example from my (updated) test case, when applied to outputs...
OpDecorate %82 BuiltIn PrimitiveTriangleIndicesEXT
OpDecorate %82 PerPrimitiveEXT
Which isn't right, and then on the input side there's the opposite problem...
in perprimitive uint in_primitive_id : SV_PrimitiveID;OpDecorate %gl_PrimitiveID_0 BuiltIn PrimitiveId
OpDecorate %gl_PrimitiveID_0 Flat
Because I'm heuristically choosing between flat and perprimitive as well. I wonder if the best course of action here is to also rely on the manual markup for builtins, and to bypass both this automatic flat annotation, and attempts to infer the perprimitive annotation?
Assuming I didn't misunderstand your suggestion.
When a fragment shader consumes input from a per-primitive mesh shader, that input also must be annotated with PerPrimitiveEXT. For mesh output, additionally validate per-primitive arrays, and CullPrimitiveEXT builtin receive PerPrimitiveEXT annotation.
2eff246    to
    3e4829f      
    Compare
  
    3e4829f    to
    c345a03      
    Compare
  
    
Currently the spirv
PerPrimitiveEXTdecoration is only being applied to mesh shader outputs. SPIRV requires this decoration to also be applied to any fragment shader inputs which consume the per-primitive output from the mesh shader.This PR is a quick approach to resolving that, by adding a new
perprimitivemodifier to slang. I'm unsure whether this is a reasonable approach, maybe it should be a spirv-specific annotation like[vk::perprimitive]instead, or the linker could check whether the associated output is already marked as per-primitive and update the pixel shader input annotation.It's also a bit weird whether it's really a 'interpolation mode' in the first place, I guess it's more about storage + disabling interpolation. So that might skew towards this being the wrong approach.
The HLSL functional spec notes that this should specific case should be be handled automatically by drivers, so the same issue shouldn't be present there. I have not investigated the situation in other backends.
This PR fixes issues with per-primitive output on the RADV driver. I'm unsure whether other drivers have different behavior in the presence of missing PerPrimitive decorations.
edit: Actually it looks like in hlsl it should be
[[vk::perprimitive]]on the pixel shader input. So copying that is probably the way to go rather than adding a new thing.