浏览代码

Merge pull request #779 from Unity-Technologies/lw-gc-optim

Reduced GC pressure in LWRP
/LightweightPipelineExperimental
GitHub 7 年前
当前提交
efa6b6c6
共有 2 个文件被更改,包括 72 次插入55 次删除
  1. 113
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs
  2. 14
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipelineUtils.cs

113
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs


private static readonly int kMaxVertexLights = 4;
// We have no good approach exposed to skip shader variants, e.g, ideally we would like to skip _CASCADE for all punctual lights
// We combine light and shadow classification keywords to reduce the amount of shader variants.
// Lightweight shader library declares defines based on these keywords to avoid having to check them in the shaders
// Core.hlsl defines _MAIN_LIGHT_DIRECTIONAL and _MAIN_LIGHT_SPOT (point lights can't be main light)
// Shadow.hlsl defines _SHADOWS_ENABLED, _SHADOWS_SOFT, _SHADOWS_CASCADE, _SHADOWS_PERSPECTIVE
private static readonly string[] kMainLightKeywords =
{
"_MAIN_LIGHT_DIRECTIONAL_SHADOW",
"_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE",
"_MAIN_LIGHT_DIRECTIONAL_SHADOW_SOFT",
"_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE_SOFT",
"_MAIN_LIGHT_SPOT_SHADOW",
"_MAIN_LIGHT_SPOT_SHADOW_SOFT"
};
private StringBuilder m_MainLightKeywordString = new StringBuilder(43);
private bool m_IsOffscreenCamera;
private Vector4[] m_LightPositions = new Vector4[kMaxVisibleLights];

private const int kMaxCascades = 4;
private int m_ShadowCasterCascadesCount;
private int m_ShadowMapRTID;
private Matrix4x4[] m_ShadowMatrices = new Matrix4x4[kMaxCascades + 1];
private RenderTargetIdentifier m_CurrCameraColorRT;
private RenderTargetIdentifier m_ShadowMapRT;
private RenderTargetIdentifier m_ColorRT;

private PostProcessLayer m_CameraPostProcessLayer;
private CameraComparer m_CameraComparer = new CameraComparer();
private LightComparer m_LightCompararer = new LightComparer();
private LightComparer m_LightComparer = new LightComparer();
private Dictionary<VisibleLight, int> m_VisibleLightsIDMap = new Dictionary<VisibleLight, int>(new LightEqualityComparer());
private Mesh m_BlitQuad;
private Material m_BlitMaterial;
private Material m_CopyDepthMaterial;

#endif
CullResults.Cull(ref cullingParameters, context, ref m_CullResults);
VisibleLight[] visibleLights = m_CullResults.visibleLights.ToArray();
List<VisibleLight> visibleLights = m_CullResults.visibleLights;
LightData lightData;
InitializeLightData(visibleLights, out lightData);

}
}
private void ShadowPass(VisibleLight[] visibleLights, ref ScriptableRenderContext context, ref LightData lightData)
private void ShadowPass(List<VisibleLight> visibleLights, ref ScriptableRenderContext context, ref LightData lightData)
{
if (m_Asset.AreShadowsEnabled() && lightData.mainLightIndex != -1)
{

context.DrawRenderers(m_CullResults.visibleRenderers, ref opaqueDrawSettings, opaqueFilterSettings);
}
private void ForwardPass(VisibleLight[] visibleLights, FrameRenderingConfiguration frameRenderingConfiguration, ref ScriptableRenderContext context, ref LightData lightData, bool stereoEnabled)
private void ForwardPass(List<VisibleLight> visibleLights, FrameRenderingConfiguration frameRenderingConfiguration, ref ScriptableRenderContext context, ref LightData lightData, bool stereoEnabled)
{
SetupShaderConstants(visibleLights, ref context, ref lightData);

cmd.GetTemporaryRT(CameraRenderTargetID.color, rtDesc, FilterMode.Bilinear);
}
private void SetupShaderConstants(VisibleLight[] visibleLights, ref ScriptableRenderContext context, ref LightData lightData)
private void SetupShaderConstants(List<VisibleLight> visibleLights, ref ScriptableRenderContext context, ref LightData lightData)
{
CommandBuffer cmd = CommandBufferPool.Get("SetupShaderConstants");
SetupShaderLightConstants(cmd, visibleLights, ref lightData);

}
private void InitializeLightData(VisibleLight[] visibleLights, out LightData lightData)
private void InitializeLightData(List<VisibleLight> visibleLights, out LightData lightData)
int visibleLightsCount = Math.Min(visibleLights.Length, m_Asset.MaxPixelLights);
int visibleLightsCount = Math.Min(visibleLights.Count, m_Asset.MaxPixelLights);
m_SortedLightIndexMap.Clear();
lightData.shadowMapSampleType = LightShadows.None;

// If we have a main light we don't shade it in the per-object light loop. We also remove it from the per-object cull list
int mainLightPresent = (lightData.mainLightIndex >= 0) ? 1 : 0;
int additionalPixelLightsCount = visibleLightsCount - mainLightPresent;
int vertexLightCount = (m_Asset.SupportsVertexLight) ? Math.Min(visibleLights.Length, kMaxPerObjectLights) - additionalPixelLightsCount : 0;
int vertexLightCount = (m_Asset.SupportsVertexLight) ? Math.Min(visibleLights.Count, kMaxPerObjectLights) - additionalPixelLightsCount : 0;
vertexLightCount = Math.Min(vertexLightCount, kMaxVertexLights);
lightData.pixelAdditionalLightsCount = additionalPixelLightsCount;

}
private int SortLights(VisibleLight[] visibleLights)
private int SortLights(List<VisibleLight> visibleLights)
int totalVisibleLights = visibleLights.Length;
int totalVisibleLights = visibleLights.Count;
Dictionary<int, int> visibleLightsIDMap = new Dictionary<int, int>();
m_VisibleLightsIDMap.Clear();
visibleLightsIDMap.Add(visibleLights[i].GetHashCode(), i);
m_VisibleLightsIDMap.Add(visibleLights[i], i);
m_LightCompararer.CurrCamera = m_CurrCamera;
Array.Sort(visibleLights, m_LightCompararer);
m_LightComparer.CurrCamera = m_CurrCamera;
visibleLights.Sort(m_LightComparer);
m_SortedLightIndexMap.Add(visibleLightsIDMap[visibleLights[i].GetHashCode()]);
m_SortedLightIndexMap.Add(m_VisibleLightsIDMap[visibleLights[i]]);
return GetMainLight(visibleLights);
}

// Otherwise directional lights have priority based on cookie support and intensity
private int GetMainLight(VisibleLight[] visibleLights)
private int GetMainLight(List<VisibleLight> visibleLights)
int totalVisibleLights = visibleLights.Length;
int totalVisibleLights = visibleLights.Count;
bool shadowsEnabled = m_Asset.AreShadowsEnabled();
if (totalVisibleLights == 0 || m_Asset.MaxPixelLights == 0)

return brighestDirectionalIndex;
}
private void InitializeLightConstants(VisibleLight[] lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightDistanceAttenuation, out Vector4 lightSpotDir,
private void InitializeLightConstants(List<VisibleLight> lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightDistanceAttenuation, out Vector4 lightSpotDir,
out Vector4 lightSpotAttenuation)
{
float directContributionNotBaked = 1.0f;

Shader.SetGlobalVector(PerFrameBuffer._SubtractiveShadowColor, CoreUtils.ConvertSRGBToActiveColorSpace(RenderSettings.subtractiveShadowColor));
}
private void SetupShaderLightConstants(CommandBuffer cmd, VisibleLight[] lights, ref LightData lightData)
private void SetupShaderLightConstants(CommandBuffer cmd, List<VisibleLight> lights, ref LightData lightData)
SetupShadowReceiverConstants(cmd, ref lights[lightData.mainLightIndex]);
SetupShadowReceiverConstants(cmd, lights[lightData.mainLightIndex]);
private void SetupMainLightConstants(CommandBuffer cmd, VisibleLight[] lights, int lightIndex)
private void SetupMainLightConstants(CommandBuffer cmd, List<VisibleLight> lights, int lightIndex)
{
Vector4 lightPos, lightColor, lightDistanceAttenuation, lightSpotDir, lightSpotAttenuation;
InitializeLightConstants(lights, lightIndex, out lightPos, out lightColor, out lightDistanceAttenuation, out lightSpotDir, out lightSpotAttenuation);

cmd.SetGlobalVector(PerCameraBuffer._MainLightSpotAttenuation, lightSpotAttenuation);
}
private void SetupAdditionalListConstants(CommandBuffer cmd, VisibleLight[] lights, ref LightData lightData)
private void SetupAdditionalListConstants(CommandBuffer cmd, List<VisibleLight> lights, ref LightData lightData)
{
int additionalLightIndex = 0;

int[] perObjectLightIndexMap = m_CullResults.GetLightIndexMap();
for (int i = 0; i < lights.Length; ++i)
for (int i = 0; i < lights.Count; ++i)
for (int i = 0; i < lights.Length && additionalLightIndex < kMaxVisibleLights; ++i)
for (int i = 0; i < lights.Count && additionalLightIndex < kMaxVisibleLights; ++i)
{
if (i != lightData.mainLightIndex)
{

cmd.SetGlobalVector("_LightDirection", new Vector4(lightDirection.x, lightDirection.y, lightDirection.z, 0.0f));
}
private void SetupShadowReceiverConstants(CommandBuffer cmd, ref VisibleLight shadowLight)
private void SetupShadowReceiverConstants(CommandBuffer cmd, VisibleLight shadowLight)
Matrix4x4[] shadowMatrices = new Matrix4x4[kMaxCascades + 1];
shadowMatrices[i] = (cascadeCount >= i) ? m_ShadowSlices[i].shadowTransform : Matrix4x4.identity;
m_ShadowMatrices[i] = (cascadeCount >= i) ? m_ShadowSlices[i].shadowTransform : Matrix4x4.identity;
// We setup and additional a no-op WorldToShadow matrix in the last index
// because the ComputeCascadeIndex function in Shadows.hlsl can return an index

shadowMatrices[kMaxCascades] = noOpShadowMatrix;
m_ShadowMatrices[kMaxCascades] = noOpShadowMatrix;
cmd.SetGlobalMatrixArray("_WorldToShadow", shadowMatrices);
cmd.SetGlobalMatrixArray("_WorldToShadow", m_ShadowMatrices);
cmd.SetGlobalVector("_ShadowData", new Vector4(light.shadowStrength, 0.0f, 0.0f, 0.0f));
cmd.SetGlobalVectorArray("_DirShadowSplitSpheres", m_DirectionalShadowSplitDistances);
cmd.SetGlobalVector("_DirShadowSplitSphereRadii", m_DirectionalShadowSplitRadii);

cmd.SetGlobalVector("_ShadowOffset3", new Vector4(invShadowResolution, invShadowResolution, 0.0f, 0.0f));
}
private void SetShaderKeywords(CommandBuffer cmd, ref LightData lightData, VisibleLight[] visibleLights)
private void SetShaderKeywords(CommandBuffer cmd, ref LightData lightData, List<VisibleLight> visibleLights)
// We have no good approach exposed to skip shader variants, e.g, ideally we would like to skip _CASCADE for all punctual lights
// We combine light and shadow classification keywords to reduce the amount of shader variants.
// Lightweight shader library declares defines based on these keywords to avoid having to check them in the shaders
// Core.hlsl defines _MAIN_LIGHT_DIRECTIONAL and _MAIN_LIGHT_SPOT (point lights can't be main light)
// Shadow.hlsl defines _SHADOWS_ENABLED, _SHADOWS_SOFT, _SHADOWS_CASCADE, _SHADOWS_PERSPECTIVE
string[] mainLightKeywords =
{
"_MAIN_LIGHT_DIRECTIONAL_SHADOW",
"_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE",
"_MAIN_LIGHT_DIRECTIONAL_SHADOW_SOFT",
"_MAIN_LIGHT_DIRECTIONAL_SHADOW_CASCADE_SOFT",
"_MAIN_LIGHT_SPOT_SHADOW",
"_MAIN_LIGHT_SPOT_SHADOW_SOFT"
};
for (int i = 0; i < mainLightKeywords.Length; ++i)
cmd.DisableShaderKeyword(mainLightKeywords[i]);
for (int i = 0; i < kMainLightKeywords.Length; ++i)
cmd.DisableShaderKeyword(kMainLightKeywords[i]);
StringBuilder keywordString = new StringBuilder("_MAIN_LIGHT");
m_MainLightKeywordString.Length = 0;
m_MainLightKeywordString.Append("_MAIN_LIGHT");
keywordString.Append("_DIRECTIONAL_SHADOW");
m_MainLightKeywordString.Append("_DIRECTIONAL_SHADOW");
keywordString.Append("_CASCADE");
m_MainLightKeywordString.Append("_CASCADE");
keywordString.Append("_SPOT_SHADOW");
m_MainLightKeywordString.Append("_SPOT_SHADOW");
keywordString.Append("_SOFT");
string keyword = keywordString.ToString();
m_MainLightKeywordString.Append("_SOFT");
string keyword = m_MainLightKeywordString.ToString();
cmd.EnableShaderKeyword(keyword);
}

14
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipelineUtils.cs


using System;
using System.Collections.Generic;
using UnityEngine.Rendering;
namespace UnityEngine.Experimental.Rendering.LightweightPipeline
{

{
Vector3 lightCameraVector = lightPos - CurrCamera.transform.position;
return Vector3.Dot(lightCameraVector, lightCameraVector);
}
}
public class LightEqualityComparer : IEqualityComparer<VisibleLight>
{
public bool Equals(VisibleLight x, VisibleLight y)
{
return x.light.GetInstanceID() == y.light.GetInstanceID();
}
public int GetHashCode(VisibleLight obj)
{
return obj.light.GetInstanceID();
}
}

正在加载...
取消
保存