Skip to content

[0031] Semantics - Move processing to Sema at entry function decl #341

@tex3d

Description

@tex3d

In the Semantics proposal, under Sema:
https://github.com/llvm/wg-hlsl/blob/main/proposals/0031-semantics.md#sema

Sema check is only stateless, and done during parsing. The parser first emits an HLSLUnparsedSemantic attribute, which is passed down to Sema.

  • convert this class into a valid semantic class like HLSLUserSemantic or HLSLSV_*.
  • check shader stage compatibility with the system semantic.
  • check type compability with the system semantic.

At this stage, we have either HLSLUserSemanticAttr attributes, or known compatible HLSLSV_*Attr attributes. All non-converted HLSLUnparsedSemantic would have raised a diagnostic to say unknown HLSL system semantic X.

No further checking is done as we must wait for codegen to move forward.

These are some of my thoughts.

No semantic differentiation or diagnostics until entry-level processing

During parsing, we do not necessarily know the usage of the decl with the semantic attribute. There is almost nothing we can assume about the semantic during attribute parsing. At this stage, without usage context, the semantic is merely an identifier. In my opinion all that should be captured into the AST semantic attribute in this location is this unparsed/uninterpreted/unmodified identifier.

Determining whether a semantic represents a specific system value, and performing any index or type checking, when you haven't determined the exact usage context, is an HLSL language change.

We could propose a change to the HLSL language that restricts the basic spellings allowed at the semantic parsing level even if it's not used for anything, but I'm not sure how much this buys us. It creates a potential compatibility issue, so that we may diagnose a tiny subset of potentially malformed-looking system value semantic assignments that are unused and ignored.

At the time when we have a full entry decl in Sema, we can then do all the checking we need to verify correct usage for shader signatures.

Perform signature diagnostics and construction in Sema, not CodeGen

Full diagnostics need to be performed in Sema rather than CodeGen, otherwise tools like clangd will lack these diagnostics.

This will involve recursive type traversal and signature element shape construction, application of semantic overrides, semantic index expansions based on type layouts, system value interpretations based on context, special object handling (like streams/patches), diagnosing of system value indexing/type/shape constraints, and so on.

I would propose that the full shader signatures should be diagnosed and constructed in Sema when checking each entry function decl. This would include some target-specific (DirectX vs. Vulkan) interpretations and checks, like signature packing and corresponding diagnostics for DirectX, for example. I anticipate some minor complications for the patch constant function handling for Hull Shaders.

Capture signature elements to entry function decl attribute(s)

I also think the details of the signatures should be captured into to the AST somehow for codegen to follow, so the logic is not duplicated. This capturing cannot (generally) be at the same location as the semantic attribute, since the semantic attribute may be on a struct field (type), and a signature element expresses the interpretation on a particular parameter of the instance of that field.

There are multiple options for capturing this information, perhaps the simplest being an attribute on the entry function that contains the full expansion of signature elements and their mapping to parameters and return type elements.

Use information captured in AST to drive CodeGen

I think the signature information captured in the AST should be sufficient for CodeGen without needing special-case code for handling each specific system value semantic. This would mean the different ways CodeGen would read/write argument/return value contents would be enumerated and encoded into the AST element.

Structured description of shader signature and semantic constraints

I would also prefer to define all the properties and constraints used for different semantic types relative to shader context in easily comprehensible tables, extending the way it's defined in DXC for DXIL to include additional type constraints, as well as account for Vulkan/SPIR-V targets. I prefer this to a bunch of special-case code spread about in different locations, since it's already defined in this structured way for DXC. This may map to a TableGen approach, or a def file approach may be sufficient.

Additional metadata capture for signatures

At CodeGen, there will be information in the signature elements that needs to be captured somewhere to preserve it for shader signature metadata. We need to design the intermediate metadata used for capturing signature information, at least for DirectX. There may also be information desirable to capture for SPIR-V, like semantic names to determine names to use in SPIR-V.

Additional Complications

  • in and out are not the only possibilities for entry parameters, you could also have inout, which is both an in and an out parameter folded into one.
  • Some shader stages have special object types that define inputs or outputs using a template argument. Some of these have indexing on the object or special operations to write to elements (Stream.Append).
  • Some shader stages use arrays to represent a separate vertex array dimension, not a packed indexable interpolant, such as GS input vertex array (ex. in triangleadj MyVertex array[6]).
  • We'll need to optimize entry functions such that signature loads/stores are fully sunk into control flow, may be moved across other memory operations, and untouched output parameter elements don't result in store output calls (boiler plate calls are cleaned up).
  • Dynamic indexing of input/output array elements previously loaded element-by-element need to translate to dynamic indexes in load/store output operations.
  • Layouts for signature elements do not necessarily match parameter memory layouts (signature element flattening).

Some of these details may prove a bit tricky for the current wrapped entry function approach.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions