microsoft / microsoft/DirectXShaderCompiler

Pass-through control point case broken for hull shader

Open
#6,001 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug crash validation
Dominant language
C++
Stars
3.7k
Forks
900
Avg merge
2d 11h
Merged PRs (30d)
44

Description

Description
Hull shader is supposed to have a special pass-through case triggered when you copy input for corresponding SV_OutputControlPointID directly to a compatible output. The pass-through case should result in no manual copying of control point inputs to control point outputs, instead using a null entry function pointer, or something like that.

There are problems blocking this scenario:

  • the compiler does not recognize the scenario in the first place
  • I cannot even craft any scenario I can think of directly in DXIL that successfully validates
  • Conflicting assumptions about what this should even look like in different areas of code

In metadata loading, code assumes that a null metadata node for the shader function in the entry list denotes the pass-through case.
If you attempt this, the validator will crash because it relies on a map of function pointers to entry properties, which will cause it to fail to look up the entry properties for the function. Even DxilModule relies on a map of function pointer to entry properties, so there are deep problems with this representation.

The validator seems to assume that the pass through case will be denoted by a declaration for the entry function, instead of a definition, at least in the code that is supposed to be validating the pass through case. But if you try this, another part of the validator will say it's invalid because it sees this as an invalid DXIL intrinsic, assuming DXIL intrinsics are the only external function declarations allowed, besides llvm intrinsics.

Steps to Reproduce

// RUN: %dxc -T hs_6_0 -E MyHSMainPassthrough %s | FileCheck %s

// CHECK-NOT: @dx.op.loadInput
// CHECK: !dx.entryPoints = !{![[entries:[0-9]+]]}

// Should entry metadata be null?
// CHECK: ![[entries]] = !{null, !"MyHSMainPassthrough",

struct HSInputOutput { float4 pos : POSITION; };
[domain("tri")] [partitioning("integer")] [outputtopology("triangle_cw")]
[outputcontrolpoints(3)] [patchconstantfunc("MyPatchConstantFunc")]
HSInputOutput MyHSMainPassthrough(InputPatch<HSInputOutput, 3> input,
                                  uint id : SV_OutputControlPointID) {
  return input[id];
}

void MyPatchConstantFunc(out HSPerPatchData output) {
  output.edges[0] = 1;
  output.edges[1] = 2;
  output.edges[2] = 3;
  output.inside = 4;
}

Actual Behavior
No error occurs, but the control point function produced loads and stores each value, instead of matching the expected degenerate pass-through case.

Environment

  • DXC version: latest main
  • Host Operating System: any

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the DxilModule entry-point representation, metadata loading, and the validator paths described in the issue; run the HLSL reproducer with dxc and FileCheck. Done means the pass-through hull shader is recognized, emits no dx.op.loadInput operations, and produces valid DXIL without validator crashes or conflicting entry-function assumptions.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.