Skip to content

Commit

Permalink
Merge pull request #8049 from Unity-Technologies/internal/master
Browse files Browse the repository at this point in the history
Internal/master
  • Loading branch information
UnityAljosha authored Mar 25, 2024
2 parents 9b6c281 + f6b9768 commit 0279aa4
Show file tree
Hide file tree
Showing 467 changed files with 50,850 additions and 9,694 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,43 @@ void MainRayGenShader(

RayGenExecute(dispatchInfo);
}

#pragma kernel EncodeShadingDirection

StructuredBuffer<float3> _SkyShadingPrecomputedDirection;
StructuredBuffer<float3> _SkyShadingDirections;
RWStructuredBuffer<uint> _SkyShadingIndices;

uint _ProbeCount;

uint LinearSearchClosestDirection(float3 direction)
{
int indexMax = 255;
float bestDot = -10.0f;
int bestIndex = 0;

for (int index=0; index< indexMax; index++)
{
float currentDot = dot(direction, _SkyShadingPrecomputedDirection[index]);
if (currentDot > bestDot)
{
bestDot = currentDot;
bestIndex = index;
}
}
return bestIndex;
}

[numthreads(64, 1, 1)]
void EncodeShadingDirection(uint probeId : SV_DispatchThreadID)
{
if (probeId >= _ProbeCount)
return;

uint bestDirectionIndex = 255;
float norm = length(_SkyShadingDirections[probeId]);
if (norm > 0.0001f)
bestDirectionIndex = LinearSearchClosestDirection(_SkyShadingDirections[probeId] / norm);

_SkyShadingIndices[probeId] = bestDirectionIndex;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,8 @@ int _BackFaceCulling;
int _BakeSkyShadingDirection;

StructuredBuffer<float3> _ProbePositions;
StructuredBuffer<float3> _SkyShadingPrecomputedDirection;
RWStructuredBuffer<float4> _SkyOcclusionOut;
RWStructuredBuffer<float3> _SkyShadingOut;
RWStructuredBuffer<uint> _SkyShadingDirectionIndexOut;


uint LinearSearchClosestDirection(float3 direction)
{
int indexMax = 255;
float bestDot = -10.0f;
int bestIndex = 0;

for (int index=0; index< indexMax; index++)
{
float currentDot = dot(direction, _SkyShadingPrecomputedDirection[index]);
if (currentDot > bestDot)
{
bestDot = currentDot;
bestIndex = index;
}
}
return bestIndex;
}


void RayGenExecute(UnifiedRT::DispatchInfo dispatchInfo)
{
Expand Down Expand Up @@ -168,23 +146,5 @@ void RayGenExecute(UnifiedRT::DispatchInfo dispatchInfo)
// The 1.125f exponent comes from experimental testing. It's the value that works the best when trying to match a bake and deringing done with the lightmapper, but it has no theoretical explanation.
// In the future, we should replace these custom windowing and deringing operations with the ones used in the lightmapper to implement a more academical solution.
_SkyOcclusionOut[probeId].yzw *= lerp(1.0f, radianceToIrradianceFactor, pow(windowL1, 1.125f));


// Normalize computed direction
if (_BakeSkyShadingDirection > 0)
{
uint bestDirectionIndex = 255;
float norm = length(_SkyShadingOut[probeId]);
if (norm > 0.0001f)
{
_SkyShadingOut[probeId] /= norm;
bestDirectionIndex = LinearSearchClosestDirection(_SkyShadingOut[probeId]);
}
else
{
_SkyShadingOut[probeId] = float3(0.0f, 0.0f, 0.0f);
}
_SkyShadingDirectionIndexOut[probeId] = bestDirectionIndex;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ static void DrawBakingHelpers(SerializedProbeAdjustmentVolume p, Editor owner)
using (new EditorGUI.DisabledScope(bakingSet == null))
{
if (GUILayout.Button(Styles.s_PreviewLighting))
ProbeGIBaking.BakeAdjustmentVolume(bakingSet, ptv);
AdaptiveProbeVolumes.BakeAdjustmentVolume(bakingSet, ptv);

ProbeVolumeLightingTab.BakeAPVButton();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System.Collections.Generic;
using UnityEditor;

using Cell = UnityEngine.Rendering.ProbeReferenceVolume.Cell;

namespace UnityEngine.Rendering
{
partial class ProbeGIBaking
partial class AdaptiveProbeVolumes
{
static ComputeShader dilationShader;
static int dilationKernel = -1;
Expand All @@ -16,6 +19,13 @@ static void InitDilationShaders()
}
}

static void GetProbeAndChunkIndex(int globalProbeIndex, out int chunkIndex, out int chunkProbeIndex)
{
var chunkSizeInProbeCount = ProbeBrickPool.GetChunkSizeInProbeCount();
chunkIndex = globalProbeIndex / chunkSizeInProbeCount;
chunkProbeIndex = globalProbeIndex - chunkIndex * chunkSizeInProbeCount;
}

[GenerateHLSL(needAccessors = false)]
struct DilatedProbe
{
Expand Down Expand Up @@ -97,10 +107,7 @@ internal void ToSphericalHarmonicsShaderConstants(ProbeReferenceVolume.Cell cell
if (cellChunkData.skyOcclusionDataL0L1.Length != 0)
WriteToShaderSkyOcclusion(SO_L0L1, cellChunkData.skyOcclusionDataL0L1, index * 4);
if (cellChunkData.skyShadingDirectionIndices.Length != 0)
{
var directions = DynamicSkyPrecomputedDirections.GetPrecomputedDirections();
cellChunkData.skyShadingDirectionIndices[index] = (byte)LinearSearchClosestDirection(directions, SO_Direction);
}
cellChunkData.skyShadingDirectionIndices[index] = (byte)SkyOcclusionBaker.EncodeSkyShadingDirection(SO_Direction);
}
}

Expand Down Expand Up @@ -167,6 +174,112 @@ public void Dispose()
static readonly int _DilationParameters2 = Shader.PropertyToID("_DilationParameters2");
static readonly int _OutputProbes = Shader.PropertyToID("_OutputProbes");

// Can definitively be optimized later on.
// Also note that all the bookkeeping of all the reference volumes will likely need to change when we move to
// proper UX.
internal static void PerformDilation()
{
var prv = ProbeReferenceVolume.instance;
var perSceneDataList = prv.perSceneDataList;
if (perSceneDataList.Count == 0) return;
SetBakingContext(perSceneDataList);

List<Cell> tempLoadedCells = new List<Cell>();

if (m_BakingSet.hasDilation)
{
var dilationSettings = m_BakingSet.settings.dilationSettings;

// Make sure all assets are loaded.
prv.PerformPendingOperations();

// TODO: This loop is very naive, can be optimized, but let's first verify if we indeed want this or not.
for (int iterations = 0; iterations < dilationSettings.dilationIterations; ++iterations)
{
// Try to load all available cells to the GPU. Might not succeed depending on the memory budget.
prv.LoadAllCells();

// Dilate all cells
List<Cell> dilatedCells = new List<Cell>(prv.cells.Values.Count);
bool everythingLoaded = !prv.hasUnloadedCells;

if (everythingLoaded)
{
foreach (var cell in prv.cells.Values)
{
if (m_CellsToDilate.ContainsKey(cell.desc.index))
{
PerformDilation(cell, m_BakingSet);
dilatedCells.Add(cell);
}
}
}
else
{
// When everything does not fit in memory, we are going to dilate one cell at a time.
// To do so, we load the cell and all its neighbours and then dilate.
// This is an inefficient use of memory but for now most of the time is spent in reading back the result anyway so it does not introduce any performance regression.

// Free All memory to make room for each cell and its neighbors for dilation.
prv.UnloadAllCells();

foreach (var cell in prv.cells.Values)
{
if (!m_CellsToDilate.ContainsKey(cell.desc.index))
continue;

var cellPos = cell.desc.position;
// Load the cell and all its neighbors before doing dilation.
for (int x = -1; x <= 1; ++x)
{
for (int y = -1; y <= 1; ++y)
{
for (int z = -1; z <= 1; ++z)
{
Vector3Int pos = cellPos + new Vector3Int(x, y, z);
if (m_CellPosToIndex.TryGetValue(pos, out var cellToLoadIndex))
{
if (prv.cells.TryGetValue(cellToLoadIndex, out var cellToLoad))
{
if (prv.LoadCell(cellToLoad))
{
tempLoadedCells.Add(cellToLoad);
}
else
Debug.LogError($"Not enough memory to perform dilation for cell {cell.desc.index}");
}
}
}
}
}

PerformDilation(cell, m_BakingSet);
dilatedCells.Add(cell);

// Free memory again.
foreach (var cellToUnload in tempLoadedCells)
prv.UnloadCell(cellToUnload);
tempLoadedCells.Clear();
}
}

// Now write back the assets.
WriteDilatedCells(dilatedCells);

AssetDatabase.SaveAssets();
AssetDatabase.Refresh();

// Reload data
foreach (var sceneData in perSceneDataList)
{
sceneData.QueueSceneRemoval();
sceneData.QueueSceneLoading();
}
prv.PerformPendingOperations();
}
}
}

static void PerformDilation(ProbeReferenceVolume.Cell cell, ProbeVolumeBakingSet bakingSet)
{
InitDilationShaders();
Expand Down Expand Up @@ -235,5 +348,36 @@ static void PerformDilation(ProbeReferenceVolume.Cell cell, ProbeVolumeBakingSet
data.ExtractDilatedProbes();
data.Dispose();
}

// NOTE: This is somewhat hacky and is going to likely be slow (or at least slower than it could).
// It is only a first iteration of the concept that won't be as impactful on memory as other options.
internal static void RevertDilation()
{
if (m_BakingSet == null)
{
if (ProbeReferenceVolume.instance.perSceneDataList.Count == 0) return;
SetBakingContext(ProbeReferenceVolume.instance.perSceneDataList);
}

var dilationSettings = m_BakingSet.settings.dilationSettings;
var blackProbe = new SphericalHarmonicsL2();

int chunkSizeInProbes = ProbeBrickPool.GetChunkSizeInProbeCount();
foreach (var cell in ProbeReferenceVolume.instance.cells.Values)
{
for (int i = 0; i < cell.data.validity.Length; ++i)
{
if (dilationSettings.enableDilation && dilationSettings.dilationDistance > 0.0f && cell.data.validity[i] > dilationSettings.dilationValidityThreshold)
{
GetProbeAndChunkIndex(i, out var chunkIndex, out var index);

var cellChunkData = GetCellChunkData(cell.data, chunkIndex);

WriteToShaderCoeffsL0L1(blackProbe, cellChunkData.shL0L1RxData, cellChunkData.shL1GL1RyData, cellChunkData.shL1BL1RzData, index * 4);
WriteToShaderCoeffsL2(blackProbe, cellChunkData.shL2Data_0, cellChunkData.shL2Data_1, cellChunkData.shL2Data_2, cellChunkData.shL2Data_3, index * 4);
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using System;

namespace UnityEngine.Rendering
{
partial class ProbeGIBaking
partial class AdaptiveProbeVolumes
{
// We use this scratch memory as a way of spoofing the texture.
static DynamicArray<float> s_Validity_locData = new DynamicArray<float>();
Expand Down
Loading

0 comments on commit 0279aa4

Please sign in to comment.