浏览代码

Optimize punctual light evaluation by having an inlined function per light type

/main
Evgenii Golubev 7 年前
当前提交
fb4e09f9
共有 3 个文件被更改,包括 106 次插入30 次删除
  1. 3
      ScriptableRenderPipeline/Core/ShaderLibrary/BC6H.hlsl
  2. 94
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl
  3. 39
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl

3
ScriptableRenderPipeline/Core/ShaderLibrary/BC6H.hlsl


// compute endpoints (min/max RGB bbox)
float3 blockMin = texels[ 0 ];
float3 blockMax = texels[ 0 ];
for ( uint i = 1; i < 16; ++i )
uint i;
for (i = 1; i < 16; ++i )
{
blockMin = min( blockMin, texels[ i ] );
blockMax = max( blockMax, texels[ i ] );

94
ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl


if (featureFlags & LIGHTFEATUREFLAGS_PUNCTUAL)
{
#ifdef LIGHTLOOP_TILE_PASS
uint punctualLightCount;
// TODO: Convert the for loop below to a while on each type as we know we are sorted and compare performance.
#ifdef LIGHTLOOP_TILE_PASS
uint punctualLightCount;
#else
punctualLightCount = _PunctualLightCount;
#endif
for (i = 0; i < punctualLightCount; ++i)
if (punctualLightCount > 0)
int punctualIndex = FetchIndex(punctualLightStart, i);
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, _LightDatas[punctualIndex], bsdfData, bakeLightingData);
AccumulateDirectLighting(lighting, aggregateLighting);
}
i = 0;
uint last = punctualLightCount - 1;
#ifdef LIGHTLOOP_TILE_PASS
uint currIndex = FetchIndex(punctualLightStart, i);
uint currIndex = i;
#endif
LightData lightData = _LightDatas[currIndex];
for (i = 0; i < _PunctualLightCount; ++i)
{
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, _LightDatas[i], bsdfData, bakeLightingData);
AccumulateDirectLighting(lighting, aggregateLighting);
}
while (i <= last && lightData.lightType == GPULIGHTTYPE_POINT)
{
lightData.lightType = GPULIGHTTYPE_POINT; // Enforce constant propagation
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, lightData, bsdfData, bakeLightingData);
AccumulateDirectLighting(lighting, aggregateLighting);
#ifdef LIGHTLOOP_TILE_PASS
currIndex = FetchIndex(punctualLightStart, min(++i, last));
#else
currIndex = min(++i, last);
#endif
lightData = _LightDatas[currIndex];
}
while (i <= last && lightData.lightType == GPULIGHTTYPE_SPOT)
{
lightData.lightType = GPULIGHTTYPE_SPOT; // Enforce constant propagation
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, lightData, bsdfData, bakeLightingData);
AccumulateDirectLighting(lighting, aggregateLighting);
#endif
#ifdef LIGHTLOOP_TILE_PASS
currIndex = FetchIndex(punctualLightStart, min(++i, last));
#else
currIndex = min(++i, last);
#endif
lightData = _LightDatas[currIndex];
}
while (i <= last && lightData.lightType == GPULIGHTTYPE_PROJECTOR_PYRAMID)
{
lightData.lightType = GPULIGHTTYPE_PROJECTOR_PYRAMID; // Enforce constant propagation
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, lightData, bsdfData, bakeLightingData);
AccumulateDirectLighting(lighting, aggregateLighting);
#ifdef LIGHTLOOP_TILE_PASS
currIndex = FetchIndex(punctualLightStart, min(++i, last));
#else
currIndex = min(++i, last);
#endif
lightData = _LightDatas[currIndex];
}
while (i <= last && lightData.lightType == GPULIGHTTYPE_PROJECTOR_BOX)
{
lightData.lightType = GPULIGHTTYPE_PROJECTOR_BOX; // Enforce constant propagation
DirectLighting lighting = EvaluateBSDF_Punctual(context, V, posInput, preLightData, lightData, bsdfData, bakeLightingData);
AccumulateDirectLighting(lighting, aggregateLighting);
#ifdef LIGHTLOOP_TILE_PASS
currIndex = FetchIndex(punctualLightStart, min(++i, last));
#else
currIndex = min(++i, last);
#endif
lightData = _LightDatas[currIndex];
}
}
}
if (featureFlags & LIGHTFEATUREFLAGS_AREA)

// By keeping line lights first we avoid this behavior and save substantial register pressure.
// TODO: This is based on the current Lit.shader and can be different for any other way of implementing area lights, how to be generic and ensure performance ?
i = 0;
uint lastIndex = areaLightCount - 1;
uint last = areaLightCount - 1;
while (i <= lastIndex && lightData.lightType == GPULIGHTTYPE_LINE)
i = 0;
while (i <= last && lightData.lightType == GPULIGHTTYPE_LINE)
lightData = _LightDatas[FetchIndex(areaLightStart, min(++i, lastIndex))];
lightData = _LightDatas[FetchIndex(areaLightStart, min(++i, last))];
while (i <= lastIndex && lightData.lightType == GPULIGHTTYPE_RECTANGLE)
while (i <= last && lightData.lightType == GPULIGHTTYPE_RECTANGLE)
lightData = _LightDatas[FetchIndex(areaLightStart, min(++i, lastIndex))];
lightData = _LightDatas[FetchIndex(areaLightStart, min(++i, last))];
}
}

39
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


float GetPunctualShapeAttenuation(LightData lightData, float3 L, float distSq)
{
// Note: lightData.invSqrAttenuationRadius is 0 when applyRangeAttenuation is false
float attenuation = GetDistanceAttenuation(distSq, lightData.invSqrAttenuationRadius);
// Reminder: lights are oriented backward (-Z)
return attenuation * GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset);
float attenuation = 1.0;
if (lightData.lightType != GPULIGHTTYPE_PROJECTOR_BOX)
{
// Note: lightData.invSqrAttenuationRadius is 0 when applyRangeAttenuation is false
attenuation *= GetDistanceAttenuation(distSq, lightData.invSqrAttenuationRadius);
}
if (lightData.lightType == GPULIGHTTYPE_SPOT)
{
// Reminder: lights are oriented backward (-Z)
attenuation *= GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset);
}
return attenuation;
}
// None of the outputs are premultiplied.

float3 lightToSample = positionWS - lightData.positionWS;
int lightType = lightData.lightType;
float3 unL = (lightType != GPULIGHTTYPE_PROJECTOR_BOX) ? -lightToSample : -lightData.forward;
float distSq = dot(unL, unL);
float3 N = bsdfData.normalWS;
float3 L = unL * rsqrt(distSq);
float NdotL = dot(N, L);
float3 L; float distSq;
if (lightType == GPULIGHTTYPE_PROJECTOR_BOX)
{
distSq = 1.0;
L = -lightData.forward;
}
else
{
distSq = dot(lightToSample, lightToSample);
L = -lightToSample * rsqrt(distSq);
}
float3 N = bsdfData.normalWS;
float NdotL = dot(N, L);
float3 color; float attenuation, shadow;
EvaluateLight_Punctual(lightLoopContext, posInput, lightData, bakeLightingData, N, L, distSq,

正在加载...
取消
保存