Skip to content

Commit 750246d

Browse files
committed
Max Sim Per Frame Control per Probe Volumes Dynamic GI (#44)
* Control over max # of probe volume dynamic GI simulation's per frame * fixed issues with static value construction * More direct control of perf controls to dynamic GI
1 parent e7b894d commit 750246d

File tree

6 files changed

+209
-92
lines changed

6 files changed

+209
-92
lines changed

com.unity.render-pipelines.high-definition/Runtime/Lighting/ProbeVolume/DynamicGI/ProbeVolumeDynamicGI.cs

Lines changed: 165 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -62,50 +62,77 @@ public partial class ProbeVolumeDynamicGI
6262
private static ProbeVolumeDynamicGI s_Instance = new ProbeVolumeDynamicGI();
6363
public static ProbeVolumeDynamicGI instance { get { return s_Instance; } }
6464

65-
internal static readonly float s_DiagonalDist = Mathf.Sqrt(3.0f);
66-
internal static readonly float s_Diagonal = 1.0f / s_DiagonalDist;
67-
internal static readonly float s_2DDiagonalDist = Mathf.Sqrt(2.0f);
68-
internal static readonly float s_2DDiagonal = 1.0f / s_2DDiagonalDist;
65+
internal static float s_DiagonalDist;
66+
internal static float s_Diagonal;
67+
internal static float s_2DDiagonalDist;
68+
internal static float s_2DDiagonal;
69+
internal static Vector4[] s_NeighborAxis;
6970

7071
private ComputeShader _PropagationHitsShader = null;
7172
private ComputeShader _PropagationAxesShader = null;
7273
private ComputeShader _PropagationCombineShader = null;
7374

75+
private Vector4[] _tempAxisLookups;
76+
private Vector4[] _sortedAxisLookups;
77+
private RelevantNeighborAxisLookupComparer _axisComparer;
78+
private ProbeVolumeSimulationRequest[] _probeVolumeSimulationRequests;
79+
private RelevantProbeVolumeSimulationComparer _requestComparer;
7480

75-
internal static readonly Vector4[] s_NeighborAxis =
76-
{
77-
// middle slice
78-
new Vector4( 1, 0, 0, 1),
79-
new Vector4( s_2DDiagonal, 0, s_2DDiagonal, s_2DDiagonalDist),
80-
new Vector4( s_2DDiagonal, 0, -s_2DDiagonal, s_2DDiagonalDist),
81-
new Vector4(-1, 0, 0, 1),
82-
new Vector4(-s_2DDiagonal, 0, s_2DDiagonal, s_2DDiagonalDist),
83-
new Vector4(-s_2DDiagonal, 0, -s_2DDiagonal, s_2DDiagonalDist),
84-
new Vector4( 0, 0, 1, 1),
85-
new Vector4( 0, 0, -1, 1),
86-
87-
// upper slice
88-
new Vector4( 0, 1, 0, 1),
89-
new Vector4( s_2DDiagonal, s_2DDiagonal, 0, s_2DDiagonalDist),
90-
new Vector4( s_Diagonal, s_Diagonal, s_Diagonal, s_DiagonalDist),
91-
new Vector4( s_Diagonal, s_Diagonal, -s_Diagonal, s_DiagonalDist),
92-
new Vector4(-s_2DDiagonal, s_2DDiagonal, 0, s_2DDiagonalDist),
93-
new Vector4(-s_Diagonal, s_Diagonal, s_Diagonal, s_DiagonalDist),
94-
new Vector4(-s_Diagonal, s_Diagonal, -s_Diagonal, s_DiagonalDist),
95-
new Vector4( 0, s_2DDiagonal, s_2DDiagonal, s_2DDiagonalDist),
96-
new Vector4( 0, s_2DDiagonal, -s_2DDiagonal, s_2DDiagonalDist),
97-
98-
// lower slice
99-
new Vector4( 0, -1, 0, 1),
100-
new Vector4( s_2DDiagonal, -s_2DDiagonal, 0, s_2DDiagonalDist),
101-
new Vector4( s_Diagonal, -s_Diagonal, s_Diagonal, s_DiagonalDist),
102-
new Vector4( s_Diagonal, -s_Diagonal, -s_Diagonal, s_DiagonalDist),
103-
new Vector4(-s_2DDiagonal, -s_2DDiagonal, 0, s_2DDiagonalDist),
104-
new Vector4(-s_Diagonal, -s_Diagonal, s_Diagonal, s_DiagonalDist),
105-
new Vector4(-s_Diagonal, -s_Diagonal, -s_Diagonal, s_DiagonalDist),
106-
new Vector4( 0, -s_2DDiagonal, s_2DDiagonal, s_2DDiagonalDist),
107-
new Vector4( 0, -s_2DDiagonal, -s_2DDiagonal, s_2DDiagonalDist),
108-
};
81+
private const int MAX_SIMULATIONS_PER_FRAME = 128;
82+
private float _sortedAxisSharpness = -1;
83+
private int _probeVolumeSimulationRequestCount = 0;
84+
private int _probeVolumeSimulationFrameTick = 0;
85+
86+
87+
ProbeVolumeDynamicGI()
88+
{
89+
s_DiagonalDist = Mathf.Sqrt(3.0f);
90+
s_Diagonal = 1.0f / s_DiagonalDist;
91+
s_2DDiagonalDist = Mathf.Sqrt(2.0f);
92+
s_2DDiagonal = 1.0f / s_2DDiagonalDist;
93+
94+
s_NeighborAxis = new Vector4[]
95+
{
96+
// middle slice
97+
new Vector4( 1, 0, 0, 1),
98+
new Vector4( s_2DDiagonal, 0, s_2DDiagonal, s_2DDiagonalDist),
99+
new Vector4( s_2DDiagonal, 0, -s_2DDiagonal, s_2DDiagonalDist),
100+
new Vector4(-1, 0, 0, 1),
101+
new Vector4(-s_2DDiagonal, 0, s_2DDiagonal, s_2DDiagonalDist),
102+
new Vector4(-s_2DDiagonal, 0, -s_2DDiagonal, s_2DDiagonalDist),
103+
new Vector4( 0, 0, 1, 1),
104+
new Vector4( 0, 0, -1, 1),
105+
106+
// upper slice
107+
new Vector4( 0, 1, 0, 1),
108+
new Vector4( s_2DDiagonal, s_2DDiagonal, 0, s_2DDiagonalDist),
109+
new Vector4( s_Diagonal, s_Diagonal, s_Diagonal, s_DiagonalDist),
110+
new Vector4( s_Diagonal, s_Diagonal, -s_Diagonal, s_DiagonalDist),
111+
new Vector4(-s_2DDiagonal, s_2DDiagonal, 0, s_2DDiagonalDist),
112+
new Vector4(-s_Diagonal, s_Diagonal, s_Diagonal, s_DiagonalDist),
113+
new Vector4(-s_Diagonal, s_Diagonal, -s_Diagonal, s_DiagonalDist),
114+
new Vector4( 0, s_2DDiagonal, s_2DDiagonal, s_2DDiagonalDist),
115+
new Vector4( 0, s_2DDiagonal, -s_2DDiagonal, s_2DDiagonalDist),
116+
117+
// lower slice
118+
new Vector4( 0, -1, 0, 1),
119+
new Vector4( s_2DDiagonal, -s_2DDiagonal, 0, s_2DDiagonalDist),
120+
new Vector4( s_Diagonal, -s_Diagonal, s_Diagonal, s_DiagonalDist),
121+
new Vector4( s_Diagonal, -s_Diagonal, -s_Diagonal, s_DiagonalDist),
122+
new Vector4(-s_2DDiagonal, -s_2DDiagonal, 0, s_2DDiagonalDist),
123+
new Vector4(-s_Diagonal, -s_Diagonal, s_Diagonal, s_DiagonalDist),
124+
new Vector4(-s_Diagonal, -s_Diagonal, -s_Diagonal, s_DiagonalDist),
125+
new Vector4( 0, -s_2DDiagonal, s_2DDiagonal, s_2DDiagonalDist),
126+
new Vector4( 0, -s_2DDiagonal, -s_2DDiagonal, s_2DDiagonalDist),
127+
};
128+
129+
_tempAxisLookups = new Vector4[s_NeighborAxis.Length];
130+
_sortedAxisLookups = new Vector4[s_NeighborAxis.Length * s_NeighborAxis.Length];
131+
_probeVolumeSimulationRequests = new ProbeVolumeSimulationRequest[MAX_SIMULATIONS_PER_FRAME];
132+
133+
_axisComparer = new RelevantNeighborAxisLookupComparer();
134+
_requestComparer = new RelevantProbeVolumeSimulationComparer();
135+
}
109136

110137
internal static void AllocateNeighbors(ref ProbeVolumePayload payload, int numMissedAxis, int numHitAxis, int numAxis)
111138
{
@@ -305,53 +332,52 @@ public void ClearAllActive(bool clearAll)
305332
_clearAllActive = clearAll;
306333
}
307334

335+
private bool _overrideInfiniteBounce = false;
336+
private float _overrideInfiniteBounceValue;
337+
public void OverrideInfiniteBounce(bool setOverride, float value = 0)
338+
{
339+
_overrideInfiniteBounce = setOverride;
340+
_overrideInfiniteBounceValue = value;
341+
}
308342

309-
internal void DispatchProbePropagation(CommandBuffer cmd, ProbeVolumeHandle probeVolume, ProbeDynamicGI giSettings, in ShaderVariablesGlobal shaderGlobals, RenderTargetIdentifier probeVolumeAtlasSHRTHandle)
343+
private int _maxSimulationsPerFrame = MAX_SIMULATIONS_PER_FRAME;
344+
public void OverrideMaxSimulationsPerFrame(bool setOverride, int maxSimulations)
310345
{
311-
if (probeVolume.parameters.supportDynamicGI
312-
&& probeVolume.IsDataAssigned()
313-
&& probeVolume.HasNeighbors()
314-
&& probeVolume.GetProbeVolumeEngineDataIndex() >= 0)
346+
if (setOverride)
315347
{
316-
InitializePropagationBuffers(probeVolume);
317-
318-
if (giSettings.clear.value || _clearAllActive)
319-
{
320-
ClearRadianceCache(probeVolume);
321-
}
322-
323-
DispatchPropagationHits(cmd, probeVolume, in giSettings);
324-
DispatchPropagationAxes(cmd, probeVolume, in giSettings);
325-
DispatchPropagationCombine(cmd, probeVolume, in giSettings, in shaderGlobals, probeVolumeAtlasSHRTHandle);
326-
probeVolume.propagationBuffers.SwapRadianceCaches();
348+
_maxSimulationsPerFrame = maxSimulations;
327349
}
328350
else
329351
{
330-
if (CleanupPropagation(probeVolume))
331-
{
332-
// trigger an update so original bake data gets set since Dynamic GI was disabled
333-
probeVolume.SetDataUpdated(true);
334-
}
352+
_maxSimulationsPerFrame = MAX_SIMULATIONS_PER_FRAME;
335353
}
336354
}
337355

338-
internal void ClearProbePropagation(CommandBuffer cmd, ProbeVolumeHandle probeVolume, ProbeDynamicGI giSettings, in ShaderVariablesGlobal shaderGlobals, RenderTargetIdentifier probeVolumeAtlasSHRTHandle)
356+
internal void DispatchProbePropagation(CommandBuffer cmd, ProbeVolumeHandle probeVolume, ProbeDynamicGI giSettings, in ShaderVariablesGlobal shaderGlobals, RenderTargetIdentifier probeVolumeAtlasSHRTHandle)
339357
{
340-
if (probeVolume.parameters.supportDynamicGI
341-
&& probeVolume.IsDataAssigned()
342-
&& probeVolume.HasNeighbors()
343-
&& probeVolume.GetProbeVolumeEngineDataIndex() >= 0)
358+
InitializePropagationBuffers(probeVolume);
359+
360+
if (giSettings.clear.value || _clearAllActive)
344361
{
345-
if (probeVolume.parameters.supportDynamicGI
346-
&& probeVolume.IsDataAssigned()
347-
&& probeVolume.HasNeighbors()
348-
&& probeVolume.GetProbeVolumeEngineDataIndex() >= 0)
362+
ClearRadianceCache(probeVolume);
363+
}
364+
365+
DispatchPropagationHits(cmd, probeVolume, in giSettings);
366+
DispatchPropagationAxes(cmd, probeVolume, in giSettings);
367+
DispatchPropagationCombine(cmd, probeVolume, in giSettings, in shaderGlobals, probeVolumeAtlasSHRTHandle);
368+
369+
probeVolume.propagationBuffers.SwapRadianceCaches();
370+
probeVolume.SetLastSimulatedFrame(_probeVolumeSimulationFrameTick);
371+
}
372+
373+
internal void ClearProbePropagation(ProbeVolumeHandle probeVolume)
374+
{
375+
if (probeVolume.AbleToSimulateDynamicGI())
376+
{
377+
if (CleanupPropagation(probeVolume))
349378
{
350-
if (CleanupPropagation(probeVolume))
351-
{
352-
// trigger an update so original bake data gets set since Dynamic GI was disabled
353-
probeVolume.SetDataUpdated(true);
354-
}
379+
// trigger an update so original bake data gets set since Dynamic GI was disabled
380+
probeVolume.SetDataUpdated(true);
355381
}
356382
}
357383
}
@@ -378,7 +404,6 @@ void DispatchPropagationHits(CommandBuffer cmd, ProbeVolumeHandle probeVolume, i
378404
cmd.SetComputeFloatParam(shader, "_RayBias", giSettings.bias.value);
379405
cmd.SetComputeFloatParam(shader, "_LeakMultiplier", giSettings.leakMultiplier.value);
380406
cmd.SetComputeFloatParam(shader, "_DirectContribution", giSettings.directContribution.value);
381-
cmd.SetComputeFloatParam(shader, "_InfiniteBounce", giSettings.infiniteBounce.value);
382407
cmd.SetComputeFloatParam(shader, "_InfiniteBounceSharpness", giSettings.infiniteBounceSharpness.value);
383408
cmd.SetComputeVectorArrayParam(shader, "_RayAxis", s_NeighborAxis);
384409

@@ -390,7 +415,14 @@ void DispatchPropagationHits(CommandBuffer cmd, ProbeVolumeHandle probeVolume, i
390415
cmd.SetComputeBufferParam(shader, kernel, "_HitRadianceCacheAxis", probeVolume.propagationBuffers.hitRadianceCache);
391416
cmd.SetComputeIntParam(shader, "_HitRadianceCacheAxisCount", probeVolume.propagationBuffers.hitRadianceCache.count);
392417

393-
CoreUtils.SetKeyword(shader, "COMPUTE_INFINITE_BOUNCE", giSettings.infiniteBounce.value > 0);
418+
float infBounce = giSettings.infiniteBounce.value;
419+
if (_overrideInfiniteBounce)
420+
{
421+
infBounce = _overrideInfiniteBounceValue;
422+
}
423+
424+
cmd.SetComputeFloatParam(shader, "_InfiniteBounce", infBounce);
425+
CoreUtils.SetKeyword(shader, "COMPUTE_INFINITE_BOUNCE", infBounce > 0);
394426

395427
int numHits = probeVolume.propagationBuffers.neighborHits.count;
396428
int dispatchX = (numHits + 63) / 64;
@@ -459,7 +491,7 @@ void DispatchPropagationAxes(CommandBuffer cmd, ProbeVolumeHandle probeVolume, i
459491
cmd.SetComputeIntParam(shader, "_RadianceCacheAxisCount", probeVolume.propagationBuffers.radianceCacheAxis0.count);
460492

461493
PrecomputeAxisCacheLookup(giSettings.propagationSharpness.value);
462-
cmd.SetComputeVectorArrayParam(shader, "_SortedNeighborAxis", s_sortedAxisLookups);
494+
cmd.SetComputeVectorArrayParam(shader, "_SortedNeighborAxis", _sortedAxisLookups);
463495

464496
int numHits = probeVolume.propagationBuffers.neighbors.count;
465497
int dispatchX = (numHits + 63) / 64;
@@ -607,7 +639,7 @@ float SGEvaluateFromDirection(float sgAmplitude, float sgSharpness, Vector3 sgMe
607639

608640
void PrecomputeAxisCacheLookup(float sgSharpness)
609641
{
610-
if (!Mathf.Approximately(s_sortedAxisSharpness, sgSharpness))
642+
if (!Mathf.Approximately(_sortedAxisSharpness, sgSharpness))
611643
{
612644
for (int axisIndex = 0; axisIndex < s_NeighborAxis.Length; ++axisIndex)
613645
{
@@ -616,14 +648,66 @@ void PrecomputeAxisCacheLookup(float sgSharpness)
616648
{
617649
var neighborDirection = s_NeighborAxis[neighborIndex];
618650
var sgWeight = SGEvaluateFromDirection(1, sgSharpness, neighborDirection, axis);
619-
s_tempAxisLookups[neighborIndex] = new Vector4(sgWeight, neighborIndex, 0, 0);
651+
_tempAxisLookups[neighborIndex] = new Vector4(sgWeight, neighborIndex, 0, 0);
620652
}
621653

622-
Array.Sort(s_tempAxisLookups, s_axisComparer);
623-
Array.Copy(s_tempAxisLookups, 0, s_sortedAxisLookups, axisIndex * s_NeighborAxis.Length, s_NeighborAxis.Length);
654+
Array.Sort(_tempAxisLookups, _axisComparer);
655+
Array.Copy(_tempAxisLookups, 0, _sortedAxisLookups, axisIndex * s_NeighborAxis.Length, s_NeighborAxis.Length);
656+
}
657+
658+
_sortedAxisSharpness = sgSharpness;
659+
}
660+
}
661+
662+
internal void ResetSimulationRequests()
663+
{
664+
_probeVolumeSimulationRequestCount = 0;
665+
++_probeVolumeSimulationFrameTick;
666+
}
667+
668+
internal void AddSimulationRequest(List<ProbeVolumeHandle> volumes, int probeVolumeIndex)
669+
{
670+
var probeVolume = volumes[probeVolumeIndex];
671+
if (probeVolume.AbleToSimulateDynamicGI() && _probeVolumeSimulationRequestCount < _probeVolumeSimulationRequests.Length)
672+
{
673+
var lastSimulatedFrame = probeVolume.GetLastSimulatedFrame();
674+
_probeVolumeSimulationRequests[_probeVolumeSimulationRequestCount] = new ProbeVolumeSimulationRequest
675+
{
676+
probeVolumeIndex = probeVolumeIndex,
677+
simulationFrameDelta = Mathf.Abs(lastSimulatedFrame - _probeVolumeSimulationFrameTick)
678+
};
679+
++_probeVolumeSimulationRequestCount;
680+
}
681+
else
682+
{
683+
if (CleanupPropagation(probeVolume))
684+
{
685+
// trigger an update so original bake data gets set since Dynamic GI was disabled
686+
probeVolume.SetDataUpdated(true);
624687
}
688+
}
689+
}
690+
691+
internal ProbeVolumeSimulationRequest[] SortSimulationRequests(out int numSimulationRequests)
692+
{
693+
Array.Sort(_probeVolumeSimulationRequests, 0, _probeVolumeSimulationRequestCount, _requestComparer);
694+
numSimulationRequests = _probeVolumeSimulationRequestCount;
695+
numSimulationRequests = Mathf.Min(numSimulationRequests, _maxSimulationsPerFrame);
625696

626-
s_sortedAxisSharpness = sgSharpness;
697+
return _probeVolumeSimulationRequests;
698+
}
699+
700+
internal struct ProbeVolumeSimulationRequest
701+
{
702+
public int probeVolumeIndex;
703+
public int simulationFrameDelta;
704+
}
705+
706+
class RelevantProbeVolumeSimulationComparer : IComparer<ProbeVolumeSimulationRequest>
707+
{
708+
public int Compare( ProbeVolumeSimulationRequest x, ProbeVolumeSimulationRequest y )
709+
{
710+
return y.simulationFrameDelta - x.simulationFrameDelta;
627711
}
628712
}
629713

@@ -635,11 +719,6 @@ public int Compare( Vector4 x, Vector4 y )
635719
return diff < 0 ? 1 : diff > 0 ? -1 : 0;
636720
}
637721
}
638-
639-
private static Vector4[] s_tempAxisLookups = new Vector4[s_NeighborAxis.Length];
640-
private static Vector4[] s_sortedAxisLookups = new Vector4[s_NeighborAxis.Length * s_NeighborAxis.Length];
641-
private static float s_sortedAxisSharpness = -1;
642-
private static RelevantNeighborAxisLookupComparer s_axisComparer = new RelevantNeighborAxisLookupComparer();
643722
}
644723

645724
} // UnityEngine.Experimental.Rendering.HDPipeline

com.unity.render-pipelines.high-definition/Runtime/Lighting/ProbeVolume/IProbeVolumeList.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ interface IProbeVolumeList
4646
int GetNeighborAxisLength(int i);
4747
void SetHitNeighborAxis(int i, ComputeBuffer buffer);
4848
void SetNeighborAxis(int i, ComputeBuffer buffer);
49+
void SetLastSimulatedFrame(int i, int simulationFrameTick);
50+
int GetLastSimulatedFrame(int i);
4951

5052
#if UNITY_EDITOR
5153
public bool IsHiddenInScene(int i);

com.unity.render-pipelines.high-definition/Runtime/Lighting/ProbeVolume/ProbeVolume.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,7 @@ internal class ProbeVolume : MonoBehaviour
654654
internal int m_ProbeVolumeEngineDataIndex = -1;
655655
internal OrientedBBox m_BoundingBox;
656656
internal ProbeVolumeEngineData m_EngineData;
657+
internal int m_simulationFrameTick = -1;
657658

658659
private ProbeVolumeSettingsKey bakeKey = new ProbeVolumeSettingsKey
659660
{
@@ -771,7 +772,7 @@ private static bool ComputeQuaternionApproximatelyEqual(Quaternion a, Quaternion
771772
private bool dataNeedsDilation = false;
772773
#endif
773774
[SerializeField] private VolumeGlobalUniqueID globalUniqueID = VolumeGlobalUniqueID.zero;
774-
775+
775776
[SerializeField] internal ProbeVolumeAsset probeVolumeAsset = null;
776777
[SerializeField] internal ProbeVolumeArtistParameters parameters = new ProbeVolumeArtistParameters(Color.white);
777778
internal ProbePropagationBuffers m_PropagationBuffers;
@@ -827,7 +828,7 @@ internal static ProbeVolumeAtlasKey ComputeProbeVolumeAtlasKey(VolumeGlobalUniqu
827828
Quaternion volumeRotation, Quaternion assetRotation, Vector3 position, bool supportDynamicGI)
828829
{
829830
Quaternion sphericalHarmonicWSFromOS = Quaternion.Inverse(assetRotation) * volumeRotation;
830-
831+
831832
// Only enforce uniquing the key based on position if dynamic GI is enabled.
832833
// If dynamic GI is enabled, two probe volumes that point to the same asset, streamed in at different locations need unique space in the atlas (because their dynamic GI component is different).
833834
// If dynamic GI is disabled, two probe volumes that point to the same asset, streamed in at different locations should share space in the atlas, since their baked data is identical.
@@ -1086,6 +1087,16 @@ internal void CleanupBuffers()
10861087
CleanupBuffers(m_VolumeBuffers);
10871088
}
10881089

1090+
internal void SetLastSimulatedFrame(int simulationFrameTick)
1091+
{
1092+
m_simulationFrameTick = simulationFrameTick;
1093+
}
1094+
1095+
internal int GetLastSimulatedFrame()
1096+
{
1097+
return m_simulationFrameTick;
1098+
}
1099+
10891100
public static void CleanupBuffers(ProbeVolumeBuffers buffers)
10901101
{
10911102
CleanupBuffer(buffers.SHL01Buffer);

0 commit comments

Comments
 (0)