浏览代码

Reduced per frame memory allocations.

/LightweightPipelineExperimental
uygar 7 年前
当前提交
47eeaedf
共有 3 个文件被更改,包括 61 次插入34 次删除
  1. 81
      ScriptableRenderPipeline/Core/CoreRP/Shadow/Shadow.cs
  2. 12
      ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowUtilities.cs
  3. 2
      ScriptableRenderPipeline/Core/CoreRP/Shadow/VectorArray.cs

81
ScriptableRenderPipeline/Core/CoreRP/Shadow/Shadow.cs


using ShadowDataVector = VectorArray<ShadowData>;
using ShadowPayloadVector = VectorArray<ShadowPayload>;
using ShadowIndicesVector = VectorArray<int>;
using ShadowAlgoVector = VectorArray<GPUShadowAlgorithm>;
using ShadowAlgoVector = VectorArray<int>;
using Profiling;
// Standard shadow map atlas implementation using one large shadow map

protected RenderTexture m_Shadowmap;
protected RenderTargetIdentifier m_ShadowmapId;
protected VectorArray<CachedEntry> m_EntryCache = new VectorArray<CachedEntry>( 0, true );
private VectorArray<CachedEntry> m_EntryPool = new VectorArray<CachedEntry>( 16, false );
protected uint m_ActiveEntriesCount;
protected FrameId m_FrameId;
protected string m_ShaderKeyword;

protected float[] m_TmpBorders = new float[((k_MaxCascadesInShader+3)/4)*4];
protected ShadowAlgoVector m_SupportedAlgorithms = new ShadowAlgoVector( 0, false );
protected Material m_DebugMaterial = null;
private readonly VectorArray<CachedEntry>.Cleanup m_Cleanup;
private readonly VectorArray<CachedEntry>.Comparator<Key> m_Comparator;
public bool captureFrame { get; set; }
private CustomSampler m_SamplerShadowMaps = CustomSampler.Create("ShadowMaps");

public ShadowAtlas( ref AtlasInit init ) : base( ref init.baseInit )
{
m_Cleanup = (CachedEntry entry) => { Free( entry ); };
m_Comparator = (ref Key k, ref CachedEntry entry) => { return k.id == entry.key.id && k.faceIdx == entry.key.faceIdx; };
m_ZClipId = Shader.PropertyToID( "_ZClip" );
if( !IsNativeDepth() )
{

{
ShadowPrecision precision = m_ShadowmapBits == 32 ? ShadowPrecision.High : ShadowPrecision.Low;
m_SupportedAlgorithms.Reserve( 5 );
m_SupportedAlgorithms.AddUniqueUnchecked( ShadowUtils.Pack( ShadowAlgorithm.PCF, ShadowVariant.V0, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( ShadowUtils.Pack( ShadowAlgorithm.PCF, ShadowVariant.V1, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( ShadowUtils.Pack( ShadowAlgorithm.PCF, ShadowVariant.V2, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( ShadowUtils.Pack( ShadowAlgorithm.PCF, ShadowVariant.V3, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( ShadowUtils.Pack( ShadowAlgorithm.PCF, ShadowVariant.V4, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( (int) ShadowUtils.Pack( ShadowAlgorithm.PCF, ShadowVariant.V0, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( (int) ShadowUtils.Pack( ShadowAlgorithm.PCF, ShadowVariant.V1, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( (int) ShadowUtils.Pack( ShadowAlgorithm.PCF, ShadowVariant.V2, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( (int) ShadowUtils.Pack( ShadowAlgorithm.PCF, ShadowVariant.V3, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( (int) ShadowUtils.Pack( ShadowAlgorithm.PCF, ShadowVariant.V4, precision ) );
ShadowRegistry.VariantDelegate del = ( Light l, ShadowAlgorithm dataAlgorithm, ShadowVariant dataVariant, ShadowPrecision dataPrecision, ref int[] dataBlock ) =>
{

m_FrameId = frameId;
uint algoIdx;
GPUShadowAlgorithm shadowAlgo = sr.shadowAlgorithm;
int shadowAlgo = (int) sr.shadowAlgorithm;
if( !m_SupportedAlgorithms.FindFirst( out algoIdx, ref shadowAlgo ) )
return false;

uint added = m_ActiveEntriesCount - originalActiveEntries;
for( uint i = originalActiveEntries; i < m_ActiveEntriesCount; ++i )
m_EntryCache.Swap( i, m_EntryCache.Count()-i-1 );
m_EntryCache.Purge( added, Free );
m_EntryCache.Purge( added, m_Cleanup );
m_ActiveEntriesCount = originalActiveEntries;
return false;
}

}
// write :(
ce.current.shadowAlgo = shadowAlgo;
ce.current.shadowAlgo = (GPUShadowAlgorithm) shadowAlgo;
m_EntryCache[ceIdx] = ce;
sd.worldToShadow = vp.transpose; // apparently we need to transpose matrices that are sent to HLSL

// write back the correct results
entries[ce.key.shadowDataIdx] = sd;
}
m_EntryCache.Purge(m_EntryCache.Count() - m_ActiveEntriesCount, (CachedEntry entry) => { Free(entry); });
m_EntryCache.Purge(m_EntryCache.Count() - m_ActiveEntriesCount, m_Cleanup );
m_EntryCache.Reset( (CachedEntry entry) => { Free(entry); });
m_EntryCache.Reset( m_Cleanup );
return false;
}

{
if (m_ActiveEntriesCount == 0)
return;
string sLabel = string.Format("Shadowmap{0}", m_TexSlot);
string sLabel = captureFrame ? string.Format("Shadowmap{0}", m_TexSlot) : "Shadowmap";
var profilingSample = new ProfilingSample(cmd, sLabel, m_SamplerShadowMaps);
string cbName = "";

if( entrySlice != curSlice )
{
Debug.Assert( curSlice == uint.MaxValue || entrySlice >= curSlice, "Entries in the entry cache are not ordered in slice order." );
cbName = string.Format("Shadowmap.Update.Slice{0}", entrySlice);
cbName = captureFrame ? string.Format("Shadowmap.Update.Slice{0}", entrySlice) : "Shadowmap.Update.Slice";
cmd.BeginSample(cbName);
if( curSlice != uint.MaxValue )

cmd.EndSample(cbName);
}
//cbName = string.Format("Shadowmap.Update - slice: {0}, vp.x: {1}, vp.y: {2}, vp.w: {3}, vp.h: {4}", curSlice, m_EntryCache[i].current.viewport.x, m_EntryCache[i].current.viewport.y, m_EntryCache[i].current.viewport.width, m_EntryCache[i].current.viewport.height);
//cmd.BeginSample(cbName);
if( captureFrame )
{
cbName = string.Format( "Shadowmap.Update - slice: {0}, vp.x: {1}, vp.y: {2}, vp.w: {3}, vp.h: {4}", curSlice, m_EntryCache[i].current.viewport.x, m_EntryCache[i].current.viewport.y, m_EntryCache[i].current.viewport.width, m_EntryCache[i].current.viewport.height);
cmd.BeginSample( cbName );
}
//cmd.EndSample(cbName);
if( captureFrame )
cmd.EndSample( cbName );
dss.lightIndex = m_EntryCache[i].key.visibleIdx;
dss.splitData = m_EntryCache[i].current.splitData;

protected bool Alloc( FrameId frameId, Key key, uint width, uint height, out uint cachedEntryIdx, VectorArray<ShadowPayload> payload )
{
CachedEntry ce = new CachedEntry();
CachedEntry ce = null;
if( m_EntryPool.Count() > 0 )
{
ce = m_EntryPool[m_EntryPool.Count()-1];
m_EntryPool.Purge( 1 );
}
if( ce == null )
ce = new CachedEntry();
ce.key = key;
ce.current.frameId = frameId;
ce.current.contentHash = -1;

uint idx;
if ( m_EntryCache.FindFirst( out idx, ref key, (ref Key k, ref CachedEntry entry) => { return k.id == entry.key.id && k.faceIdx == entry.key.faceIdx; } ) )
if ( m_EntryCache.FindFirst( out idx, ref key, m_Comparator ) )
m_EntryPool.Add( m_EntryCache[idx] );
m_EntryCache[idx] = ce;
cachedEntryIdx = m_ActiveEntriesCount;
m_EntryCache.SwapUnchecked( m_ActiveEntriesCount++, idx );

{
m_EntryCache.SwapUnchecked( idx, m_EntryCache.Count()-1 );
m_EntryCache.Purge( 1, Free );
m_EntryCache.Purge( 1, m_Cleanup );
}
}

protected void Free( CachedEntry ce )
{
// Nothing to do for this implementation here, as the atlas is reconstructed each frame, instead of keeping state across frames
m_EntryPool.Add( ce );
}
override public void DisplayShadowMap(CommandBuffer debugCB, Vector4 scaleBias, uint slice, float screenX, float screenY, float screenSizeX, float screenSizeY, float minValue, float maxValue)

m_SupportedAlgorithms.Reserve( 5 );
if( supports_VSM )
{
m_SupportedAlgorithms.AddUniqueUnchecked( ShadowUtils.Pack( ShadowAlgorithm.VSM, ShadowVariant.V0, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( (int) ShadowUtils.Pack( ShadowAlgorithm.VSM, ShadowVariant.V0, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( ShadowUtils.Pack( ShadowAlgorithm.EVSM, ShadowVariant.V0, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( (int) ShadowUtils.Pack( ShadowAlgorithm.EVSM, ShadowVariant.V0, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( ShadowUtils.Pack( ShadowAlgorithm.EVSM, ShadowVariant.V0, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( ShadowUtils.Pack( ShadowAlgorithm.EVSM, ShadowVariant.V1, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( (int) ShadowUtils.Pack( ShadowAlgorithm.EVSM, ShadowVariant.V0, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( (int) ShadowUtils.Pack( ShadowAlgorithm.EVSM, ShadowVariant.V1, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( ShadowUtils.Pack( ShadowAlgorithm.MSM, ShadowVariant.V0, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( ShadowUtils.Pack( ShadowAlgorithm.MSM, ShadowVariant.V1, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( (int) ShadowUtils.Pack( ShadowAlgorithm.MSM, ShadowVariant.V0, precision ) );
m_SupportedAlgorithms.AddUniqueUnchecked( (int) ShadowUtils.Pack( ShadowAlgorithm.MSM, ShadowVariant.V1, precision ) );
registry.Register( type, precision, ShadowAlgorithm.MSM, "Moment shadow map (MSM)",
new ShadowVariant[] { ShadowVariant.V0, ShadowVariant.V1 }, new string[] { "Hamburg", "Hausdorff" }, new ShadowRegistry.VariantDelegate[] { msmDel, msmDel } );
}

}
}
private readonly SortReverter m_SortReverter = new SortReverter();
private readonly VectorArray<long>.Extractor<int> m_Extractor = delegate(long key) { return (int) (key & 0xffffffff); };
protected override void PrioritizeShadowCasters( Camera camera, List<VisibleLight> lights, uint shadowRequestsCount, int[] shadowRequests )
{
// this function simply looks at the projected area on the screen, ignoring all light types and shapes

m_TmpSortKeys.AddUnchecked( val );
}
m_TmpSortKeys.Sort( new SortReverter() );
m_TmpSortKeys.ExtractTo( shadowRequests, 0, out shadowRequestsCount, delegate(long key) { return (int) (key & 0xffffffff); } );
m_TmpSortKeys.Sort( m_SortReverter );
m_TmpSortKeys.ExtractTo( shadowRequests, 0, out shadowRequestsCount, m_Extractor );
}
protected override void PruneShadowCasters( Camera camera, List<VisibleLight> lights, ref VectorArray<int> shadowRequests, ref ShadowRequestVector requestsGranted, out uint totalRequestCount )

12
ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowUtilities.cs


public static Matrix4x4 ExtractPointLightMatrix( VisibleLight vl, uint faceIdx, float fovBias, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData )
{
Debug.Assert( faceIdx <= (uint) CubemapFace.NegativeZ, "Tried to extract cubemap face " + faceIdx + "." );
if( faceIdx > (uint) CubemapFace.NegativeZ )
Debug.LogError( "Tried to extract cubemap face " + faceIdx + "." );
splitData = new ShadowSplitData();
splitData.cullingSphere.Set( 0.0f, 0.0f, 0.0f, float.NegativeInfinity );

var vari = ExtractVariant( gpuAlgo );
return Pack( algo, vari, ShadowPrecision.Low );
}
public static float Asfloat( uint val ) { return System.BitConverter.ToSingle( System.BitConverter.GetBytes( val ), 0 ); }
public static float Asfloat( int val ) { return System.BitConverter.ToSingle( System.BitConverter.GetBytes( val ), 0 ); }
public static int Asint( float val ) { return System.BitConverter.ToInt32( System.BitConverter.GetBytes( val ), 0 ); }
public static uint Asuint( float val ) { return System.BitConverter.ToUInt32( System.BitConverter.GetBytes( val ), 0 ); }
public static float Asfloat( uint val ) { unsafe { return *((float*)&val); } }
public static float Asfloat( int val ) { unsafe { return *((float*)&val); } }
public static int Asint( float val ) { unsafe { return *((int*)&val); } }
public static uint Asuint( float val ) { unsafe { return *((uint*)&val); } }
}
} // end of namespace UnityEngine.Experimental.ScriptableRenderLoop

2
ScriptableRenderPipeline/Core/CoreRP/Shadow/VectorArray.cs


{
for (idx = 0; idx < m_count; ++idx)
{
if (m_array[m_offset + idx].Equals(designator))
if (System.Collections.Generic.EqualityComparer<T>.Default.Equals(m_array[m_offset + idx], designator))
return true;
}
idx = k_InvalidIdx;

正在加载...
取消
保存