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
相关产品推荐
相关产品推荐

