You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hull与Domain着色器无法编译的问题排查求助

着色器编译错误排查求助

Hull Shader 报错

  • main函数上方的所有属性均出现警告X3554:unknown attribute <attr_name_here>, or attribute invalid for this statement
  • main函数的InputPatch参数出现错误X3658:'main': InputPatch inputs can only be used in the domain shaders and a hull shader's patch constant function

Hull Shader 代码

struct HullShaderInput
{
    float4 wPos : WPOSITION;
    float4 position : SV_POSITION;
    float3 colour : COLOUR;
    float3 normal : NORMAL;
    float2 uv : UV;
};

struct HullShaderConstDataOutput
{
    float EdgeTessFactor[3] : SV_TessFactor;
    float InsideTessFactor : SV_InsideTessFactor;
};

struct HullShaderOutput
{
    float4 wPos : WPOSITION;
    float4 position : SV_POSITION;
    float3 colour : COLOUR;
    float3 normal : NORMAL;
    float2 uv : UV;
};

cbuffer cBuff : register(b0)
{
    float4x4 world;
    float4x4 view;
    float4x4 projection;
    float4 camPos;
}

#define NUM_CONTROL_POINTS 3

float calcTessFactor(float3 vertP1, float3 vertP2)
{
    float edgeLen = distance(vertP1, vertP2);
    float edgeCamDist = distance((vertP1+vertP2)/2, camPos.xyz);
    
    return clamp((edgeLen)/(edgeCamDist), 1.0f, 63.0f);
}

HullShaderConstDataOutput CalcHSPatchConstants
(   InputPatch<HullShaderInput, NUM_CONTROL_POINTS> ip,
    uint i : SV_PrimitiveID )
{
    HullShaderConstDataOutput output;
    output.EdgeTessFactor[i] = calcTessFactor(ip[i].wPos.xyz, ip[(i+1)%3].wPos.xyz);
    output.InsideTessFactor = (output.EdgeTessFactor[0]+output.EdgeTessFactor[1]+output.EdgeTessFactor[2])/3;

    return output;
}

[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("HullShaderConstDataOutput")]
HullShaderOutput main
(   InputPatch<HullShaderInput, NUM_CONTROL_POINTS> ip,
    uint i : SV_OutputControlPointID    )
{
    HullShaderOutput output;
    
    output.wPos = ip[i].wPos;
    output.position = ip[i].position;
    output.normal = ip[i].normal;
    output.uv = ip[i].uv;
    
    return output;
}

Domain Shader 报错

  • [domain("tri")]属性出现警告X3554
  • main函数的OutputPatch参数出现错误X3658

Domain Shader 代码

struct DomainShaderConstDataInput
{
    float EdgeTessFactor[3] : SV_TessFactor;
    float InsideTessFactor : SV_InsideTessFactor;
};

struct DomainShaderInput
{
    float4 wPos : WPOSITION;
    float4 position : SV_POSITION;
    float3 colour : COLOUR;
    float3 normal : NORMAL;
    float2 uv : UV;
};

struct DomainShaderOutput
{
    float4 wPos : WPOSITION;
    float4 position : SV_POSITION;
    float3 colour : COLOUR;
    float3 normal : NORMAL;
    float2 uv : UV;
};

cbuffer cBuff : register(b0)
{
    float4x4 world;
    float4x4 view;
    float4x4 projection;
    float4 camPos;
};

#define NUM_CONTROL_POINTS 3

[domain("tri")]
DomainShaderOutput main
(   DomainShaderConstDataInput input, float3 barycentric : SV_DomainLocation,
    const OutputPatch<DomainShaderInput, NUM_CONTROL_POINTS> patch  )
{
    DomainShaderOutput output;
    output.wPos = patch[0].wPos*barycentric.x + patch[1].wPos*barycentric.y + patch[2].wPos*barycentric.z;
    output.normal = normalize(patch[0].normal*barycentric.x + patch[1].normal*barycentric.y + patch[2].normal*barycentric.z);
    output.uv = patch[0].uv*barycentric.x + patch[1].uv*barycentric.y + patch[2].uv*barycentric.z;
    output.position = mul(mul(output.wPos, view), projection);
    
    return output;
}

我已经知道原本用Shader Model 4不行,切换到SM5后还是编译失败,提示找不到HullShaderConstDataOutput属性的入口点,请问问题出在哪?


错误修正方案

1. Hull Shader 核心错误修正

  • patchconstantfunc 参数错误:[patchconstantfunc("HullShaderConstDataOutput")] 填了结构体名,实际应该填常量函数的名字CalcHSPatchConstants,这是导致"找不到入口点"的直接原因。
  • main函数参数错误:Hull Shader的main函数不能直接接收InputPatch,正确格式是用uint : SV_OutputControlPointID索引,搭配单个HullShaderInput输入(系统会自动传入对应索引的控制点数据)。
  • 常量函数逻辑错误:原函数用i : SV_PrimitiveID遍历边是错误的,SV_PrimitiveID是当前patch的ID,不是边的索引,需要手动计算三条边的tess因子。

修正后的Hull Shader代码:

struct HullShaderInput
{
    float4 wPos : WPOSITION;
    float4 position : SV_POSITION;
    float3 colour : COLOUR;
    float3 normal : NORMAL;
    float2 uv : UV;
};

struct HullShaderConstDataOutput
{
    float EdgeTessFactor[3] : SV_TessFactor;
    float InsideTessFactor : SV_InsideTessFactor;
};

struct HullShaderOutput
{
    float4 wPos : WPOSITION;
    float4 position : SV_POSITION;
    float3 colour : COLOUR;
    float3 normal : NORMAL;
    float2 uv : UV;
};

cbuffer cBuff : register(b0)
{
    float4x4 world;
    float4x4 view;
    float4x4 projection;
    float4 camPos;
}

#define NUM_CONTROL_POINTS 3

float calcTessFactor(float3 vertP1, float3 vertP2)
{
    float edgeLen = distance(vertP1, vertP2);
    float edgeCamDist = distance((vertP1+vertP2)/2, camPos.xyz);
    
    return clamp((edgeLen)/(edgeCamDist), 1.0f, 63.0f);
}

HullShaderConstDataOutput CalcHSPatchConstants
(   InputPatch<HullShaderInput, NUM_CONTROL_POINTS> ip,
    uint patchID : SV_PrimitiveID )
{
    HullShaderConstDataOutput output;
    // 手动计算三条边的 tess 因子
    output.EdgeTessFactor[0] = calcTessFactor(ip[0].wPos.xyz, ip[1].wPos.xyz);
    output.EdgeTessFactor[1] = calcTessFactor(ip[1].wPos.xyz, ip[2].wPos.xyz);
    output.EdgeTessFactor[2] = calcTessFactor(ip[2].wPos.xyz, ip[0].wPos.xyz);
    output.InsideTessFactor = (output.EdgeTessFactor[0]+output.EdgeTessFactor[1]+output.EdgeTessFactor[2])/3;

    return output;
}

[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("CalcHSPatchConstants")] // 修正为函数名
HullShaderOutput main
(   HullShaderInput input, // 改为单个输入
    uint i : SV_OutputControlPointID    )
{
    HullShaderOutput output;
    
    output.wPos = input.wPos;
    output.position = input.position;
    output.normal = input.normal;
    output.uv = input.uv;
    
    return output;
}

2. Domain Shader 核心错误修正

  • 多余的domain属性:Domain Shader不需要[domain("tri")]属性,该属性是Hull Shader专用,删除后可解决X3554警告。
  • OutputPatch参数错误:Domain Shader接收控制点数据应该用InputPatch,而非OutputPatch,这是导致X3658错误的原因。
  • 矩阵乘法顺序错误:原代码mul(mul(output.wPos, view), projection)不符合MVP变换顺序,HLSL矩阵是左乘,需改为mul(projection, mul(view, output.wPos))。

修正后的Domain Shader代码:

struct DomainShaderConstDataInput
{
    float EdgeTessFactor[3] : SV_TessFactor;
    float InsideTessFactor : SV_InsideTessFactor;
};

struct DomainShaderInput
{
    float4 wPos : WPOSITION;
    float4 position : SV_POSITION;
    float3 colour : COLOUR;
    float3 normal : NORMAL;
    float2 uv : UV;
};

struct DomainShaderOutput
{
    float4 wPos : WPOSITION;
    float4 position : SV_POSITION;
    float3 colour : COLOUR;
    float3 normal : NORMAL;
    float2 uv : UV;
};

cbuffer cBuff : register(b0)
{
    float4x4 world;
    float4x4 view;
    float4x4 projection;
    float4 camPos;
};

#define NUM_CONTROL_POINTS 3

// 删除[domain("tri")]属性
DomainShaderOutput main
(   DomainShaderConstDataInput input, float3 barycentric : SV_DomainLocation,
    const InputPatch<DomainShaderInput, NUM_CONTROL_POINTS> patch  ) // 改为InputPatch
{
    DomainShaderOutput output;
    output.wPos = patch[0].wPos*barycentric.x + patch[1].wPos*barycentric.y + patch[2].wPos*barycentric.z;
    output.normal = normalize(patch[0].normal*barycentric.x + patch[1].normal*barycentric.y + patch[2].normal*barycentric.z);
    output.uv = patch[0].uv*barycentric.x + patch[1].uv*barycentric.y + patch[2].uv*barycentric.z;
    // 修正矩阵乘法顺序
    output.position = mul(projection, mul(view, output.wPos));
    
    return output;
}

额外注意点

  • 编译时需明确指定Shader Model 5(如hs_5_0、ds_5_0)。

内容的提问来源于stack exchange,提问作者Atryx10

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:03:11