Directx 着色器代码优化
我有这个代码片段(用于cubemap PCF过滤)。我想为着色器模型2优化它。我尝试用统一存储的置换矩阵消除分支,但它需要太多(2x24) GLSL处理得很好。目标是向后兼容Directx 着色器代码优化,directx,shader,Directx,Shader,我有这个代码片段(用于cubemap PCF过滤)。我想为着色器模型2优化它。我尝试用统一存储的置换矩阵消除分支,但它需要太多(2x24) GLSL处理得很好。目标是向后兼容 (BTW.算法是错误的,但这不是现在的问题)不是真正的优化,而是考虑测试这个。 显然,在这种情况下,并非总是期望的,也很少有最好的解决方案是转移到不合适的CPU额外代码(例如,由于指令计数)。在分支的情况下,您可以: 将分支条件检查移动到CPU 拆分并移动以分离着色器分支实体 根据条件检查的结果绑定适当的着色器 这是你
(BTW.算法是错误的,但这不是现在的问题)
不是真正的优化,而是考虑测试这个。
显然,在这种情况下,并非总是期望的,也很少有最好的解决方案是转移到不合适的CPU额外代码(例如,由于指令计数)。在分支的情况下,您可以:- 将分支条件检查移动到CPU
- 拆分并移动以分离着色器分支实体
- 根据条件检查的结果绑定适当的着色器
希望能有所帮助。虽然我不知道SM2.0能否解决这个问题,但考虑到GPU能力的提升,我提供了一个SM3.0解决方案 请记住,这段代码是我自己的着色器语言的一个片段(但与HLSL类似):
模板
浮点PCFIrregularCUBE(采样器阴影贴图、采样器噪声测试、浮点3 ldir、浮点2 sloc、浮点2 texelsize)
{
常量浮点内核半径=2.0f;
float3 l=正常化(ldir);
3铝=abs(l);
浮子2噪声;
浮动2旋转;
浮动标准差,t,s;
浮动d=长度(ldir);
噪声=tex2D(noisetex,sloc);
噪声=正常化(噪声*2.0f-1.0f);
float2-rotmat0=float2(noise.x,noise.y);
float2-rotmat1=float2(-noise.y,noise.x);
浮动3次;
s=0;
对于(int i=0;isd)-0.0f:1.0f);
s+=((标准差<0.001f)~1.0f:t);
}
返回s*(1.0f/样本);
}
CubeOffsetXXX类似于:
float3 CubeOffsetZXY(float3 swiz, float2 off, float2 texelsize)
{
float3 ret;
ret.xy = swiz.xy + 2.0f * off * texelsize * swiz.z;
ret.z = sqrt(1.0f - dot(ret.xy, ret.xy));
if( swiz.z < 0 )
ret.z *= -1.0f;
return ret;
}
float3立方体偏移设置zxy(float3开关、float2关闭、float2 texelsize)
{
浮动3-ret;
ret.xy=swiz.xy+2.0f*off*texelsize*swiz.z;
ret.z=sqrt(1.0f-点(ret.xy,ret.xy));
如果(开关z<0)
ret.z*=-1.0f;
返回ret;
}
如需了解更多详细信息,请在谷歌上搜索不规则PCF。最糟糕的结果(如“相机靠近”)是:
请注意由不规则PCF引起的“盐和胡椒”噪音。从远处看,这是完全可以接受的(Crysis 1方法)。条件在着色器内部,因此我无法将其移动到CPU(ldir=wpos-lightpos)请提供
CubeOffset()
definitionadded;我想(也许)把它预先计算成一个纹理顺便问一下,你优化的目标是什么?你不符合规定吗?根据多少?107算术,总共111个(SM2中允许64和96个)
float3 CubeOffset(float3 swiz, float2 off, float2 texelsize)
{
float3 ret;
ret.yz = swiz.yz + 2.0f * off * texelsize;
ret.x = sqrt(1.0f - dot(ret.yz, ret.yz));
if( swiz.x < 0 )
ret.x *= -1.0f;
return ret;
}
error X5608: Compiled shader code uses too many arithmetic instruction slots (107).
Max. allowed by the target (ps_2_0) is 64.
error X5609: Compiled shader code uses too many instruction slots (111).
Max. allowed by the target (ps_2_0) is 96.
template <int samples>
float PCFIrregularCUBE(sampler shadowmap, sampler noisetex, float3 ldir, float2 sloc, float2 texelsize)
{
const float kernelradius = 2.0f;
float3 l = normalize(ldir);
float3 al = abs(l);
float2 noise;
float2 rotated;
float sd, t, s;
float d = length(ldir);
noise = tex2D(noisetex, sloc);
noise = normalize(noise * 2.0f - 1.0f);
float2 rotmat0 = float2(noise.x, noise.y);
float2 rotmat1 = float2(-noise.y, noise.x);
float3 off;
s = 0;
for( int i = 0; i < samples; ++i ) {
rotated.x = dot(irreg_kernel[i], rotmat0) * kernelradius;
rotated.y = dot(irreg_kernel[i], rotmat1) * kernelradius;
if( al.x < al.y ) {
if( al.y < al.z )
off = CubeOffsetZXY(l, rotated, texelsize);
else
off = CubeOffsetYXZ(l, rotated, texelsize);
} else {
if( al.x < al.z )
off = CubeOffsetZXY(l, rotated, texelsize);
else
off = CubeOffsetXYZ(l, rotated, texelsize);
}
sd = texCUBE(shadowmap, off).r;
t = ((d > sd) ? 0.0f : 1.0f);
s += ((sd < 0.001f) ? 1.0f : t);
}
return s * (1.0f / samples);
}
float3 CubeOffsetZXY(float3 swiz, float2 off, float2 texelsize)
{
float3 ret;
ret.xy = swiz.xy + 2.0f * off * texelsize * swiz.z;
ret.z = sqrt(1.0f - dot(ret.xy, ret.xy));
if( swiz.z < 0 )
ret.z *= -1.0f;
return ret;
}