Skip to content

Hdrp/reflection probe scale perf #252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
May 7, 2020
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.Rendering;
using UnityEngine.TestTools;
using NUnit.Framework;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Threading;
using Unity.PerformanceTesting;
using UnityEditor.Rendering.HighDefinition;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using static PerformanceTestUtils;
using static PerformanceMetricNames;

public class HDReflectionSystemTests : EditorPerformanceTests
{
[Version("1"), Test, Performance]
public void HDProbeSystemRegister()
{
using (ListPool<HDProbe>.Get(out var probes))
{
// Create a lot of probe
for (var i = 0; i < 10000; ++i)
{
var gameObject = new GameObject(i.ToString("0000"));
// Deactivate the GameObject to avoid OnEnable calls (which register the probe)
gameObject.SetActive(false);
gameObject.AddComponent<ReflectionProbe>();
var probe = gameObject.AddComponent<HDAdditionalReflectionData>();
probe.enabled = false;
probes.Add(probe);
}

// Measure registration
Measure.Method(() =>
{
foreach (var probe in probes)
HDProbeSystem.RegisterProbe(probe);
}).Run();

// Unregister
foreach (var probe in probes)
HDProbeSystem.UnregisterProbe(probe);

// Delete the probes
foreach (var probe in probes)
Object.DestroyImmediate(probe.gameObject);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions com.unity.render-pipelines.high-definition/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Use multi_compile API for deferred compute shader with shadow mask.
- Made the StaticLightingSky class public so that users can change it by script for baking purpose.
- Shadowmask and realtime reflectoin probe property are hide in Quality settings
- Improved performance of reflection probe management when using a lot of probes.

## [7.1.1] - 2019-09-05

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,26 +131,27 @@ IScriptableBakedReflectionSystemStageNotifier handle
HashUtilities.AppendHash(ref skySettingsHash, ref allProbeDependencyHash);

var bakedProbes = HDProbeSystem.bakedProbes;
var bakedProbeCount = HDProbeSystem.bakedProbeCount;

// == 2. ==
var states = stackalloc HDProbeBakingState[bakedProbes.Count];
var states = stackalloc HDProbeBakingState[bakedProbeCount];
ComputeProbeInstanceID(bakedProbes, states);
ComputeProbeSettingsHashes(bakedProbes, states);
// TODO: Handle bounce dependency here
ComputeProbeBakingHashes(bakedProbes.Count, allProbeDependencyHash, states);
ComputeProbeBakingHashes(bakedProbeCount, allProbeDependencyHash, states);

CoreUnsafeUtils.QuickSort<HDProbeBakingState, Hash128, HDProbeBakingState.ProbeBakingHash>(
bakedProbes.Count, states
bakedProbeCount, states
);

int operationCount = 0, addCount = 0, remCount = 0;
var maxProbeCount = Mathf.Max(bakedProbes.Count, m_HDProbeBakedStates.Length);
var maxProbeCount = Mathf.Max(bakedProbeCount, m_HDProbeBakedStates.Length);
var addIndices = stackalloc int[maxProbeCount];
var remIndices = stackalloc int[maxProbeCount];

if (m_HDProbeBakedStates.Length == 0)
{
for (int i = 0; i < bakedProbes.Count; ++i)
for (int i = 0; i < bakedProbeCount; ++i)
addIndices[addCount++] = i;
operationCount = addCount;
}
Expand All @@ -165,7 +166,7 @@ IScriptableBakedReflectionSystemStageNotifier handle
HDProbeBakingState, HDProbeBakingState.ProbeBakingHash
> (
m_HDProbeBakedStates.Length, oldBakedStates, // old hashes
bakedProbes.Count, states, // new hashes
bakedProbeCount, states, // new hashes
addIndices, remIndices,
out addCount, out remCount
);
Expand Down Expand Up @@ -202,7 +203,7 @@ IScriptableBakedReflectionSystemStageNotifier handle
// Get from cache or render the probe
if (!File.Exists(cacheFile))
RenderAndWriteToFile(probe, cacheFile, cubeRT, planarRT);

planarRT.Release();
}
cubeRT.Release();
Expand Down Expand Up @@ -232,7 +233,7 @@ IScriptableBakedReflectionSystemStageNotifier handle
for (int j = 0; j < 2; ++j)
{
AssetDatabase.StartAssetEditing();
for (int i = 0; i < bakedProbes.Count; ++i)
for (int i = 0; i < bakedProbeCount; ++i)
{
var index = addIndices[i];
var instanceId = states[index].instanceID;
Expand Down Expand Up @@ -312,7 +313,7 @@ IScriptableBakedReflectionSystemStageNotifier handle
handle.SetIsDone(true);
}

public static bool BakeProbes(IList<HDProbe> bakedProbes)
public static bool BakeProbes(IEnumerable<HDProbe> bakedProbes)
{
if (!(RenderPipelineManager.currentPipeline is HDRenderPipeline hdPipeline))
{
Expand All @@ -326,9 +327,8 @@ public static bool BakeProbes(IList<HDProbe> bakedProbes)
var cubeRT = HDRenderUtilities.CreateReflectionProbeRenderTarget(cubemapSize);

// Render and write the result to disk
for (int i = 0; i < bakedProbes.Count; ++i)
foreach (var probe in bakedProbes)
{
var probe = bakedProbes[i];
var bakedTexturePath = HDBakingUtilities.GetBakedTextureFilePath(probe);
var planarRT = HDRenderUtilities.CreatePlanarProbeRenderTarget((int)probe.resolution);
RenderAndWriteToFile(probe, bakedTexturePath, cubeRT, planarRT);
Expand All @@ -342,9 +342,8 @@ public static bool BakeProbes(IList<HDProbe> bakedProbes)
for (int j = 0; j < 2; ++j)
{
AssetDatabase.StartAssetEditing();
for (int i = 0; i < bakedProbes.Count; ++i)
foreach (var probe in bakedProbes)
{
var probe = bakedProbes[i];
var bakedTexturePath = HDBakingUtilities.GetBakedTextureFilePath(probe);
AssetDatabase.ImportAsset(bakedTexturePath);
ImportAssetAt(probe, bakedTexturePath);
Expand All @@ -353,9 +352,8 @@ public static bool BakeProbes(IList<HDProbe> bakedProbes)
}

AssetDatabase.StartAssetEditing();
for (int i = 0; i < bakedProbes.Count; ++i)
foreach (var probe in bakedProbes)
{
var probe = bakedProbes[i];
var bakedTexturePath = HDBakingUtilities.GetBakedTextureFilePath(probe);

// Get or create the baked texture asset for the probe
Expand All @@ -379,9 +377,8 @@ public static bool BakeProbes(IList<HDProbe> bakedProbes)
// updateCount is a transient data, so don't execute this code before the asset reload.
{
UnityEngine.Random.InitState((int)(1000 * hdPipeline.GetTime()));
for (int i = 0; i < bakedProbes.Count; ++i)
foreach (var probe in bakedProbes)
{
var probe = bakedProbes[i];
var c = UnityEngine.Random.Range(2, 10);
while (probe.texture.updateCount < c) probe.texture.IncrementUpdateCount();
}
Expand Down Expand Up @@ -663,23 +660,28 @@ string GetGICacheFileForHDProbe(Hash128 hash)
return Path.Combine(hashFolder, string.Format("HDProbe-{0}.exr", hash));
}

static void ComputeProbeInstanceID(IList<HDProbe> probes, HDProbeBakingState* states)
static void ComputeProbeInstanceID(IEnumerable<HDProbe> probes, HDProbeBakingState* states)
{
for (int i = 0; i < probes.Count; ++i)
states[i].instanceID = probes[i].GetInstanceID();
var i = 0;
foreach (var probe in probes)
{
states[i].instanceID = probe.GetInstanceID();
++i;
}
}

static void ComputeProbeSettingsHashes(IList<HDProbe> probes, HDProbeBakingState* states)
static void ComputeProbeSettingsHashes(IEnumerable<HDProbe> probes, HDProbeBakingState* states)
{
for (int i = 0; i < probes.Count; ++i)
var i = 0;
foreach (var probe in probes)
{
var probe = probes[i];
var positionSettings = ProbeCapturePositionSettings.ComputeFrom(probe, null);
var positionSettingsHash = positionSettings.ComputeHash();
// TODO: make ProbeSettings and unmanaged type so its hash can be the hash of its memory
var probeSettingsHash = probe.settings.ComputeHash();
HashUtilities.AppendHash(ref positionSettingsHash, ref probeSettingsHash);
states[i].probeSettingsHash = probeSettingsHash;
++i;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ struct HDProbeCullingResults
List<HDProbe> m_VisibleProbes;

public IReadOnlyList<HDProbe> visibleProbes => m_VisibleProbes ?? s_EmptyList;
internal List<HDProbe> writeableVisibleProbes => m_VisibleProbes;

internal void Reset()
{
Expand All @@ -20,11 +19,11 @@ internal void Reset()
m_VisibleProbes.Clear();
}

internal void Set(List<HDProbe> visibleProbes)
internal void AddProbe(HDProbe visibleProbes)
{
Assert.IsNotNull(m_VisibleProbes);

m_VisibleProbes.AddRange(visibleProbes);
m_VisibleProbes.Add(visibleProbes);
}
}
}
Loading