Skip to content

Commit 6cfe0d6

Browse files
committed
Probe Volumes: Make all bake requests go through the AdditionalGIBakeRequestsManager. Track the generationIndex in the least significant 8 bits of the lightmapperBakeID, and talk to the lightmapper with this composite ID. This ensures that anytime we call SetAdditionalBakeProbes we generate a completely unique bake request from the perspective of the lightmapper, ensuring that we will always bake this data (because the lightmapper will hash these IDs to determine if it has any work to do). Previously, if we set an ID with new data, or if we cleared an ID then set it with new data, the lightmapper wouldnt track these data changes, and so it would skip baking these actually new bake requests. (#17)
Co-authored-by: pastasfuture <nickb@bonfirestudios.com>
1 parent a2479ad commit 6cfe0d6

File tree

2 files changed

+74
-20
lines changed

2 files changed

+74
-20
lines changed

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

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ namespace UnityEngine.Rendering.HighDefinition
1414
public class AdditionalGIBakeRequestsManager
1515
{
1616
// The baking ID for the extra requests
17-
internal static readonly int s_BakingID = int.MaxValue;
17+
private static int s_AdditionalGIBakeRequestsBakingID = 0;
18+
private static readonly int s_LightmapperBakeIDStart = 1;
1819

1920
private static AdditionalGIBakeRequestsManager s_Instance = new AdditionalGIBakeRequestsManager();
2021
/// <summary>
@@ -56,32 +57,90 @@ private AdditionalGIBakeRequestsManager()
5657
// Rather than hashing and hoping we don't collide, lets handle this robustly by
5758
// keeping a dictionary of ProbeVolumeGlobalUniqueID->int bit keys.
5859
private Dictionary<ProbeVolumeGlobalUniqueID, int> lightmapperBakeIDFromBakeID = new Dictionary<ProbeVolumeGlobalUniqueID, int>(32);
59-
private int lightmapperBakeIDNext = 0;
60+
private int lightmapperBakeIDNext = s_LightmapperBakeIDStart;
6061

61-
internal bool TryGetLightmapperBakeIDFromBakeID(ProbeVolumeGlobalUniqueID bakeID, out int lightmapperBakeID)
62+
internal void SetAdditionalBakedProbes(ProbeVolumeGlobalUniqueID bakeID, Vector3[] positions)
63+
{
64+
if (TryGetLightmapperBakeIDFromBakeID(bakeID, out int lightmapperBakeID))
65+
{
66+
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(lightmapperBakeID, null);
67+
68+
// When baking, the lightmapper hashes its state (i.e: the list of all AdditionalBakedProbes requests)
69+
// and only bakes data if this hash is not changed.
70+
// By storing a generation ID inside of our lightmapperBakeID, we ensure that Sets will always look like a completely new bake request to the lightmapper.
71+
// The lightmapper will always bake it.
72+
// Without storing this generation index, if we clear our bake request by setting positions to NULL, then set our bake request with valid data,
73+
// then bake, the lightmapper will treat the new bake request as an already completed old one, and skip doing any work.
74+
// In the future, after proving out this generation based approach, it would be a good idea to move this generation tracking code into the lightmapper,
75+
// so that users dont need to do this bookkeeping for the lightmapper - they can simply set and clear requests and always get the correct, fresh results.
76+
IncrementLightmapperBakeIDGeneration(bakeID, out lightmapperBakeID);
77+
78+
if (positions != null)
79+
{
80+
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(lightmapperBakeID, positions);
81+
}
82+
}
83+
}
84+
85+
internal bool GetAdditionalBakedProbes(ProbeVolumeGlobalUniqueID bakeID, NativeArray<SphericalHarmonicsL2> outBakedProbeSH, NativeArray<float> outBakedProbeValidity, NativeArray<float> outBakedProbeOctahedralDepth)
86+
{
87+
bool success = false;
88+
if (TryGetLightmapperBakeIDFromBakeID(bakeID, out int lightmapperBakeID))
89+
{
90+
success = UnityEditor.Experimental.Lightmapping.GetAdditionalBakedProbes(lightmapperBakeID, outBakedProbeSH, outBakedProbeValidity, outBakedProbeOctahedralDepth);
91+
}
92+
return success;
93+
}
94+
95+
private bool TryGetLightmapperBakeIDFromBakeID(ProbeVolumeGlobalUniqueID bakeID, out int lightmapperBakeID)
6296
{
6397
bool success = false;
6498
if (lightmapperBakeIDFromBakeID.TryGetValue(bakeID, out lightmapperBakeID))
6599
{
66100
success = true;
67101
}
68-
else if (lightmapperBakeIDNext == s_BakingID)
102+
// Leave the whole top bit free. We shouldn't encounter it in practice, avoiding it allows us to not worry about handling the signed case.
103+
else if (lightmapperBakeIDNext == ((1 << 23) - 1))
69104
{
70105
success = false;
71106
lightmapperBakeID = -1;
72-
Debug.LogWarningFormat("Error: Used up all lightmapper bake IDs. This should never happen. Somehow all {0} ids have been used up. This must be the result of a bug. Unlikely that you created and baked {0} unique bake requests. Quit and reopen unity to flush all IDs.", s_BakingID - 1);
107+
Debug.LogWarningFormat("Error: Used up all lightmapper bake IDs. This should never happen. Somehow all {0} ids have been used up. This must be the result of a bug. Unlikely that you created and baked {0} unique bake requests. Quit and reopen unity to flush all IDs.", (1 << 23) - 1);
73108
}
74109
else
75110
{
76111
success = true;
77-
lightmapperBakeID = lightmapperBakeIDNext;
112+
lightmapperBakeID = lightmapperBakeIDNext << 8;
78113
++lightmapperBakeIDNext;
79114
lightmapperBakeIDFromBakeID.Add(bakeID, lightmapperBakeID);
80115
}
81116

82117
return success;
83118
}
84119

120+
private void IncrementLightmapperBakeIDGeneration(ProbeVolumeGlobalUniqueID bakeID, out int lightmapperBakeID)
121+
{
122+
lightmapperBakeID = -1;
123+
if (lightmapperBakeIDFromBakeID.TryGetValue(bakeID, out lightmapperBakeID))
124+
{
125+
IncrementLightmapperBakeIDGeneration(ref lightmapperBakeID);
126+
lightmapperBakeIDFromBakeID[bakeID] = lightmapperBakeID;
127+
}
128+
else
129+
{
130+
Debug.Assert(false);
131+
}
132+
}
133+
134+
private static void IncrementLightmapperBakeIDGeneration(ref int lightmapperBakeID)
135+
{
136+
const int MASK = 255;
137+
int generationIndex = lightmapperBakeID & MASK;
138+
generationIndex = (generationIndex == MASK) ? 0 : (generationIndex + 1);
139+
140+
lightmapperBakeID &= ~MASK;
141+
lightmapperBakeID |= generationIndex;
142+
}
143+
85144
/// <summary>
86145
/// Enqueue a request for probe rendering at the specified location.
87146
/// </summary>
@@ -214,7 +273,9 @@ internal void AddRequestsToLightmapper()
214273

215274
EnsureRequestPositionsSanitized();
216275

217-
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(s_BakingID, m_RequestPositionsSanitized);
276+
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(s_AdditionalGIBakeRequestsBakingID, null);
277+
IncrementLightmapperBakeIDGeneration(ref s_AdditionalGIBakeRequestsBakingID);
278+
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(s_AdditionalGIBakeRequestsBakingID, m_RequestPositionsSanitized);
218279
m_RequestToLightmapperIsSet = true;
219280

220281
UnityEditor.Experimental.Lightmapping.additionalBakedProbesCompleted -= OnAdditionalProbesBakeCompleted;
@@ -223,7 +284,7 @@ internal void AddRequestsToLightmapper()
223284

224285
private void RemoveRequestsFromLightmapper()
225286
{
226-
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(s_BakingID, null);
287+
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(s_AdditionalGIBakeRequestsBakingID, null);
227288
m_RequestToLightmapperIsSet = false;
228289
}
229290

@@ -237,7 +298,7 @@ private void OnAdditionalProbesBakeCompleted()
237298
var validity = new NativeArray<float>(m_RequestPositions.Count, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
238299
var bakedProbeOctahedralDepth = new NativeArray<float>(m_RequestPositions.Count * 64, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
239300

240-
if (UnityEditor.Experimental.Lightmapping.GetAdditionalBakedProbes(s_BakingID, sh, validity, bakedProbeOctahedralDepth))
301+
if (UnityEditor.Experimental.Lightmapping.GetAdditionalBakedProbes(s_AdditionalGIBakeRequestsBakingID, sh, validity, bakedProbeOctahedralDepth))
241302
{
242303
SetSHCoefficients(sh);
243304
PushSHCoefficientsToReflectionProbes();

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

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,10 +1245,7 @@ internal void ForceBakingDisabled()
12451245
if (!UnityEditor.EditorApplication.isPlaying)
12461246
{
12471247
// Do not spend time interacting with the baking API if we are in playmode.
1248-
if (AdditionalGIBakeRequestsManager.instance.TryGetLightmapperBakeIDFromBakeID(GetBakeID(), out int lightmapperBakeID))
1249-
{
1250-
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(lightmapperBakeID, null);
1251-
}
1248+
AdditionalGIBakeRequestsManager.instance.SetAdditionalBakedProbes(GetBakeID(), null);
12521249
return;
12531250
}
12541251
}
@@ -1359,8 +1356,7 @@ internal void OnProbesBakeCompleted()
13591356
#else
13601357
var octahedralDepth = new NativeArray<float>(numProbes * 8 * 8, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
13611358
#endif
1362-
bool lightmapperBakeIDExists = AdditionalGIBakeRequestsManager.instance.TryGetLightmapperBakeIDFromBakeID(GetBakeID(), out int lightmapperBakeID);
1363-
if(lightmapperBakeIDExists && UnityEditor.Experimental.Lightmapping.GetAdditionalBakedProbes(lightmapperBakeID, sh, validity, octahedralDepth))
1359+
if(AdditionalGIBakeRequestsManager.instance.GetAdditionalBakedProbes(GetBakeID(), sh, validity, octahedralDepth))
13641360
{
13651361
if (probeVolumeAsset == null)
13661362
{
@@ -1419,7 +1415,7 @@ internal void OnProbesBakeCompleted()
14191415
string parentName = (transform.parent == null) ? "null" : transform.parent.name;
14201416
bool isCompanionGameObject = gameObject.scene.path == "";
14211417
string companionString = isCompanionGameObject ? "true" : "false";
1422-
Debug.LogFormat("Failed to get data at id: {0}, with lightmapperBakeID {1}, with probe volume: {2}, and parent: {3}, companionGameObject: {4}", GetBakeID(), lightmapperBakeID, name, parentName, companionString);
1418+
Debug.LogFormat("Failed to get data at id: {0}, with probe volume: {1}, and parent: {2}, companionGameObject: {3}", GetBakeID(), name, parentName, companionString);
14231419
}
14241420

14251421
sh.Dispose();
@@ -1499,9 +1495,6 @@ private void SetupProbePositions()
14991495
if (UnityEditor.EditorApplication.isPlaying)
15001496
return;
15011497

1502-
if (!AdditionalGIBakeRequestsManager.instance.TryGetLightmapperBakeIDFromBakeID(GetBakeID(), out int lightmapperBakeID))
1503-
return;
1504-
15051498
int probeCount = parameters.resolutionX * parameters.resolutionY * parameters.resolutionZ;
15061499
m_ProbePositions = new Vector3[probeCount];
15071500

@@ -1529,7 +1522,7 @@ private void SetupProbePositions()
15291522
}
15301523
}
15311524

1532-
UnityEditor.Experimental.Lightmapping.SetAdditionalBakedProbes(lightmapperBakeID, m_ProbePositions);
1525+
AdditionalGIBakeRequestsManager.instance.SetAdditionalBakedProbes(GetBakeID(), m_ProbePositions);
15331526
bakingEnabled = true;
15341527
}
15351528

0 commit comments

Comments
 (0)