microsoft / DirectXShaderCompiler

This repo hosts the source for the DirectX Shader Compiler which is based on LLVM/Clang.
Other
3.09k stars 690 forks source link

Pass-through control point case broken for hull shader #6001

Open tex3d opened 12 months ago

tex3d commented 12 months ago

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:

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

damyanp commented 1 week ago

It seems there's multiple issues here, at least one of them is a bug in the validator that we'll want to address, so we'll likely need to split this issue up.