浏览代码

Added a new ShadowPayload struct that contains 4 ints to cut down on the number of buffer load instructions in shaders.

Updated the code to use the new shadow payload struct instead of a simple int[] array.
Removed an obsolete assertion.
/main
uygar 7 年前
当前提交
02ed6370
共有 6 个文件被更改,包括 51 次插入50 次删除
  1. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  2. 26
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.cs
  3. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.hlsl
  4. 23
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowAlgorithms.hlsl
  5. 40
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowBase.cs
  6. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowContext.hlsl

8
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs


{
// shadow related stuff
const int k_MaxShadowDataSlots = 64;
const int k_MaxPayloadSlotsPerShadowData = 16;
const int k_MaxPayloadSlotsPerShadowData = 4;
ShadowmapBase[] m_Shadowmaps;
ShadowManager m_ShadowMgr;
static ComputeBuffer s_ShadowDataBuffer;

{
s_ShadowDataBuffer = new ComputeBuffer( k_MaxShadowDataSlots, System.Runtime.InteropServices.Marshal.SizeOf( typeof( ShadowExp.ShadowData ) ) );
s_ShadowPayloadBuffer = new ComputeBuffer( k_MaxShadowDataSlots * k_MaxPayloadSlotsPerShadowData, System.Runtime.InteropServices.Marshal.SizeOf( typeof( int ) ) );
s_ShadowPayloadBuffer = new ComputeBuffer( k_MaxShadowDataSlots * k_MaxPayloadSlotsPerShadowData, System.Runtime.InteropServices.Marshal.SizeOf( typeof( ShadowExp.ShadowData ) ) );
ShadowAtlas.AtlasInit atlasInit;
atlasInit.baseInit.width = (uint) shadowSettings.shadowAtlasWidth;
atlasInit.baseInit.height = (uint) shadowSettings.shadowAtlasHeight;

uint offset, count;
ShadowExp.ShadowData[] sds;
sc.GetShadowDatas( out sds, out offset, out count );
Debug.Assert( offset == 0 );
int[] payloads;
ShadowPayload[] payloads;
Debug.Assert( offset == 0 );
s_ShadowPayloadBuffer.SetData( payloads );
};

26
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.cs


using ShadowRequestVector = VectorArray<ShadowmapBase.ShadowRequest>;
using ShadowDataVector = VectorArray<ShadowData>;
using ShadowPayloadVector = VectorArray<int>;
using ShadowPayloadVector = VectorArray<ShadowPayload>;
using ShadowIndicesVector = VectorArray<int>;
// Standard shadow map atlas implementation using one large shadow map

// TODO: clean up resources if necessary
}
override public bool Reserve( FrameId frameId, ref ShadowData shadowData, ShadowRequest sr, uint width, uint height, ref VectorArray<ShadowData> entries, ref VectorArray<int> payload, VisibleLight[] lights )
override public bool Reserve( FrameId frameId, ref ShadowData shadowData, ShadowRequest sr, uint width, uint height, ref VectorArray<ShadowData> entries, ref VectorArray<ShadowPayload> payload, VisibleLight[] lights )
{
for( uint i = 0, cnt = sr.facecount; i < cnt; ++i )
{

return Reserve( frameId, ref shadowData, sr, m_TmpWidths, m_TmpHeights, ref entries, ref payload, lights );
}
override public bool Reserve( FrameId frameId, ref ShadowData shadowData, ShadowRequest sr, uint[] widths, uint[] heights, ref VectorArray<ShadowData> entries, ref VectorArray<int> payload, VisibleLight[] lights )
override public bool Reserve( FrameId frameId, ref ShadowData shadowData, ShadowRequest sr, uint[] widths, uint[] heights, ref VectorArray<ShadowData> entries, ref VectorArray<ShadowPayload> payload, VisibleLight[] lights )
{
ShadowData sd = shadowData;
ShadowData dummy = new ShadowData();

if (sr.shadowType == GPUShadowType.Directional)
{
uint payloadSize = 4 * k_MaxCascadesInShader;
payload.Reserve( payloadSize );
ShadowPayload sp = new ShadowPayload();
payload.Reserve( k_MaxCascadesInShader );
payload.AddUnchecked( ShadowUtils.Asint( m_TmpSplits[i].x ) );
payload.AddUnchecked( ShadowUtils.Asint( m_TmpSplits[i].y ) );
payload.AddUnchecked( ShadowUtils.Asint( m_TmpSplits[i].z ) );
payload.AddUnchecked( ShadowUtils.Asint( m_TmpSplits[i].w ) );
sp.Set( m_TmpSplits[i] );
payload.AddUnchecked( sp );
}
}

override public bool ReserveFinalize( FrameId frameId, ref VectorArray<ShadowData> entries, ref VectorArray<int> payload )
override public bool ReserveFinalize( FrameId frameId, ref VectorArray<ShadowData> entries, ref VectorArray<ShadowPayload> payload )
{
if( Layout() )
{

cb.ReleaseTemporaryRT( m_TempDepthId );
}
protected bool Alloc( FrameId frameId, Key key, uint width, uint height, out uint cachedEntryIdx, VectorArray<int> payload )
protected bool Alloc( FrameId frameId, Key key, uint width, uint height, out uint cachedEntryIdx, VectorArray<ShadowPayload> payload )
{
CachedEntry ce = new CachedEntry();
ce.key = key;

{
public ShadowContextAccess( ref ShadowContext.CtxtInit initializer ) : base( ref initializer ) { }
// unfortunately ref returns are only a C# 7.0 feature
public VectorArray<ShadowData> shadowDatas { get { return m_ShadowDatas; } set { m_ShadowDatas = value; } }
public VectorArray<int> payloads { get { return m_Payloads; } set { m_Payloads = value; } }
public VectorArray<ShadowData> shadowDatas { get { return m_ShadowDatas; } set { m_ShadowDatas = value; } }
public VectorArray<ShadowPayload> payloads { get { return m_Payloads; } set { m_Payloads = value; } }
}
private const int k_MaxShadowmapPerType = 4;

ShadowPayloadVector payloadVector = m_ShadowCtxt.payloads;
m_ShadowIndices.Reset( m_TmpRequests.Count() );
AllocateShadows( frameId, lights, totalGranted, ref m_TmpRequests, ref m_ShadowIndices, ref shadowVector, ref payloadVector );
Debug.Assert( m_TmpRequests.Count() == m_ShadowIndices.Count() && shadowRequestsCount == m_ShadowIndices.Count() );
Debug.Assert( m_TmpRequests.Count() == m_ShadowIndices.Count() );
m_ShadowCtxt.shadowDatas = shadowVector;
m_ShadowCtxt.payloads = payloadVector;

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/Shadow.hlsl


struct ShadowContext \
{ \
StructuredBuffer<ShadowData> shadowDatas; \
StructuredBuffer<int> payloads; \
StructuredBuffer<int4> payloads; \
Texture2DArray tex2DArray[_Tex2DArraySlots]; \
TextureCubeArray texCubeArray[_TexCubeArraySlots]; \
SamplerComparisonState compSamplers[_SamplerCompSlots]; \

23
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowAlgorithms.hlsl


{
uint offset = GetPayloadOffset( shadowContext.shadowDatas[index] );
splitSpheres[0].x = asfloat( shadowContext.payloads[offset + 0] );
splitSpheres[0].y = asfloat( shadowContext.payloads[offset + 1] );
splitSpheres[0].z = asfloat( shadowContext.payloads[offset + 2] );
splitSpheres[0].w = asfloat( shadowContext.payloads[offset + 3] );
splitSpheres[1].x = asfloat( shadowContext.payloads[offset + 4] );
splitSpheres[1].y = asfloat( shadowContext.payloads[offset + 5] );
splitSpheres[1].z = asfloat( shadowContext.payloads[offset + 6] );
splitSpheres[1].w = asfloat( shadowContext.payloads[offset + 7] );
splitSpheres[2].x = asfloat( shadowContext.payloads[offset + 8] );
splitSpheres[2].y = asfloat( shadowContext.payloads[offset + 9] );
splitSpheres[2].z = asfloat( shadowContext.payloads[offset +10] );
splitSpheres[2].w = asfloat( shadowContext.payloads[offset +11] );
splitSpheres[3].x = asfloat( shadowContext.payloads[offset +12] );
splitSpheres[3].y = asfloat( shadowContext.payloads[offset +13] );
splitSpheres[3].z = asfloat( shadowContext.payloads[offset +14] );
splitSpheres[3].w = asfloat( shadowContext.payloads[offset +15] );
splitSpheres[0] = asfloat( shadowContext.payloads[offset + 0] );
splitSpheres[1] = asfloat( shadowContext.payloads[offset + 1] );
splitSpheres[2] = asfloat( shadowContext.payloads[offset + 2] );
splitSpheres[3] = asfloat( shadowContext.payloads[offset + 3] );
}
float EvalShadow_CascadedDepth( ShadowContext shadowContext, float3 positionWS, int index, float3 L )

40
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowBase.cs


}
// -------------- End temporary structs that need to be replaced at some point ---------------
public struct ShadowPayload
{
public int p0;
public int p1;
public int p2;
public int p3;
public void Set( float v0, float v1, float v2, float v3 )
{
p0 = ShadowUtils.Asint( v0 );
p1 = ShadowUtils.Asint( v1 );
p2 = ShadowUtils.Asint( v2 );
p3 = ShadowUtils.Asint( v3 );
}
public void Set( Vector4 v ) { Set( v.x, v.y, v.z, v.w ); }
}
// Class holding resource information that needs to be synchronized with shaders.
public class ShadowContextStorage

public void SetTexCubeArraySlot( uint slot, RenderTargetIdentifier val ) { m_TexCubeArray[slot] = val; }
protected VectorArray<ShadowData> m_ShadowDatas = new VectorArray<ShadowData>( 0, false );
protected VectorArray<int> m_Payloads = new VectorArray<int>( 0, false );
protected VectorArray<ShadowPayload> m_Payloads = new VectorArray<ShadowPayload>( 0, false );
protected VectorArray<RenderTargetIdentifier> m_Tex2DArray = new VectorArray<RenderTargetIdentifier>( 0, true );
protected VectorArray<RenderTargetIdentifier> m_TexCubeArray = new VectorArray<RenderTargetIdentifier>( 0, true );
protected VectorArray<ComparisonSamplerState> m_CompSamplers = new VectorArray<ComparisonSamplerState>( 0, true );

public void BindResources( CommandBuffer cb ) { m_ResourceBinderDel( this, cb ); }
// the following functions are to be used by the bind and sync delegates
public void GetShadowDatas(out ShadowData[] shadowDatas, out uint offset, out uint count) { shadowDatas = m_ShadowDatas.AsArray(out offset, out count); }
public void GetPayloads(out int[] payloads, out uint offset, out uint count) { payloads = m_Payloads.AsArray(out offset, out count); }
public void GetTex2DArrays(out RenderTargetIdentifier[] tex2DArrays, out uint offset, out uint count) { tex2DArrays = m_Tex2DArray.AsArray(out offset, out count); }
public void GetTexCubeArrays(out RenderTargetIdentifier[] texCubeArrays, out uint offset, out uint count) { texCubeArrays = m_TexCubeArray.AsArray(out offset, out count); }
public void GetComparisonSamplerArrays(out ComparisonSamplerState[] compSamplers, out uint offset, out uint count) { compSamplers = m_CompSamplers.AsArray(out offset, out count); }
public void GetSamplerArrays(out SamplerState[] samplerArrays, out uint offset, out uint count) { samplerArrays = m_Samplers.AsArray(out offset, out count); }
public void GetShadowDatas( out ShadowData[] shadowDatas, out uint offset, out uint count ) { shadowDatas = m_ShadowDatas.AsArray( out offset, out count ); }
public void GetPayloads( out ShadowPayload[] payloads, out uint offset, out uint count ) { payloads = m_Payloads.AsArray( out offset, out count ); }
public void GetTex2DArrays( out RenderTargetIdentifier[] tex2DArrays, out uint offset, out uint count ) { tex2DArrays = m_Tex2DArray.AsArray( out offset, out count ); }
public void GetTexCubeArrays( out RenderTargetIdentifier[] texCubeArrays, out uint offset, out uint count ) { texCubeArrays = m_TexCubeArray.AsArray( out offset, out count ); }
public void GetComparisonSamplerArrays( out ComparisonSamplerState[] compSamplers, out uint offset, out uint count ) { compSamplers = m_CompSamplers.AsArray( out offset, out count ); }
public void GetSamplerArrays( out SamplerState[] samplerArrays, out uint offset, out uint count ) { samplerArrays = m_Samplers.AsArray( out offset, out count ); }
private SyncDel m_DataSyncerDel;
private BindDel m_ResourceBinderDel;

public uint GetMaxPayload() { return m_MaxPayloadCount; }
public void AssignId( uint shadowId ) { m_ShadowId = shadowId; }
public void Assign( CullResults cullResults ) { m_CullResults = cullResults; } // TODO: Remove when m_CullResults is removed again
abstract public bool Reserve( FrameId frameId, ref ShadowData shadowData, ShadowRequest sr, uint width, uint height, ref VectorArray<ShadowData> entries, ref VectorArray<int> payloads, VisibleLight[] lights );
abstract public bool Reserve( FrameId frameId, ref ShadowData shadowData, ShadowRequest sr, uint[] widths, uint[] heights, ref VectorArray<ShadowData> entries, ref VectorArray<int> payloads, VisibleLight[] lights );
abstract public bool ReserveFinalize( FrameId frameId, ref VectorArray<ShadowData> entries, ref VectorArray<int> payloads );
abstract public bool Reserve( FrameId frameId, ref ShadowData shadowData, ShadowRequest sr, uint width, uint height, ref VectorArray<ShadowData> entries, ref VectorArray<ShadowPayload> payloads, VisibleLight[] lights );
abstract public bool Reserve( FrameId frameId, ref ShadowData shadowData, ShadowRequest sr, uint[] widths, uint[] heights, ref VectorArray<ShadowData> entries, ref VectorArray<ShadowPayload> payloads, VisibleLight[] lights );
abstract public bool ReserveFinalize( FrameId frameId, ref VectorArray<ShadowData> entries, ref VectorArray<ShadowPayload> payloads );
abstract public void Update( FrameId frameId, ScriptableRenderContext renderContext, CullResults cullResults, VisibleLight[] lights );
abstract public void ReserveSlots( ShadowContextStorage sc );
abstract public void Fill( ShadowContextStorage cs );

// When called the array contains the indices of lights requesting shadows,
// upon returning the array contains up to shadowRequestsCount valid shadow caster indices,
// whereas [shadowRequestsCount;originalRequestsCount) will hold all indices for lights that wanted to cast a shadow but got rejected.
// shadowDataIndices contains the offset into the shadowDatas array for each shadow casting light, e.g. lights[shadowRequests[i]].shadowDataOffset = shadowDataIndices[i];
// shadowDataIndices contains the offset into the shadowDatas array only for each shadow casting light, e.g. lights[shadowRequests[i]].shadowDataOffset = shadowDataIndices[i];
// shadowDatas contains shadowmap related basic parameters that can be passed to the shader.
// shadowPayloads contains implementation specific data that is accessed from the shader by indexing into an Buffer<int> using ShadowData.ShadowmapData.payloadOffset.
// This is the equivalent of a void pointer in the shader and there needs to be loader code that knows how to interpret the data.

// prune the shadow requests - may modify shadowRequests and shadowsCountshadowRequestsCount
protected abstract void PruneShadowCasters( Camera camera, VisibleLight[] lights, ref VectorArray<int> shadowRequests, ref VectorArray<ShadowmapBase.ShadowRequest> requestsGranted, out uint totalRequestCount );
// allocate the shadow requests in the shadow map, only is called if shadowsCount > 0 - may modify shadowRequests and shadowsCount
protected abstract void AllocateShadows( FrameId frameId, VisibleLight[] lights, uint totalGranted, ref VectorArray<ShadowmapBase.ShadowRequest> grantedRequests, ref VectorArray<int> shadowIndices, ref VectorArray<ShadowData> shadowmapDatas, ref VectorArray<int> shadowmapPayload );
protected abstract void AllocateShadows( FrameId frameId, VisibleLight[] lights, uint totalGranted, ref VectorArray<ShadowmapBase.ShadowRequest> grantedRequests, ref VectorArray<int> shadowIndices, ref VectorArray<ShadowData> shadowmapDatas, ref VectorArray<ShadowPayload> shadowmapPayload );
}
} // end of namespace ShadowExp

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Shadow/ShadowContext.hlsl


SHADOWCONTEXT_DECLARE( SHADOWCONTEXT_MAX_TEX2DARRAY, SHADOWCONTEXT_MAX_TEXCUBEARRAY, SHADOWCONTEXT_MAX_COMPSAMPLER, SHADOWCONTEXT_MAX_SAMPLER );
StructuredBuffer<ShadowData> _ShadowDatasExp;
StructuredBuffer<int> _ShadowPayloads;
StructuredBuffer<int4> _ShadowPayloads;
TEXTURE2D_ARRAY(_ShadowmapExp_Dir);
SAMPLER2D_SHADOW(sampler_ShadowmapExp_Dir);
TEXTURE2D_ARRAY(_ShadowmapExp_PointSpot);

正在加载...
取消
保存