@@ -43,6 +43,7 @@ namespace PatchUtil
4343 static const uint volumeAngularResolution = 4 ; // Must match C# side.
4444 static const float3 invalidIrradiance = float3 (-1 , -1 , -1 );
4545 static const uint updateMax = 32 ;
46+ static const uint evictionThreshold = 60 * 4 ;
4647
4748 struct PatchGeometry
4849 {
@@ -52,15 +53,18 @@ namespace PatchUtil
5253
5354 struct PatchCounterSet
5455 {
56+ // Layout
57+ // 0x000000FF: Update count.
58+ // 0x0000FF00: Rank.
59+ // 0xFFFF0000: Last access frame.
5560 uint data;
5661 };
5762
5863 struct PatchStatisticsSet
5964 {
6065 float3 mean;
6166 float3 variance;
62- PatchCounterSet patchCounters;
63- uint rank;
67+ PatchCounterSet counters;
6468 };
6569
6670 struct VolumeParamSet
@@ -81,14 +85,41 @@ namespace PatchUtil
8185 uint ringConfigOffset;
8286 };
8387
84- void Reset (inout PatchCounterSet set)
88+ uint ModuloDistance (uint a, uint b, uint modulo)
89+ {
90+ int dif = abs (int (a) - int (b));
91+ return min (dif, modulo - dif);
92+ }
93+
94+ uint GetFramesSinceLastAccess (uint currentFrameIdx, uint patchLastAccessFrame)
95+ {
96+ // Here we take into account that last access frame index is in [0, 2^16-1].
97+ // We use that the last frame index can never be later than current frame index.
98+ const uint modulo = 65536 ; // 2^16
99+ return ModuloDistance (
100+ currentFrameIdx % modulo,
101+ patchLastAccessFrame,
102+ modulo);
103+ }
104+
105+ void Reset (out PatchCounterSet set)
85106 {
86107 set.data = 0 ;
87108 }
88109
89110 uint GetUpdateCount (PatchCounterSet set)
90111 {
91- return set.data & 0xFFFF ;
112+ return set.data & 0xFF ;
113+ }
114+
115+ uint GetRank (PatchCounterSet set)
116+ {
117+ return (set.data & 0xFF00 ) >> 8 ;
118+ }
119+
120+ void SetRank (inout PatchCounterSet set, uint rank)
121+ {
122+ set.data = (rank << 8 ) | (set.data & 0xFFFF00FF );
92123 }
93124
94125 uint GetLastAccessFrame (PatchCounterSet set)
@@ -98,7 +129,7 @@ namespace PatchUtil
98129
99130 void SetUpdateCount (inout PatchCounterSet set, uint updateCount)
100131 {
101- set.data = updateCount | (set.data & 0xFFFF0000 );
132+ set.data = updateCount | (set.data & 0xFFFFFF00 );
102133 }
103134
104135 void SetLastAccessFrame (inout PatchCounterSet set, uint lastAccessFrame)
@@ -113,9 +144,9 @@ namespace PatchUtil
113144
114145 void WriteLastFrameAccess (RWStructuredBuffer <PatchUtil::PatchStatisticsSet> statisticsSets, uint patchIdx, uint frameIdx)
115146 {
116- PatchCounterSet counterSet = statisticsSets[patchIdx].patchCounters ;
147+ PatchCounterSet counterSet = statisticsSets[patchIdx].counters ;
117148 SetLastAccessFrame (counterSet, frameIdx);
118- statisticsSets[patchIdx].patchCounters = counterSet;
149+ statisticsSets[patchIdx].counters = counterSet;
119150 }
120151
121152 float GetVoxelSize (float voxelMinSize, uint cascadeIdx)
@@ -166,14 +197,14 @@ namespace PatchUtil
166197 {
167198 // To avoid discontinuities near the cardinal axis directions, we apply an arbitrary rotation.
168199 // This is based on the assumption that surfaces oriented along the cardinal axis directions
169- // are most likely in a scene compared to other directions.
200+ // are more likely in a scene compared to other directions.
170201 const float3x3 arbitraryRotation = float3x3 (
171202 float3 (0.34034f , -0.30925f , 0.888f ),
172203 float3 (-0.30925f , 0.85502f , 0.41629f ),
173204 float3 (-0.888f , -0.41629f , 0.19536f ));
174205 const float3 rotatedDirection = mul (arbitraryRotation, direction);
175206
176- const uint2 angularSquarePos = min (uint2 (3 , 3 ), SphereToSquare (rotatedDirection) * angularResolution);
207+ const uint2 angularSquarePos = min (uint2 (angularResolution - 1 , angularResolution - 1 ), SphereToSquare (rotatedDirection) * angularResolution);
177208 return angularSquarePos.y * angularResolution + angularSquarePos.x;
178209 }
179210
@@ -321,7 +352,7 @@ namespace PatchUtil
321352 return resultBool;
322353 }
323354
324- uint FindPatchIndex (VolumeParamSet volumeParams, StructuredBuffer< uint > cellPatchIndices, float3 worldPosition, float3 worldNormal)
355+ uint FindPatchIndex (VolumeParamSet volumeParams, CellPatchIndexBufferType cellPatchIndices, float3 worldPosition, float3 worldNormal)
325356 {
326357 VolumePositionResolution posResolution = ResolveVolumePosition (worldPosition, volumeParams);
327358 if (posResolution.isValid ())
@@ -345,7 +376,7 @@ namespace PatchUtil
345376 }
346377 }
347378
348- uint FindPatchIndexAndUpdateLastAccess (VolumeParamSet volumeParams, StructuredBuffer< uint > cellPatchIndices, RWStructuredBuffer <PatchUtil::PatchStatisticsSet> patchStatisticSets, float3 worldPosition, float3 worldNormal, uint frameIdx)
379+ uint FindPatchIndexAndUpdateLastAccess (VolumeParamSet volumeParams, CellPatchIndexBufferType cellPatchIndices, RWStructuredBuffer <PatchUtil::PatchStatisticsSet> patchStatisticSets, float3 worldPosition, float3 worldNormal, uint frameIdx)
349380 {
350381 const uint patchIdx = FindPatchIndex (volumeParams, cellPatchIndices, worldPosition, worldNormal);
351382 if (patchIdx != invalidPatchIndex)
@@ -384,12 +415,17 @@ namespace PatchUtil
384415 resultIrradiance);
385416 }
386417
418+ float3 EvalIrradiance (SphericalHarmonics::RGBL1 irradiance, float3 normal)
419+ {
420+ return max (0 , SphericalHarmonics::Eval (irradiance, normal));
421+ }
422+
387423 float3 ReadPlanarIrradiance (PatchIrradianceBufferType patchIrradiances, CellPatchIndexBufferType cellPatchIndices, uint spatialResolution, uint cascadeIdx, uint3 volumeSpacePosition, float3 worldNormal)
388424 {
389425 SphericalHarmonics::RGBL1 resultIrradiance;
390426 bool resultBool = ReadHemisphericalIrradiance (patchIrradiances, cellPatchIndices, spatialResolution, cascadeIdx, volumeSpacePosition, worldNormal, resultIrradiance);
391427 if (resultBool)
392- return max ( 0 , SphericalHarmonics:: Eval ( resultIrradiance, worldNormal) );
428+ return EvalIrradiance ( resultIrradiance, worldNormal);
393429 else
394430 return invalidIrradiance;
395431 }
@@ -420,20 +456,16 @@ namespace PatchUtil
420456
421457 PatchStatisticsSet InitPatchStatistics (float3 irradianceSeed, uint frameIndex, uint rank)
422458 {
423- PatchCounterSet counterSet;
424- Reset (counterSet);
425- PatchUtil::SetLastAccessFrame (counterSet, frameIndex);
426-
427459 PatchStatisticsSet stats;
428460 stats.mean = irradianceSeed;
429461 stats.variance = 0 ;
430- stats.patchCounters = counterSet;
431- stats.rank = rank;
462+ Reset (stats.counters);
463+ SetLastAccessFrame (stats.counters, frameIndex);
464+ SetRank (stats.counters, rank);
432465
433466 return stats;
434467 }
435468
436-
437469#if BOUNCE_PATCH_ALLOCATION
438470 void AllocatePatch (
439471 float3 worldPosition,
@@ -461,17 +493,17 @@ namespace PatchUtil
461493 allocParams.cellAllocationMarks,
462494 cellIdx);
463495
464- if (resolutionResult.code == PatchUtil::patchIndexResolutionCodeAllocationFailure || resolutionResult.code == PatchUtil::patchIndexResolutionCodeLookup )
465- return ;
466-
467- PatchUtil::PatchGeometry geo;
468- geo.position = worldPosition ;
469- geo.normal = worldNormal ;
470- patchGeometries[resolutionResult.patchIdx] = geo;
471-
472- SphericalHarmonics::RGBL1 irradianceSeed = (SphericalHarmonics::RGBL1) 0 ;
473- patchIrradiances [resolutionResult.patchIdx] = irradianceSeed;
474- patchStatistics[resolutionResult.patchIdx] = PatchUtil:: InitPatchStatistics (irradianceSeed.l0, frameIndex, /*rank*/ 1 );
496+ if (resolutionResult.code == PatchUtil::patchIndexResolutionCodeAllocationSuccess )
497+ {
498+ PatchUtil::PatchGeometry geo;
499+ geo.position = worldPosition ;
500+ geo.normal = worldNormal ;
501+ patchGeometries[resolutionResult.patchIdx] = geo ;
502+
503+ SphericalHarmonics::RGBL1 irradianceSeed = (SphericalHarmonics::RGBL1) 0 ;
504+ patchIrradiances[resolutionResult.patchIdx] = irradianceSeed ;
505+ patchStatistics [resolutionResult.patchIdx] = PatchUtil:: InitPatchStatistics ( irradianceSeed.l0, frameIndex, /*rank*/ 1 ) ;
506+ }
475507 }
476508#endif
477509}
0 commit comments