hlsl shader编译中遇到的一个坑

来源:互联网 发布:无线网访客网络 编辑:程序博客网 时间:2024/05/21 15:41

        最近在修改我们引擎中shader编译相关的逻辑的时候遇到了一个坑。写这个引擎的前辈为了让vertex shader和fragmentshader名称相同的寄存器常量对于的寄存器索引也是一样的。在编写shader代码的时候手动指定了每个常量的寄存器索引并人工保证索引不会冲突,如此一来就可以在逻辑代码中对于每个名称的uniform只记录一个索引号并利用这个索引号来填充寄存器常量。我个人认为这样写不太好,一方面由于shader代码中存在着很多预编译宏,这回导致很多在宏内部的索引号没有利用起来使得整个寄存器的可用空间极大的浪费。另一方面每次修改一个效果或者增减一些效果的时候需要增加或减少一些uniform。由于要保证vertex shader 和fragment shader中索引相同,需要调整两个shader中寄存器的索引以便达到索引相同的目的,这是一个非常头疼并且没什么价值的工作。因此我就把shader的逻辑代码中记录寄存器索引的地方改为针对每个shader都单独记录一个索引ID并分别使用各自的ID来设置寄存器常量的数据,这样在写shader的时候就不需要考虑索引冲突问题。

        然而悲剧就这样发生了,编译后的shader不知道为什么索引号好像都出问题了。按照编译生成的索引号去填充数据结果有时候表现就不对。一开始以为是设置数据的时候出问题了,找了好久都没有发现问题的所在。然后就使用了shader版的打印大发(把每个数据单独分离出来最终当做颜色输出)一个一个数据看,矩阵一行一行看。最终发现有些寄存器数据好像被写坏了,然后再使用注释大法找到了相关的代码片段。根据这一点就开始跟踪整个shader的编译过程包括寄存器索引的存储和使用到最后数据的设置,终于皇天不负有心人让我发现了问题的所在。然来shader编译后整个shader都被编译器个优化了以便导致好多东西面目全非。

        看看具体的代码吧

struct VertexShaderInput{float4 g_Color : COLOR0;float4 g_Position : POSITION0;float3 g_Normal : NORMAL0;float2 g_TexCoord0 : TEXCOORD0;};struct VertexShaderOutput{float4 pos : POSITION;float4 v_TexCoord0 : TEXCOORD0;float3 v_WorldPos : TEXCOORD1;float4 v_ProjPos : TEXCOORD2;float3 v_VertexNormal : TEXCOORD3;    float3 v_ViewPos : TEXCOORD6;};//float4x4 g_WorldViewProjMatrix ;//float4x4 g_WorldMatrix ;//float4x4 g_WorldViewMatrix ;float4x4 g_WorldMatrix;float time;VertexShaderOutput main(VertexShaderInput input){VertexShaderOutput output;float x = time;    output.pos = float4(1.0, 1.0, 1.0, 1.0);  //  output.pos = mul(float4(1.0, 1.0, 1.0, 1.0), g_WorldViewProjMatrix);    output.v_TexCoord0 = float4(1.0, 1.0, 1.0, 1.0) ;//mul(float4(1.0, 1.0, 1.0, 1.0), g_WorldMatrix);output.v_WorldPos =float3(1.0, 1.0, 1.0);output.v_ProjPos = float4(1.0, 0.0, 0.0, 0.0);//output.v_ProjPos = mul(float4(1.0, 0.0, 0.0, 0.0), g_WorldViewMatrix);float4 ttt=  mul(float4(1.0, 1.0, 1.0, 1.0), g_WorldMatrix);output.v_VertexNormal =ttt.xyz;    output.v_ViewPos = float3(1.0, 1.0, 1.0);    return output;}
上面是我精简到最后的代码片段。这段代码中声明了两个寄存器常量float4x4 g_WorldMatrix和float time。由于time在代码中只对x进行了赋值带并没有输出。因此这个常量就没有了相与没有声明,这一点还比较好理解。一般这个最后设置shader数据的时候也没有填。因此的更深的是g_WorldMatrix。明明声明的是float4x4应该是4x4的矩阵占用4个寄存器。然而并不是这样。
float4 ttt=  mul(float4(1.0, 1.0, 1.0, 1.0), g_WorldMatrix);output.v_VertexNormal =ttt.xyz;
由于在输出结果中outpu.v_VertexNormal 只取了ttt的xyz分量。因此g_WorldMatrix中最后一行并不影响输出的结果因此g_worldmatrix只被分配了3个寄存器因为最后一行不影响计算结果。这优化做的。。。只能改代码了


0 0
原创粉丝点击