Browse Source

Merge branch 'master' into ww1dev/hdrp17/staging

# Conflicts:
#	Packages/com.unity.rendering.light-transport/Runtime/UnifiedRayTracing/Common/TerrainToMesh.cs
#	Packages/com.unity.rendering.light-transport/Tests/Editor/UnifiedRayTracing/AccelStructTests.cs
#	Packages/com.unity.rendering.light-transport/package.json
ww1dev/hdrp17/staging
Nico de Poel 6 months ago
parent
commit
c1ceeb1d32
  1. 19
      Packages/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentEditor.cs
  2. 5
      Packages/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentListEditor.cs
  3. 156
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/Debug/DebugDisplayGPUResidentDrawer.cs
  4. 132
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawer.cs
  5. 80
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawerBurst.cs
  6. 2
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawerBurst.cs.meta
  7. 49
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawerDebug.cs
  8. 75
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCuller.cs
  9. 19
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCullerBurst.cs
  10. 2
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCullerBurst.cs.meta
  11. 278
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCullingBatcher.cs
  12. 301
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCullingBatcherBurst.cs
  13. 2
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCullingBatcherBurst.cs.meta
  14. 207
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceData/InstanceDataSystem.Jobs.cs
  15. 17
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceData/InstanceDataSystem.cs
  16. 191
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceData/InstanceDataSystemBurst.cs
  17. 2
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceData/InstanceDataSystemBurst.cs.meta
  18. 10
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceOcclusionCuller.cs
  19. 10
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceOcclusionCuller.cs.hlsl
  20. 106
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/LODGroupDataPool.cs
  21. 72
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/LODGroupDataPoolBurst.cs
  22. 2
      Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/LODGroupDataPoolBurst.cs.meta
  23. 3
      Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs
  24. 1
      Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.hlsl
  25. 4
      Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs
  26. 1
      Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/LensFlareDataSRP.cs
  27. 4
      Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/IRenderGraphBuilder.cs
  28. 21
      Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs
  29. 22
      Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilders.cs
  30. 49
      Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphUtilsBlit.cs
  31. 29
      Packages/com.unity.render-pipelines.core/Runtime/RenderPipelineResources/GPUDriven/InstanceOcclusionCullingKernels.compute
  32. 45
      Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeManager.cs
  33. 18
      Packages/com.unity.render-pipelines.core/Runtime/XR/XRPass.cs
  34. 1
      Packages/com.unity.render-pipelines.core/Runtime/XR/XRSystem.cs
  35. 2
      Packages/com.unity.render-pipelines.core/package.json
  36. 64
      Packages/com.unity.render-pipelines.high-definition/Editor/Material/Decal/DecalProjectorEditor.cs
  37. 4
      Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/FogVolumePropertyBlock.cs
  38. 8
      Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/FogVolumeSubTarget.cs
  39. 2
      Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/OverdrawDebug.hlsl
  40. 2
      Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/ShaderPassPreview.hlsl
  41. 13
      Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/ShaderPassVoxelize.hlsl
  42. 36
      Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/VoxelizationTransforms.hlsl
  43. 7
      Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/VoxelizationTransforms.hlsl.meta
  44. 8
      Packages/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/Templates/Pixel.template.hlsl
  45. 6
      Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs
  46. 3
      Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs
  47. 3
      Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingLightLoop.hlsl
  48. 3
      Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs
  49. 3
      Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl
  50. 58
      Packages/com.unity.render-pipelines.high-definition/Runtime/Sky/SkyManager.cs
  51. 2
      Packages/com.unity.render-pipelines.high-definition/package.json
  52. 53
      Packages/com.unity.rendering.light-transport/Runtime/UnifiedRayTracing/Common/TerrainToMesh.cs
  53. 1
      Packages/com.unity.rendering.light-transport/Tests/Editor/UnifiedRayTracing/AccelStructTests.cs
  54. 2
      Packages/com.unity.rendering.light-transport/package.json
  55. 2
      Packages/com.unity.shadergraph/package.json
  56. 16
      Packages/com.unity.ugui/Runtime/UGUI/UI/Core/Image.cs
  57. 1
      Packages/com.unity.ugui/Runtime/UGUI/UI/Core/Slider.cs
  58. 2
      Packages/com.unity.ugui/package.json
  59. 1
      Packages/com.unity.visualeffectgraph/Editor/Inspector/VFXSlotContainerEditor.cs
  60. 2
      Packages/com.unity.visualeffectgraph/package.json

19
Packages/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentEditor.cs

@ -279,13 +279,6 @@ namespace UnityEditor.Rendering
var supportedOn = volumeComponentType.GetCustomAttribute<VolumeComponentMenuForRenderPipeline>();
m_LegacyPipelineTypes = supportedOn != null ? supportedOn.pipelineTypes : Array.Empty<Type>();
#pragma warning restore CS0618
EditorApplication.contextualPropertyMenu += OnPropertyContextMenu;
}
void OnDestroy()
{
EditorApplication.contextualPropertyMenu -= OnPropertyContextMenu;
}
internal void DetermineVisibility(Type renderPipelineAssetType, Type renderPipelineType)
@ -393,23 +386,13 @@ namespace UnityEditor.Rendering
profile != null &&
defaultProfile != profile)
{
menu.AddSeparator(string.Empty);
menu.AddItem(EditorGUIUtility.TrTextContent($"Show Default Volume Profile"), false,
() => Selection.activeObject = defaultProfile);
menu.AddItem(EditorGUIUtility.TrTextContent($"Apply Values to Default Volume Profile"), false, copyAction);
}
}
void OnPropertyContextMenu(GenericMenu menu, SerializedProperty property)
{
if (property.serializedObject.targetObject != target)
return;
var targetComponent = property.serializedObject.targetObject as VolumeComponent;
AddDefaultProfileContextMenuEntries(menu, VolumeManager.instance.globalDefaultProfile,
() => VolumeProfileUtils.AssignValuesToProfile(VolumeManager.instance.globalDefaultProfile, targetComponent, property));
}
/// <summary>
/// Unity calls this method after drawing the header for each VolumeComponentEditor
/// </summary>

5
Packages/com.unity.render-pipelines.core/Editor/Volume/VolumeComponentListEditor.cs

@ -445,13 +445,14 @@ namespace UnityEditor.Rendering
if (!m_IsDefaultVolumeProfile)
menu.AddItem(EditorGUIUtility.TrTextContent("Remove"), false, () => RemoveComponent(id));
menu.AddSeparator(string.Empty);
if (targetEditor.hasAdditionalProperties)
{
menu.AddSeparator(string.Empty);
menu.AddAdvancedPropertiesBoolMenuItem(() => targetEditor.showAdditionalProperties,
() => targetEditor.showAdditionalProperties ^= true);
}
menu.AddSeparator(string.Empty);
targetEditor.AddDefaultProfileContextMenuEntries(menu, VolumeManager.instance.globalDefaultProfile,
() => VolumeProfileUtils.CopyValuesToProfile(targetComponent, VolumeManager.instance.globalDefaultProfile));

156
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/Debug/DebugDisplayGPUResidentDrawer.cs

@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using Unity.Collections;
#if UNITY_EDITOR
using UnityEditor;
#endif
using static UnityEngine.Rendering.DebugUI;
using static UnityEngine.Rendering.DebugUI.Widget;
@ -106,6 +109,7 @@ namespace UnityEngine.Rendering
else
return new InstanceOcclusionEventStats();
}
static class Strings
{
public const string drawerSettingsContainerName = "GPU Resident Drawer Settings";
@ -144,6 +148,7 @@ namespace UnityEngine.Rendering
{
return GPUResidentDrawer.GetDebugStats()?.instanceOcclusionEventStats.Length ?? 0;
}
private static DebugUI.Table.Row AddInstanceCullerViewDataRow(int viewIndex)
{
return new DebugUI.Table.Row
@ -154,9 +159,32 @@ namespace UnityEngine.Rendering
children =
{
new DebugUI.Value { displayName = "View Type", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => GetInstanceCullerViewStats(viewIndex).viewType },
new DebugUI.Value { displayName = "View Instance ID", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => GetInstanceCullerViewStats(viewIndex).viewInstanceID },
new DebugUI.Value { displayName = "View Instance ID", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () =>
{
var viewStats = GetInstanceCullerViewStats(viewIndex);
#if UNITY_EDITOR
Object view = EditorUtility.InstanceIDToObject(viewStats.viewInstanceID);
if (view)
{
return $"{viewStats.viewInstanceID} ({view.name})";
}
#endif
return viewStats.viewInstanceID;
}
},
new DebugUI.Value { displayName = "Split Index", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => GetInstanceCullerViewStats(viewIndex).splitIndex },
new DebugUI.Value { displayName = "Visible Instances", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => GetInstanceCullerViewStats(viewIndex).visibleInstances },
new DebugUI.Value { displayName = "Visible Instances CPU | GPU", tooltip = "Visible instances after CPU culling and after GPU culling.", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () =>
{
var viewStats = GetInstanceCullerViewStats(viewIndex);
return $"{viewStats.visibleInstancesOnCPU} | {viewStats.visibleInstancesOnGPU}";
}
},
new DebugUI.Value { displayName = "Visible Primitives CPU | GPU", tooltip = "Visible primitives after CPU culling and after GPU culling.", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () =>
{
var viewStats = GetInstanceCullerViewStats(viewIndex);
return $"{viewStats.visiblePrimitivesOnCPU} | {viewStats.visiblePrimitivesOnGPU}";
}
},
new DebugUI.Value { displayName = "Draw Commands", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => GetInstanceCullerViewStats(viewIndex).drawCommands },
}
};
@ -182,6 +210,16 @@ namespace UnityEngine.Rendering
return (stats.eventType == InstanceOcclusionEventType.OcclusionTest) ? stats.culledInstances : "-";
}
private static object VisiblePrimitivesString(in InstanceOcclusionEventStats stats)
{
return (stats.eventType == InstanceOcclusionEventType.OcclusionTest) ? stats.visiblePrimitives : "-";
}
private static object CulledPrimitivesString(in InstanceOcclusionEventStats stats)
{
return (stats.eventType == InstanceOcclusionEventType.OcclusionTest) ? stats.culledPrimitives : "-";
}
private static DebugUI.Table.Row AddInstanceOcclusionPassDataRow(int eventIndex)
{
return new DebugUI.Table.Row
@ -191,13 +229,27 @@ namespace UnityEngine.Rendering
isHiddenCallback = () => { return eventIndex >= GetInstanceOcclusionEventCount(); },
children =
{
new DebugUI.Value { displayName = "View Instance ID", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => GetInstanceOcclusionEventStats(eventIndex).viewInstanceID },
new DebugUI.Value { displayName = "View Instance ID", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () =>
{
var eventStats = GetInstanceOcclusionEventStats(eventIndex);
#if UNITY_EDITOR
Object view = EditorUtility.InstanceIDToObject(eventStats.viewInstanceID);
if (view)
{
return $"{eventStats.viewInstanceID} ({view.name})";
}
#endif
return eventStats.viewInstanceID;
}
},
new DebugUI.Value { displayName = "Event Type", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => $"{GetInstanceOcclusionEventStats(eventIndex).eventType}" },
new DebugUI.Value { displayName = "Occluder Version", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => OccluderVersionString(GetInstanceOcclusionEventStats(eventIndex)) },
new DebugUI.Value { displayName = "Subview Mask", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => $"0x{GetInstanceOcclusionEventStats(eventIndex).subviewMask:X}" },
new DebugUI.Value { displayName = "Occlusion Test", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => $"{OcclusionTestString(GetInstanceOcclusionEventStats(eventIndex))}" },
new DebugUI.Value { displayName = "Visible Instances", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => VisibleInstancesString(GetInstanceOcclusionEventStats(eventIndex)) },
new DebugUI.Value { displayName = "Culled Instances", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => CulledInstancesString(GetInstanceOcclusionEventStats(eventIndex)) },
new DebugUI.Value { displayName = "Visible Primitives", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => VisiblePrimitivesString(GetInstanceOcclusionEventStats(eventIndex)) },
new DebugUI.Value { displayName = "Culled Primitives", refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () => CulledPrimitivesString(GetInstanceOcclusionEventStats(eventIndex)) },
}
};
}
@ -298,6 +350,104 @@ namespace UnityEngine.Rendering
}
});
instanceCullerStats.children.Add(new DebugUI.ValueTuple()
{
displayName = "Total Visible Instances (Cameras | Lights | Both)",
values = new[]
{
new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () =>
{
int totalGRDInstances = 0;
for (int viewIndex = 0; viewIndex < GetInstanceCullerViewCount(); viewIndex++)
{
var viewStats = GetInstanceCullerViewStats(viewIndex);
if (viewStats.viewType == BatchCullingViewType.Camera)
totalGRDInstances += viewStats.visibleInstancesOnGPU;
}
return totalGRDInstances;
}
},
new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () =>
{
int totalGRDInstances = 0;
for (int viewIndex = 0; viewIndex < GetInstanceCullerViewCount(); viewIndex++)
{
var viewStats = GetInstanceCullerViewStats(viewIndex);
if (viewStats.viewType == BatchCullingViewType.Light)
totalGRDInstances += viewStats.visibleInstancesOnGPU;
}
return totalGRDInstances;
}
},
new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () =>
{
int totalGRDInstances = 0;
for (int viewIndex = 0; viewIndex < GetInstanceCullerViewCount(); viewIndex++)
{
var viewStats = GetInstanceCullerViewStats(viewIndex);
if (viewStats.viewType != BatchCullingViewType.Filtering
&& viewStats.viewType != BatchCullingViewType.Picking
&& viewStats.viewType != BatchCullingViewType.SelectionOutline)
totalGRDInstances += viewStats.visibleInstancesOnGPU;
}
return totalGRDInstances;
}
},
}
});
instanceCullerStats.children.Add(new DebugUI.ValueTuple()
{
displayName = "Total Visible Primitives (Cameras | Lights | Both)",
values = new[]
{
new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () =>
{
int totalGRDPrimitives = 0;
for (int viewIndex = 0; viewIndex < GetInstanceCullerViewCount(); viewIndex++)
{
var viewStats = GetInstanceCullerViewStats(viewIndex);
if (viewStats.viewType == BatchCullingViewType.Camera)
totalGRDPrimitives += viewStats.visiblePrimitivesOnGPU;
}
return totalGRDPrimitives;
}
},
new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () =>
{
int totalGRDPrimitives = 0;
for (int viewIndex = 0; viewIndex < GetInstanceCullerViewCount(); viewIndex++)
{
var viewStats = GetInstanceCullerViewStats(viewIndex);
if (viewStats.viewType == BatchCullingViewType.Light)
totalGRDPrimitives += viewStats.visiblePrimitivesOnGPU;
}
return totalGRDPrimitives;
}
},
new DebugUI.Value { refreshRate = k_RefreshRate, formatString = k_FormatString, getter = () =>
{
int totalGRDPrimitives = 0;
for (int viewIndex = 0; viewIndex < GetInstanceCullerViewCount(); viewIndex++)
{
var viewStats = GetInstanceCullerViewStats(viewIndex);
if (viewStats.viewType != BatchCullingViewType.Filtering
&& viewStats.viewType != BatchCullingViewType.Picking
&& viewStats.viewType != BatchCullingViewType.SelectionOutline)
totalGRDPrimitives += viewStats.visiblePrimitivesOnGPU;
}
return totalGRDPrimitives;
}
},
}
});
DebugUI.Table viewTable = new DebugUI.Table
{
displayName = "",

132
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawer.cs

@ -530,7 +530,7 @@ namespace UnityEngine.Rendering
rendererIDs[i] = renderers[i] ? renderers[i].GetInstanceID() : 0;
m_Batcher.UpdateSelectedRenderers(rendererIDs);
rendererIDs.Dispose();
Profiler.EndSample();
@ -620,7 +620,7 @@ namespace UnityEngine.Rendering
UpdateSelection();
m_IsSelectionDirty = false;
}
m_FrameUpdateNeeded = false;
#endif
}
@ -827,14 +827,8 @@ namespace UnityEngine.Rendering
if (materials.Length > 0)
{
new ClassifyMaterialsJob
{
materialIDs = materials.AsReadOnly(),
batchMaterialHash = m_Batcher.instanceCullingBatcher.batchMaterialHash.AsReadOnly(),
unsupportedMaterialIDs = unsupportedMaterials,
supportedMaterialIDs = supportedMaterials,
supportedPackedMaterialDatas = supportedPackedMaterialDatas
}.Run();
GPUResidentDrawerBurst.ClassifyMaterials(materials, m_Batcher.instanceCullingBatcher.batchMaterialHash.AsReadOnly(),
ref supportedMaterials, ref unsupportedMaterials, ref supportedPackedMaterialDatas);
}
}
@ -844,13 +838,8 @@ namespace UnityEngine.Rendering
if (unsupportedMaterials.Length > 0)
{
new FindUnsupportedRenderersJob
{
unsupportedMaterials = unsupportedMaterials.AsReadOnly(),
materialIDArrays = m_BatchersContext.sharedInstanceData.materialIDArrays,
rendererGroups = m_BatchersContext.sharedInstanceData.rendererGroupIDs,
unsupportedRenderers = unsupportedRenderers,
}.Run();
GPUResidentDrawerBurst.FindUnsupportedRenderers(unsupportedMaterials, m_BatchersContext.sharedInstanceData.materialIDArrays,
m_BatchersContext.sharedInstanceData.rendererGroupIDs, ref unsupportedRenderers);
}
return unsupportedRenderers;
@ -860,13 +849,8 @@ namespace UnityEngine.Rendering
{
NativeHashSet<int> filteredMaterials = new NativeHashSet<int>(materials.Length, allocator);
new GetMaterialsWithChangedPackedMaterialJob
{
materialIDs = materials.AsReadOnly(),
packedMaterialDatas = packedMaterialDatas.AsReadOnly(),
packedMaterialHash = batcher.instanceCullingBatcher.packedMaterialHash.AsReadOnly(),
filteredMaterials = filteredMaterials
}.Run();
GPUResidentDrawerBurst.GetMaterialsWithChangedPackedMaterial(materials, packedMaterialDatas,
batcher.instanceCullingBatcher.packedMaterialHash.AsReadOnly(), ref filteredMaterials);
return filteredMaterials;
}
@ -893,79 +877,6 @@ namespace UnityEngine.Rendering
return (renderersWithMaterials, renderersWithMeshes);
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
private struct ClassifyMaterialsJob : IJob
{
[ReadOnly] public NativeParallelHashMap<int, BatchMaterialID>.ReadOnly batchMaterialHash;
[ReadOnly] public NativeArray<int>.ReadOnly materialIDs;
public NativeList<int> supportedMaterialIDs;
public NativeList<int> unsupportedMaterialIDs;
public NativeList<GPUDrivenPackedMaterialData> supportedPackedMaterialDatas;
public void Execute()
{
var usedMaterialIDs = new NativeList<int>(4, Allocator.TempJob);
foreach (var materialID in materialIDs)
{
if (batchMaterialHash.ContainsKey(materialID))
usedMaterialIDs.Add(materialID);
}
if (usedMaterialIDs.IsEmpty)
{
usedMaterialIDs.Dispose();
return;
}
unsupportedMaterialIDs.Resize(usedMaterialIDs.Length, NativeArrayOptions.UninitializedMemory);
supportedMaterialIDs.Resize(usedMaterialIDs.Length, NativeArrayOptions.UninitializedMemory);
supportedPackedMaterialDatas.Resize(usedMaterialIDs.Length, NativeArrayOptions.UninitializedMemory);
int unsupportedMaterialCount = GPUDrivenProcessor.ClassifyMaterials(usedMaterialIDs.AsArray(), unsupportedMaterialIDs.AsArray(), supportedMaterialIDs.AsArray(), supportedPackedMaterialDatas.AsArray());
unsupportedMaterialIDs.Resize(unsupportedMaterialCount, NativeArrayOptions.ClearMemory);
supportedMaterialIDs.Resize(usedMaterialIDs.Length - unsupportedMaterialCount, NativeArrayOptions.ClearMemory);
supportedPackedMaterialDatas.Resize(supportedMaterialIDs.Length, NativeArrayOptions.ClearMemory);
usedMaterialIDs.Dispose();
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
private struct FindUnsupportedRenderersJob : IJob
{
[ReadOnly] public NativeArray<int>.ReadOnly unsupportedMaterials;
[ReadOnly] public NativeArray<SmallIntegerArray>.ReadOnly materialIDArrays;
[ReadOnly] public NativeArray<int>.ReadOnly rendererGroups;
public NativeList<int> unsupportedRenderers;
public unsafe void Execute()
{
if (unsupportedMaterials.Length == 0)
return;
for (int arrayIndex = 0; arrayIndex < materialIDArrays.Length; arrayIndex++)
{
var materialIDs = materialIDArrays[arrayIndex];
int rendererID = rendererGroups[arrayIndex];
for (int i = 0; i < materialIDs.Length; i++)
{
int materialID = materialIDs[i];
if (unsupportedMaterials.Contains(materialID))
{
unsupportedRenderers.Add(rendererID);
break;
}
}
}
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
private unsafe struct FindRenderersFromMaterialOrMeshJob : IJobParallelForBatch
{
@ -1012,7 +923,7 @@ namespace UnityEngine.Rendering
}
{
var rendererMaterials = materialIDArrays[rendererIndex];
for (int materialIndex = 0; materialIndex < rendererMaterials.Length; materialIndex++)
{
var materialID = rendererMaterials[materialIndex];
@ -1029,30 +940,5 @@ namespace UnityEngine.Rendering
selectedRenderGroupsForMeshes.AddRangeNoResize(renderersToAddForMeshesPtr, renderersToAddForMeshes.Length);
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
private struct GetMaterialsWithChangedPackedMaterialJob : IJob
{
[ReadOnly] public NativeArray<int>.ReadOnly materialIDs;
[ReadOnly] public NativeArray<GPUDrivenPackedMaterialData>.ReadOnly packedMaterialDatas;
[ReadOnly] public NativeParallelHashMap<int, GPUDrivenPackedMaterialData>.ReadOnly packedMaterialHash;
[WriteOnly] public NativeHashSet<int> filteredMaterials;
public void Execute()
{
for (int index = 0; index < materialIDs.Length ; index++)
{
var materialID = materialIDs[index];
var newPackedMaterialData = packedMaterialDatas[index];
// Has its packed material changed? If the material isn't in the packed material cache, consider the material has changed.
if (packedMaterialHash.TryGetValue(materialID, out var packedMaterial) && packedMaterial.Equals(newPackedMaterialData))
continue;
filteredMaterials.Add(materialID);
}
}
}
}
}

80
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawerBurst.cs

@ -0,0 +1,80 @@
using Unity.Collections;
using UnityEngine.Rendering;
using Unity.Burst;
namespace UnityEngine.Rendering
{
[BurstCompile]
internal static class GPUResidentDrawerBurst
{
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
public static void ClassifyMaterials(in NativeArray<int> materialIDs, in NativeParallelHashMap<int, BatchMaterialID>.ReadOnly batchMaterialHash,
ref NativeList<int> supportedMaterialIDs, ref NativeList<int> unsupportedMaterialIDs, ref NativeList<GPUDrivenPackedMaterialData> supportedPackedMaterialDatas)
{
var usedMaterialIDs = new NativeList<int>(4, Allocator.Temp);
foreach (var materialID in materialIDs)
{
if (batchMaterialHash.ContainsKey(materialID))
usedMaterialIDs.Add(materialID);
}
if (usedMaterialIDs.IsEmpty)
{
usedMaterialIDs.Dispose();
return;
}
unsupportedMaterialIDs.Resize(usedMaterialIDs.Length, NativeArrayOptions.UninitializedMemory);
supportedMaterialIDs.Resize(usedMaterialIDs.Length, NativeArrayOptions.UninitializedMemory);
supportedPackedMaterialDatas.Resize(usedMaterialIDs.Length, NativeArrayOptions.UninitializedMemory);
int unsupportedMaterialCount = GPUDrivenProcessor.ClassifyMaterials(usedMaterialIDs.AsArray(), unsupportedMaterialIDs.AsArray(), supportedMaterialIDs.AsArray(), supportedPackedMaterialDatas.AsArray());
unsupportedMaterialIDs.Resize(unsupportedMaterialCount, NativeArrayOptions.ClearMemory);
supportedMaterialIDs.Resize(usedMaterialIDs.Length - unsupportedMaterialCount, NativeArrayOptions.ClearMemory);
supportedPackedMaterialDatas.Resize(supportedMaterialIDs.Length, NativeArrayOptions.ClearMemory);
usedMaterialIDs.Dispose();
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
public static void FindUnsupportedRenderers(in NativeArray<int> unsupportedMaterials, in NativeArray<SmallIntegerArray>.ReadOnly materialIDArrays, in NativeArray<int>.ReadOnly rendererGroups,
ref NativeList<int> unsupportedRenderers)
{
for (int arrayIndex = 0; arrayIndex < materialIDArrays.Length; arrayIndex++)
{
var materialIDs = materialIDArrays[arrayIndex];
int rendererID = rendererGroups[arrayIndex];
for (int i = 0; i < materialIDs.Length; i++)
{
int materialID = materialIDs[i];
if (unsupportedMaterials.Contains(materialID))
{
unsupportedRenderers.Add(rendererID);
break;
}
}
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
public static void GetMaterialsWithChangedPackedMaterial(in NativeArray<int> materialIDs, in NativeArray<GPUDrivenPackedMaterialData> packedMaterialDatas,
in NativeParallelHashMap<int, GPUDrivenPackedMaterialData>.ReadOnly packedMaterialHash, ref NativeHashSet<int> filteredMaterials)
{
for (int index = 0; index < materialIDs.Length ; index++)
{
var materialID = materialIDs[index];
var newPackedMaterialData = packedMaterialDatas[index];
// Has its packed material changed? If the material isn't in the packed material cache, consider the material has changed.
if (packedMaterialHash.TryGetValue(materialID, out var packedMaterial) && packedMaterial.Equals(newPackedMaterialData))
continue;
filteredMaterials.Add(materialID);
}
}
}
}

2
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawerBurst.cs.meta

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2f50a3b1f0997d342837e27ab3b95e6f

49
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/GPUResidentDrawerDebug.cs

@ -10,7 +10,10 @@ namespace UnityEngine.Rendering
public BatchCullingViewType viewType;
public int viewInstanceID;
public int splitIndex;
public int visibleInstances;
public int visibleInstancesOnCPU;
public int visibleInstancesOnGPU;
public int visiblePrimitivesOnCPU;
public int visiblePrimitivesOnGPU;
public int drawCommands;
}
@ -29,6 +32,8 @@ namespace UnityEngine.Rendering
public OcclusionTest occlusionTest;
public int visibleInstances;
public int culledInstances;
public int visiblePrimitives;
public int culledPrimitives;
}
internal struct DebugOccluderStats
@ -55,6 +60,48 @@ namespace UnityEngine.Rendering
occluderStats = new NativeList<DebugOccluderStats>(Allocator.Persistent);
}
public void FinalizeInstanceCullerViewStats()
{
// For each view, update the on GPU instance and primitive counts. The final rendered primitive and
// instance count can be found at the last pass of all the occlusion passes.
for (int viewIndex = 0; viewIndex < instanceCullerStats.Length; viewIndex++)
{
InstanceCullerViewStats cullerStats = instanceCullerStats[viewIndex];
InstanceOcclusionEventStats lastOcclusionEventStats = GetLastInstanceOcclusionEventStatsForView(viewIndex);
if (lastOcclusionEventStats.viewInstanceID == cullerStats.viewInstanceID)
{
// The Min test is because the SelectionOutline view (and probably picking as well) share the same viewInstanceID with
// the scene camera for instance, so we pick up the camera's occlusion event. And we can't have more instances on GPU than we had on CPU.
cullerStats.visibleInstancesOnGPU = Math.Min(lastOcclusionEventStats.visibleInstances, cullerStats.visibleInstancesOnCPU);
cullerStats.visiblePrimitivesOnGPU = Math.Min(lastOcclusionEventStats.visiblePrimitives, cullerStats.visiblePrimitivesOnCPU);
}
else
{
// There was no occlusion culling for this view, so reuse the same counts as on the CPU.
cullerStats.visibleInstancesOnGPU = cullerStats.visibleInstancesOnCPU;
cullerStats.visiblePrimitivesOnGPU = cullerStats.visiblePrimitivesOnCPU;
}
instanceCullerStats[viewIndex] = cullerStats;
}
}
private InstanceOcclusionEventStats GetLastInstanceOcclusionEventStatsForView(int viewIndex)
{
if (viewIndex < instanceCullerStats.Length)
{
int viewInstanceID = instanceCullerStats[viewIndex].viewInstanceID;
for (int passIndex = instanceOcclusionEventStats.Length - 1; passIndex >= 0; passIndex--)
{
if (instanceOcclusionEventStats[passIndex].viewInstanceID == viewInstanceID)
return instanceOcclusionEventStats[passIndex];
}
}
return new InstanceOcclusionEventStats();
}
public void Dispose()
{
if (instanceCullerStats.IsCreated)

75
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCuller.cs

@ -429,7 +429,21 @@ namespace UnityEngine.Rendering
return instanceData.localToWorldIsFlippedBits.Get(instanceIndex);
}
unsafe public void Execute(int batchIndex)
static int GetPrimitiveCount(int indexCount, MeshTopology topology, bool nativeQuads)
{
switch (topology)
{
case MeshTopology.Triangles: return indexCount / 3;
case MeshTopology.Quads: return nativeQuads ? (indexCount / 4) : (indexCount / 4 * 2);
case MeshTopology.Lines: return indexCount / 2;
case MeshTopology.LineStrip: return (indexCount >= 1) ? (indexCount - 1) : 0;
case MeshTopology.Points: return indexCount;
default: Debug.Assert(false, "unknown primitive type"); return 0;
}
}
public void Execute(int batchIndex)
{
// figure out how many combinations of views/features we need to partition by
int configCount = binningConfig.visibilityConfigCount;
@ -529,7 +543,12 @@ namespace UnityEngine.Rendering
int visibleCount = visibleCountPerView[viewIndex];
if (visibleCount > 0)
{
int primitiveCount = GetPrimitiveCount((int)drawBatch.procInfo.indexCount, drawBatch.procInfo.topology, false);
Interlocked.Add(ref UnsafeUtility.AsRef<int>(counterPtr + (int)InstanceCullerSplitDebugCounter.VisibleInstances), visibleCount);
Interlocked.Add(ref UnsafeUtility.AsRef<int>(counterPtr + (int)InstanceCullerSplitDebugCounter.VisiblePrimitives), visibleCount * primitiveCount);
}
}
}
}
@ -854,7 +873,7 @@ namespace UnityEngine.Rendering
firstIndex = drawBatch.procInfo.firstIndex,
baseVertex = drawBatch.procInfo.baseVertex,
firstInstanceGlobalIndex = (uint)instanceInfoGlobalIndex,
maxInstanceCount = (uint)visibleInstanceCount,
maxInstanceCountAndTopology = ((uint)visibleInstanceCount << 3) | (uint)drawBatch.procInfo.topology,
};
output.indirectDrawCommands[drawCommandOffset] = new BatchDrawCommandIndirect
{
@ -1215,6 +1234,7 @@ namespace UnityEngine.Rendering
internal enum InstanceCullerSplitDebugCounter
{
VisibleInstances,
VisiblePrimitives,
DrawCommands,
Count,
}
@ -1293,7 +1313,10 @@ namespace UnityEngine.Rendering
viewType = info.viewType,
viewInstanceID = info.viewInstanceID,
splitIndex = info.splitIndex,
visibleInstances = m_Counters[counterBase + (int)InstanceCullerSplitDebugCounter.VisibleInstances],
visibleInstancesOnCPU = m_Counters[counterBase + (int)InstanceCullerSplitDebugCounter.VisibleInstances],
visibleInstancesOnGPU = 0, // Unknown at this point, will be filled in later
visiblePrimitivesOnCPU = m_Counters[counterBase + (int)InstanceCullerSplitDebugCounter.VisiblePrimitives],
visiblePrimitivesOnGPU = 0, // Unknown at this point, will be filled in later
drawCommands = m_Counters[counterBase + (int)InstanceCullerSplitDebugCounter.DrawCommands],
});
}
@ -1442,8 +1465,10 @@ namespace UnityEngine.Rendering
}
int counterBase = index * (int)InstanceOcclusionTestDebugCounter.Count;
int occludedCounter = m_LatestCounters[counterBase + (int)InstanceOcclusionTestDebugCounter.Occluded];
int notOccludedCounter = m_LatestCounters[counterBase + (int)InstanceOcclusionTestDebugCounter.NotOccluded];
int instancesOccludedCounter = m_LatestCounters[counterBase + (int)InstanceOcclusionTestDebugCounter.InstancesOccluded];
int instancesNotOccludedCounter = m_LatestCounters[counterBase + (int)InstanceOcclusionTestDebugCounter.InstancesNotOccluded];
int primitivesOccludedCounter = m_LatestCounters[counterBase + (int)InstanceOcclusionTestDebugCounter.PrimitivesOccluded];
int primitivesNotOccludedCounter = m_LatestCounters[counterBase + (int)InstanceOcclusionTestDebugCounter.PrimitivesNotOccluded];
debugStats.instanceOcclusionEventStats.Add(new InstanceOcclusionEventStats
{
@ -1452,8 +1477,10 @@ namespace UnityEngine.Rendering
occluderVersion = occluderVersion,
subviewMask = info.subviewMask,
occlusionTest = info.occlusionTest,
visibleInstances = notOccludedCounter,
culledInstances = occludedCounter,
visibleInstances = instancesNotOccludedCounter,
culledInstances = instancesOccludedCounter,
visiblePrimitives = primitivesNotOccludedCounter,
culledPrimitives = primitivesOccludedCounter,
});
}
}
@ -1531,25 +1558,6 @@ namespace UnityEngine.Rendering
m_CommandBuffer.name = "EnsureValidOcclusionTestResults";
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
private unsafe struct SetupCullingJobInput : IJob
{
public float lodBias;
[NativeDisableUnsafePtrRestriction] public BatchCullingContext* context;
[NativeDisableUnsafePtrRestriction] public ReceiverPlanes* receiverPlanes;
[NativeDisableUnsafePtrRestriction] public ReceiverSphereCuller* receiverSphereCuller;
[NativeDisableUnsafePtrRestriction] public FrustumPlaneCuller* frustumPlaneCuller;
[NativeDisableUnsafePtrRestriction] public float* screenRelativeMetric;
public void Execute()
{
*receiverPlanes = ReceiverPlanes.Create(*context, Allocator.TempJob);
*receiverSphereCuller = ReceiverSphereCuller.Create(*context, Allocator.TempJob);
*frustumPlaneCuller = FrustumPlaneCuller.Create(*context, receiverPlanes->planes.AsArray(), *receiverSphereCuller, Allocator.TempJob);
*screenRelativeMetric = LODGroupRenderingUtils.CalculateScreenRelativeMetric(context->lodParameters, lodBias);
}
}
private unsafe JobHandle CreateFrustumCullingJob(
in BatchCullingContext cc,
in CPUInstanceData.ReadOnly instanceData,
@ -1561,7 +1569,7 @@ namespace UnityEngine.Rendering
NativeArray<byte> rendererVisibilityMasks,
NativeArray<byte> rendererCrossFadeValues)
{
Assert.IsTrue(cc.cullingSplits.Length <= 6, "InstanceCullingBatcher supports up to 6 culling splits.");
Assert.IsTrue(cc.cullingSplits.Length <= 6, "InstanceCuller supports up to 6 culling splits.");
ReceiverPlanes receiverPlanes;
ReceiverSphereCuller receiverSphereCuller;
@ -1570,16 +1578,8 @@ namespace UnityEngine.Rendering
fixed (BatchCullingContext* contextPtr = &cc)
{
new SetupCullingJobInput()
{
lodBias = QualitySettings.lodBias,
context = contextPtr,
frustumPlaneCuller = &frustumPlaneCuller,
receiverPlanes = &receiverPlanes,
receiverSphereCuller = &receiverSphereCuller,
screenRelativeMetric = &screenRelativeMetric,
}.Run();
InstanceCullerBurst.SetupCullingJobInput(QualitySettings.lodBias, contextPtr, &receiverPlanes, &receiverSphereCuller,
&frustumPlaneCuller, &screenRelativeMetric);
}
if (occlusionCullingCommon != null)
@ -2296,6 +2296,7 @@ namespace UnityEngine.Rendering
{
m_SplitDebugArray.MoveToDebugStatsAndClear(m_DebugStats);
m_OcclusionEventDebugArray.MoveToDebugStatsAndClear(m_DebugStats);
m_DebugStats.FinalizeInstanceCullerViewStats();
}
}

19
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCullerBurst.cs

@ -0,0 +1,19 @@
using Unity.Collections;
using Unity.Burst;
namespace UnityEngine.Rendering
{
[BurstCompile]
internal static class InstanceCullerBurst
{
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
public static unsafe void SetupCullingJobInput(float lodBias, BatchCullingContext* context, ReceiverPlanes* receiverPlanes,
ReceiverSphereCuller* receiverSphereCuller, FrustumPlaneCuller* frustumPlaneCuller, float* screenRelativeMetric)
{
*receiverPlanes = ReceiverPlanes.Create(*context, Allocator.TempJob);
*receiverSphereCuller = ReceiverSphereCuller.Create(*context, Allocator.TempJob);
*frustumPlaneCuller = FrustumPlaneCuller.Create(*context, receiverPlanes->planes.AsArray(), *receiverSphereCuller, Allocator.TempJob);
*screenRelativeMetric = LODGroupRenderingUtils.CalculateScreenRelativeMetric(context->lodParameters, lodBias);
}
}
}

2
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCullerBurst.cs.meta

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 99f3de5decfa27b47a4ab725fc059f50

278
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCullingBatcher.cs

@ -384,245 +384,6 @@ namespace UnityEngine.Rendering
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
internal struct CreateDrawBatchesJob : IJob
{
[ReadOnly] public bool implicitInstanceIndices;
[ReadOnly] public NativeArray<InstanceHandle> instances;
[ReadOnly] public GPUDrivenRendererGroupData rendererData;
[ReadOnly] public NativeParallelHashMap<int, BatchMeshID>.ReadOnly batchMeshHash;
[ReadOnly] public NativeParallelHashMap<int, BatchMaterialID>.ReadOnly batchMaterialHash;
[ReadOnly] public NativeParallelHashMap<int, GPUDrivenPackedMaterialData>.ReadOnly packedMaterialDataHash;
public NativeParallelHashMap<RangeKey, int> rangeHash;
public NativeList<DrawRange> drawRanges;
public NativeParallelHashMap<DrawKey, int> batchHash;
public NativeList<DrawBatch> drawBatches;
[WriteOnly] public NativeList<DrawInstance> drawInstances;
private ref DrawRange EditDrawRange(in RangeKey key)
{
int drawRangeIndex;
if (!rangeHash.TryGetValue(key, out drawRangeIndex))
{
var drawRange = new DrawRange { key = key, drawCount = 0, drawOffset = 0 };
drawRangeIndex = drawRanges.Length;
rangeHash.Add(key, drawRangeIndex);
drawRanges.Add(drawRange);
}
ref DrawRange data = ref drawRanges.ElementAt(drawRangeIndex);
Assert.IsTrue(data.key.Equals(key));
return ref data;
}
private ref DrawBatch EditDrawBatch(in DrawKey key, in SubMeshDescriptor subMeshDescriptor)
{
var procInfo = new MeshProceduralInfo();
procInfo.topology = subMeshDescriptor.topology;
procInfo.baseVertex = (uint)subMeshDescriptor.baseVertex;
procInfo.firstIndex = (uint)subMeshDescriptor.indexStart;
procInfo.indexCount = (uint)subMeshDescriptor.indexCount;
int drawBatchIndex;
if (!batchHash.TryGetValue(key, out drawBatchIndex))
{
var drawBatch = new DrawBatch() { key = key, instanceCount = 0, instanceOffset = 0, procInfo = procInfo };
drawBatchIndex = drawBatches.Length;
batchHash.Add(key, drawBatchIndex);
drawBatches.Add(drawBatch);
}
ref DrawBatch data = ref drawBatches.ElementAt(drawBatchIndex);
Assert.IsTrue(data.key.Equals(key));
return ref data;
}
public void ProcessRenderer(int i)
{
var meshIndex = rendererData.meshIndex[i];
var meshID = rendererData.meshID[meshIndex];
var submeshCount = rendererData.subMeshCount[meshIndex];
var subMeshDescOffset = rendererData.subMeshDescOffset[meshIndex];
var batchMeshID = batchMeshHash[meshID];
var rendererGroupID = rendererData.rendererGroupID[i];
var startSubMesh = rendererData.subMeshStartIndex[i];
var gameObjectLayer = rendererData.gameObjectLayer[i];
var renderingLayerMask = rendererData.renderingLayerMask[i];
var materialsOffset = rendererData.materialsOffset[i];
var materialsCount = rendererData.materialsCount[i];
var lightmapIndex = rendererData.lightmapIndex[i];
var packedRendererData = rendererData.packedRendererData[i];
var rendererPriority = rendererData.rendererPriority[i];
int instanceCount;
int instanceOffset;
if (implicitInstanceIndices)
{
instanceCount = 1;
instanceOffset = i;
}
else
{
instanceCount = rendererData.instancesCount[i];
instanceOffset = rendererData.instancesOffset[i];
}
if (instanceCount == 0)
return;
const int kLightmapIndexMask = 0xffff;
const int kLightmapIndexInfluenceOnly = 0xfffe;
var overridenComponents = InstanceComponentGroup.Default;
// Add per-instance wind parameters
if(packedRendererData.hasTree)
overridenComponents |= InstanceComponentGroup.Wind;
var lmIndexMasked = lightmapIndex & kLightmapIndexMask;
// Object doesn't have a valid lightmap Index, -> uses probes for lighting
if (lmIndexMasked >= kLightmapIndexInfluenceOnly)
{
// Only add the component when needed to store blended results (shader will use the ambient probe when not present)
if (packedRendererData.lightProbeUsage == LightProbeUsage.BlendProbes)
overridenComponents |= InstanceComponentGroup.LightProbe;
}
else
{
// Add per-instance lightmap parameters
overridenComponents |= InstanceComponentGroup.Lightmap;
}
// Scan all materials once to retrieve whether this renderer is indirect-compatible or not (and store it in the RangeKey).
Span<GPUDrivenPackedMaterialData> packedMaterialDatas = stackalloc GPUDrivenPackedMaterialData[materialsCount];
var supportsIndirect = true;
for (int matIndex = 0; matIndex < materialsCount; ++matIndex)
{
if (matIndex >= submeshCount)
{
Debug.LogWarning("Material count in the shared material list is higher than sub mesh count for the mesh. Object may be corrupted.");
continue;
}
var materialIndex = rendererData.materialIndex[materialsOffset + matIndex];
GPUDrivenPackedMaterialData packedMaterialData;
if (rendererData.packedMaterialData.Length > 0)
{
packedMaterialData = rendererData.packedMaterialData[materialIndex];
}
else
{
var materialID = rendererData.materialID[materialIndex];
bool isFound = packedMaterialDataHash.TryGetValue(materialID, out packedMaterialData);
Assert.IsTrue(isFound, "Packed material data not found.");
}
supportsIndirect &= packedMaterialData.isIndirectSupported;
packedMaterialDatas[matIndex] = packedMaterialData;
}
var rangeKey = new RangeKey
{
layer = (byte)gameObjectLayer,
renderingLayerMask = renderingLayerMask,
motionMode = packedRendererData.motionVecGenMode,
shadowCastingMode = packedRendererData.shadowCastingMode,
staticShadowCaster = packedRendererData.staticShadowCaster,
rendererPriority = rendererPriority,
supportsIndirect = supportsIndirect
};
ref DrawRange drawRange = ref EditDrawRange(rangeKey);
for (int matIndex = 0; matIndex < materialsCount; ++matIndex)
{
if (matIndex >= submeshCount)
{
Debug.LogWarning("Material count in the shared material list is higher than sub mesh count for the mesh. Object may be corrupted.");
continue;
}
var materialIndex = rendererData.materialIndex[materialsOffset + matIndex];
var materialID = rendererData.materialID[materialIndex];
var packedMaterialData = packedMaterialDatas[matIndex];
if (materialID == 0)
{
Debug.LogWarning("Material in the shared materials list is null. Object will be partially rendered.");
continue;
}
batchMaterialHash.TryGetValue(materialID, out BatchMaterialID batchMaterialID);
// We always provide crossfade value packed in instance index. We don't use None even if there is no LOD to not split the batch.
var flags = BatchDrawCommandFlags.LODCrossFadeValuePacked;
// Let the engine know if we've opted out of lightmap texture arrays
flags |= BatchDrawCommandFlags.UseLegacyLightmapsKeyword;
// assume that a custom motion vectors pass contains deformation motion, so should always output motion vectors
// (otherwise this flag is set dynamically during culling only when the transform is changing)
if (packedMaterialData.isMotionVectorsPassEnabled)
flags |= BatchDrawCommandFlags.HasMotion;
if (packedMaterialData.isTransparent)
flags |= BatchDrawCommandFlags.HasSortingPosition;
{
var submeshIndex = startSubMesh + matIndex;
var subMeshDesc = rendererData.subMeshDesc[subMeshDescOffset + submeshIndex];
var drawKey = new DrawKey
{
materialID = batchMaterialID,
meshID = batchMeshID,
submeshIndex = submeshIndex,
flags = flags,
transparentInstanceId = packedMaterialData.isTransparent ? rendererGroupID : 0,
range = rangeKey,
overridenComponents = (uint)overridenComponents,
// When we've opted out of lightmap texture arrays, we
// need to pass in a valid lightmap index. The engine
// uses this index for sorting and for breaking the
// batch when lightmaps change across draw calls, and
// for binding the correct light map.
lightmapIndex = lightmapIndex
};
ref DrawBatch drawBatch = ref EditDrawBatch(drawKey, subMeshDesc);
if (drawBatch.instanceCount == 0)
++drawRange.drawCount;
drawBatch.instanceCount += instanceCount;
for (int j = 0; j < instanceCount; ++j)
{
var instanceIndex = instanceOffset + j;
InstanceHandle instance = instances[instanceIndex];
drawInstances.Add(new DrawInstance { key = drawKey, instanceIndex = instance.index });
}
}
}
}
public void Execute()
{
for (int i = 0; i < rendererData.rendererGroupID.Length; ++i)
ProcessRenderer(i);
}
}
internal class CPUDrawInstanceData
{
public NativeList<DrawInstance> drawInstances => m_DrawInstances;
@ -720,23 +481,16 @@ namespace UnityEngine.Rendering
internalDrawIndex.Dispose();
}
public unsafe void DestroyDrawInstanceIndices(NativeArray<int> drawInstanceIndicesToDestroy)
public void DestroyDrawInstanceIndices(NativeArray<int> drawInstanceIndicesToDestroy)
{
Profiler.BeginSample("DestroyDrawInstanceIndices.ParallelSort");
drawInstanceIndicesToDestroy.ParallelSort().Complete();
Profiler.EndSample();
var removeDrawInstanceIndicesJob = new RemoveDrawInstanceIndicesJob
{
drawInstanceIndices = drawInstanceIndicesToDestroy,
drawInstances = m_DrawInstances,
drawBatches = m_DrawBatches,
drawRanges = m_DrawRanges,
batchHash = m_BatchHash,
rangeHash = m_RangeHash
};
removeDrawInstanceIndicesJob.Run();
Profiler.BeginSample("DestroyDrawInstanceIndices.RemoveDrawInstanceIndices");
InstanceCullingBatcherBurst.RemoveDrawInstanceIndices(drawInstanceIndicesToDestroy, ref m_DrawInstances, ref m_RangeHash,
ref m_BatchHash, ref m_DrawRanges, ref m_DrawBatches);
Profiler.EndSample();
}
public unsafe void DestroyDrawInstances(NativeArray<InstanceHandle> destroyedInstances)
@ -1150,20 +904,14 @@ namespace UnityEngine.Rendering
RegisterBatchMeshes(rendererData.meshID);
}
new CreateDrawBatchesJob
{
implicitInstanceIndices = rendererData.instancesCount.Length == 0,
instances = instances,
rendererData = rendererData,
batchMeshHash = m_BatchMeshHash.AsReadOnly(),
batchMaterialHash = m_BatchMaterialHash.AsReadOnly(),
packedMaterialDataHash = m_PackedMaterialHash.AsReadOnly(),
rangeHash = m_DrawInstanceData.rangeHash,
drawRanges = m_DrawInstanceData.drawRanges,
batchHash = m_DrawInstanceData.batchHash,
drawBatches = m_DrawInstanceData.drawBatches,
drawInstances = m_DrawInstanceData.drawInstances
}.Run();
var rangeHash = m_DrawInstanceData.rangeHash;
var drawRanges = m_DrawInstanceData.drawRanges;
var batchHash = m_DrawInstanceData.batchHash;
var drawBatches = m_DrawInstanceData.drawBatches;
var drawInstances = m_DrawInstanceData.drawInstances;
InstanceCullingBatcherBurst.CreateDrawBatches(rendererData.instancesCount.Length == 0, instances, rendererData,
m_BatchMeshHash, m_BatchMaterialHash, m_PackedMaterialHash, ref rangeHash, ref drawRanges, ref batchHash, ref drawBatches, ref drawInstances);
m_DrawInstanceData.NeedsRebuild();
UpdateInstanceDataBufferLayoutVersion();

301
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCullingBatcherBurst.cs

@ -0,0 +1,301 @@
using System;
using Unity.Collections;
using Unity.Burst;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine.Assertions;
namespace UnityEngine.Rendering
{
[BurstCompile]
internal static class InstanceCullingBatcherBurst
{
private static void RemoveDrawRange(in RangeKey key, ref NativeParallelHashMap<RangeKey, int> rangeHash, ref NativeList<DrawRange> drawRanges)
{
int drawRangeIndex = rangeHash[key];
ref DrawRange lastDrawRange = ref drawRanges.ElementAt(drawRanges.Length - 1);
rangeHash[lastDrawRange.key] = drawRangeIndex;
rangeHash.Remove(key);
drawRanges.RemoveAtSwapBack(drawRangeIndex);
}
private static void RemoveDrawBatch(in DrawKey key, ref NativeList<DrawRange> drawRanges, ref NativeParallelHashMap<RangeKey, int> rangeHash,
ref NativeParallelHashMap<DrawKey, int> batchHash, ref NativeList<DrawBatch> drawBatches)
{
int drawBatchIndex = batchHash[key];
int drawRangeIndex = rangeHash[key.range];
ref DrawRange drawRange = ref drawRanges.ElementAt(drawRangeIndex);
Assert.IsTrue(drawRange.drawCount > 0);
if (--drawRange.drawCount == 0)
RemoveDrawRange(drawRange.key, ref rangeHash, ref drawRanges);
ref DrawBatch lastDrawBatch = ref drawBatches.ElementAt(drawBatches.Length - 1);
batchHash[lastDrawBatch.key] = drawBatchIndex;
batchHash.Remove(key);
drawBatches.RemoveAtSwapBack(drawBatchIndex);
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
public static unsafe void RemoveDrawInstanceIndices(in NativeArray<int> drawInstanceIndices, ref NativeList<DrawInstance> drawInstances, ref NativeParallelHashMap<RangeKey, int> rangeHash,
ref NativeParallelHashMap<DrawKey, int> batchHash, ref NativeList<DrawRange> drawRanges, ref NativeList<DrawBatch> drawBatches)
{
var drawInstancesPtr = (DrawInstance*)drawInstances.GetUnsafePtr();
var drawInstancesNewBack = drawInstances.Length - 1;
for (int indexRev = drawInstanceIndices.Length - 1; indexRev >= 0; --indexRev)
{
int indexToRemove = drawInstanceIndices[indexRev];
DrawInstance* drawInstance = drawInstancesPtr + indexToRemove;
int drawBatchIndex = batchHash[drawInstance->key];
ref DrawBatch drawBatch = ref drawBatches.ElementAt(drawBatchIndex);
Assert.IsTrue(drawBatch.instanceCount > 0);
if (--drawBatch.instanceCount == 0)
RemoveDrawBatch(drawBatch.key, ref drawRanges, ref rangeHash, ref batchHash, ref drawBatches);
UnsafeUtility.MemCpy(drawInstance, drawInstancesPtr + drawInstancesNewBack--, sizeof(DrawInstance));
}
drawInstances.ResizeUninitialized(drawInstancesNewBack + 1);
}
private static ref DrawRange EditDrawRange(in RangeKey key, NativeParallelHashMap<RangeKey, int> rangeHash, NativeList<DrawRange> drawRanges)
{
int drawRangeIndex;
if (!rangeHash.TryGetValue(key, out drawRangeIndex))
{
var drawRange = new DrawRange { key = key, drawCount = 0, drawOffset = 0 };
drawRangeIndex = drawRanges.Length;
rangeHash.Add(key, drawRangeIndex);
drawRanges.Add(drawRange);
}
ref DrawRange data = ref drawRanges.ElementAt(drawRangeIndex);
Assert.IsTrue(data.key.Equals(key));
return ref data;
}
private static ref DrawBatch EditDrawBatch(in DrawKey key, in SubMeshDescriptor subMeshDescriptor, NativeParallelHashMap<DrawKey, int> batchHash, NativeList<DrawBatch> drawBatches)
{
var procInfo = new MeshProceduralInfo();
procInfo.topology = subMeshDescriptor.topology;
procInfo.baseVertex = (uint)subMeshDescriptor.baseVertex;
procInfo.firstIndex = (uint)subMeshDescriptor.indexStart;
procInfo.indexCount = (uint)subMeshDescriptor.indexCount;
int drawBatchIndex;
if (!batchHash.TryGetValue(key, out drawBatchIndex))
{
var drawBatch = new DrawBatch() { key = key, instanceCount = 0, instanceOffset = 0, procInfo = procInfo };
drawBatchIndex = drawBatches.Length;
batchHash.Add(key, drawBatchIndex);
drawBatches.Add(drawBatch);
}
ref DrawBatch data = ref drawBatches.ElementAt(drawBatchIndex);
Assert.IsTrue(data.key.Equals(key));
return ref data;
}
private static void ProcessRenderer(int i, bool implicitInstanceIndices, in GPUDrivenRendererGroupData rendererData,
NativeParallelHashMap<int, BatchMeshID> batchMeshHash, NativeParallelHashMap<int, GPUDrivenPackedMaterialData> packedMaterialDataHash,
NativeParallelHashMap<int, BatchMaterialID> batchMaterialHash, NativeArray<InstanceHandle> instances, NativeList<DrawInstance> drawInstances,
NativeParallelHashMap<RangeKey, int> rangeHash, NativeList<DrawRange> drawRanges, NativeParallelHashMap<DrawKey, int> batchHash,
NativeList<DrawBatch> drawBatches)
{
var meshIndex = rendererData.meshIndex[i];
var meshID = rendererData.meshID[meshIndex];
var submeshCount = rendererData.subMeshCount[meshIndex];
var subMeshDescOffset = rendererData.subMeshDescOffset[meshIndex];
var batchMeshID = batchMeshHash[meshID];
var rendererGroupID = rendererData.rendererGroupID[i];
var startSubMesh = rendererData.subMeshStartIndex[i];
var gameObjectLayer = rendererData.gameObjectLayer[i];
var renderingLayerMask = rendererData.renderingLayerMask[i];
var materialsOffset = rendererData.materialsOffset[i];
var materialsCount = rendererData.materialsCount[i];
var lightmapIndex = rendererData.lightmapIndex[i];
var packedRendererData = rendererData.packedRendererData[i];
var rendererPriority = rendererData.rendererPriority[i];
int instanceCount;
int instanceOffset;
if (implicitInstanceIndices)
{
instanceCount = 1;
instanceOffset = i;
}
else
{
instanceCount = rendererData.instancesCount[i];
instanceOffset = rendererData.instancesOffset[i];
}
if (instanceCount == 0)
return;
const int kLightmapIndexMask = 0xffff;
const int kLightmapIndexInfluenceOnly = 0xfffe;
var overridenComponents = InstanceComponentGroup.Default;
// Add per-instance wind parameters
if(packedRendererData.hasTree)
overridenComponents |= InstanceComponentGroup.Wind;
var lmIndexMasked = lightmapIndex & kLightmapIndexMask;
// Object doesn't have a valid lightmap Index, -> uses probes for lighting
if (lmIndexMasked >= kLightmapIndexInfluenceOnly)
{
// Only add the component when needed to store blended results (shader will use the ambient probe when not present)
if (packedRendererData.lightProbeUsage == LightProbeUsage.BlendProbes)
overridenComponents |= InstanceComponentGroup.LightProbe;
}
else
{
// Add per-instance lightmap parameters
overridenComponents |= InstanceComponentGroup.Lightmap;
}
// Scan all materials once to retrieve whether this renderer is indirect-compatible or not (and store it in the RangeKey).
Span<GPUDrivenPackedMaterialData> packedMaterialDatas = stackalloc GPUDrivenPackedMaterialData[materialsCount];
var supportsIndirect = true;
for (int matIndex = 0; matIndex < materialsCount; ++matIndex)
{
if (matIndex >= submeshCount)
{
Debug.LogWarning("Material count in the shared material list is higher than sub mesh count for the mesh. Object may be corrupted.");
continue;
}
var materialIndex = rendererData.materialIndex[materialsOffset + matIndex];
GPUDrivenPackedMaterialData packedMaterialData;
if (rendererData.packedMaterialData.Length > 0)
{
packedMaterialData = rendererData.packedMaterialData[materialIndex];
}
else
{
var materialID = rendererData.materialID[materialIndex];
bool isFound = packedMaterialDataHash.TryGetValue(materialID, out packedMaterialData);
Assert.IsTrue(isFound, "Packed material data not found.");
}
supportsIndirect &= packedMaterialData.isIndirectSupported;
packedMaterialDatas[matIndex] = packedMaterialData;
}
var rangeKey = new RangeKey
{
layer = (byte)gameObjectLayer,
renderingLayerMask = renderingLayerMask,
motionMode = packedRendererData.motionVecGenMode,
shadowCastingMode = packedRendererData.shadowCastingMode,
staticShadowCaster = packedRendererData.staticShadowCaster,
rendererPriority = rendererPriority,
supportsIndirect = supportsIndirect
};
ref DrawRange drawRange = ref EditDrawRange(rangeKey, rangeHash, drawRanges);
for (int matIndex = 0; matIndex < materialsCount; ++matIndex)
{
if (matIndex >= submeshCount)
{
Debug.LogWarning("Material count in the shared material list is higher than sub mesh count for the mesh. Object may be corrupted.");
continue;
}
var materialIndex = rendererData.materialIndex[materialsOffset + matIndex];
var materialID = rendererData.materialID[materialIndex];
var packedMaterialData = packedMaterialDatas[matIndex];
if (materialID == 0)
{
Debug.LogWarning("Material in the shared materials list is null. Object will be partially rendered.");
continue;
}
batchMaterialHash.TryGetValue(materialID, out BatchMaterialID batchMaterialID);
// We always provide crossfade value packed in instance index. We don't use None even if there is no LOD to not split the batch.
var flags = BatchDrawCommandFlags.LODCrossFadeValuePacked;
// Let the engine know if we've opted out of lightmap texture arrays
flags |= BatchDrawCommandFlags.UseLegacyLightmapsKeyword;
// assume that a custom motion vectors pass contains deformation motion, so should always output motion vectors
// (otherwise this flag is set dynamically during culling only when the transform is changing)
if (packedMaterialData.isMotionVectorsPassEnabled)
flags |= BatchDrawCommandFlags.HasMotion;
if (packedMaterialData.isTransparent)
flags |= BatchDrawCommandFlags.HasSortingPosition;
{
var submeshIndex = startSubMesh + matIndex;
var subMeshDesc = rendererData.subMeshDesc[subMeshDescOffset + submeshIndex];
var drawKey = new DrawKey
{
materialID = batchMaterialID,
meshID = batchMeshID,
submeshIndex = submeshIndex,
flags = flags,
transparentInstanceId = packedMaterialData.isTransparent ? rendererGroupID : 0,
range = rangeKey,
overridenComponents = (uint)overridenComponents,
// When we've opted out of lightmap texture arrays, we
// need to pass in a valid lightmap index. The engine
// uses this index for sorting and for breaking the
// batch when lightmaps change across draw calls, and
// for binding the correct light map.
lightmapIndex = lightmapIndex
};
ref DrawBatch drawBatch = ref EditDrawBatch(drawKey, subMeshDesc, batchHash, drawBatches);
if (drawBatch.instanceCount == 0)
++drawRange.drawCount;
drawBatch.instanceCount += instanceCount;
for (int j = 0; j < instanceCount; ++j)
{
var instanceIndex = instanceOffset + j;
InstanceHandle instance = instances[instanceIndex];
drawInstances.Add(new DrawInstance { key = drawKey, instanceIndex = instance.index });
}
}
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
public static void CreateDrawBatches(bool implicitInstanceIndices, in NativeArray<InstanceHandle> instances, in GPUDrivenRendererGroupData rendererData,
in NativeParallelHashMap<int, BatchMeshID> batchMeshHash, in NativeParallelHashMap<int, BatchMaterialID> batchMaterialHash,
in NativeParallelHashMap<int, GPUDrivenPackedMaterialData> packedMaterialDataHash,
ref NativeParallelHashMap<RangeKey, int> rangeHash, ref NativeList<DrawRange> drawRanges, ref NativeParallelHashMap<DrawKey, int> batchHash, ref NativeList<DrawBatch> drawBatches,
ref NativeList<DrawInstance> drawInstances)
{
for (int i = 0; i < rendererData.rendererGroupID.Length; ++i)
ProcessRenderer(i, implicitInstanceIndices, rendererData, batchMeshHash, packedMaterialDataHash, batchMaterialHash, instances,
drawInstances, rangeHash, drawRanges, batchHash, drawBatches);
}
}
}

2
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceCullingBatcherBurst.cs.meta

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 07b72b6a7afa9b448b3103bb66d57ca0

207
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceData/InstanceDataSystem.Jobs.cs

@ -482,213 +482,6 @@ namespace UnityEngine.Rendering
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
private struct ReallocateInstancesJob : IJob
{
[ReadOnly] public bool implicitInstanceIndices;
[ReadOnly] public NativeArray<int> rendererGroupIDs;
[ReadOnly] public NativeArray<GPUDrivenPackedRendererData> packedRendererData;
[ReadOnly] public NativeArray<int> instanceOffsets;
[ReadOnly] public NativeArray<int> instanceCounts;
public InstanceAllocators instanceAllocators;
public CPUInstanceData instanceData;
public CPUSharedInstanceData sharedInstanceData;
public NativeArray<InstanceHandle> instances;
public NativeParallelMultiHashMap<int, InstanceHandle> rendererGroupInstanceMultiHash;
public void Execute()
{
for (int i = 0; i < rendererGroupIDs.Length; ++i)
{
var rendererGroupID = rendererGroupIDs[i];
var hasTree = packedRendererData[i].hasTree;
int instanceCount;
int instanceOffset;
if (implicitInstanceIndices)
{
instanceCount = 1;
instanceOffset = i;
}
else
{
instanceCount = instanceCounts[i];
instanceOffset = instanceOffsets[i];
}
SharedInstanceHandle sharedInstance;
if (rendererGroupInstanceMultiHash.TryGetFirstValue(rendererGroupID, out var instance, out var it))
{
sharedInstance = instanceData.Get_SharedInstance(instance);
int currentInstancesCount = sharedInstanceData.Get_RefCount(sharedInstance);
int instancesToFreeCount = currentInstancesCount - instanceCount;
if (instancesToFreeCount > 0)
{
bool success = true;
int freedInstancesCount = 0;
for (int j = 0; j < instanceCount; ++j)
success = rendererGroupInstanceMultiHash.TryGetNextValue(out instance, ref it);
Assert.IsTrue(success);
while (success)
{
instanceData.Remove(instance);
instanceAllocators.FreeInstance(instance);
rendererGroupInstanceMultiHash.Remove(it);
++freedInstancesCount;
success = rendererGroupInstanceMultiHash.TryGetNextValue(out instance, ref it);
}
Assert.AreEqual(instancesToFreeCount, freedInstancesCount);
}
}
else
{
sharedInstance = instanceAllocators.AllocateSharedInstance();
sharedInstanceData.AddNoGrow(sharedInstance);
}
if (instanceCount > 0)
{
sharedInstanceData.Set_RefCount(sharedInstance, instanceCount);
for (int j = 0; j < instanceCount; ++j)
{
int instanceIndex = instanceOffset + j;
if (instances[instanceIndex].valid)
continue;
InstanceHandle newInstance;
if (!hasTree)
newInstance = instanceAllocators.AllocateInstance(InstanceType.MeshRenderer);
else
newInstance = instanceAllocators.AllocateInstance(InstanceType.SpeedTree);
instanceData.AddNoGrow(newInstance);
int index = instanceData.InstanceToIndex(newInstance);
instanceData.sharedInstances[index] = sharedInstance;
instanceData.movedInCurrentFrameBits.Set(index, false);
instanceData.movedInPreviousFrameBits.Set(index, false);
instanceData.visibleInPreviousFrameBits.Set(index, false);
rendererGroupInstanceMultiHash.Add(rendererGroupID, newInstance);
instances[instanceIndex] = newInstance;
}
}
else
{
sharedInstanceData.Remove(sharedInstance);
instanceAllocators.FreeSharedInstance(sharedInstance);
}
}
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
private struct FreeInstancesJob : IJob
{
[ReadOnly] public NativeArray<InstanceHandle> instances;
public InstanceAllocators instanceAllocators;
public CPUInstanceData instanceData;
public CPUSharedInstanceData sharedInstanceData;
public NativeParallelMultiHashMap<int, InstanceHandle> rendererGroupInstanceMultiHash;
public void Execute()
{
foreach (var instance in instances)
{
if (!instanceData.IsValidInstance(instance))
continue;
int instanceIndex = instanceData.InstanceToIndex(instance);
SharedInstanceHandle sharedInstance = instanceData.sharedInstances[instanceIndex];
int sharedInstanceIndex = sharedInstanceData.SharedInstanceToIndex(sharedInstance);
int refCount = sharedInstanceData.refCounts[sharedInstanceIndex];
var rendererGroupID = sharedInstanceData.rendererGroupIDs[sharedInstanceIndex];
Assert.IsTrue(refCount > 0);
if (refCount > 1)
{
sharedInstanceData.refCounts[sharedInstanceIndex] = refCount - 1;
}
else
{
sharedInstanceData.Remove(sharedInstance);
instanceAllocators.FreeSharedInstance(sharedInstance);
}
instanceData.Remove(instance);
instanceAllocators.FreeInstance(instance);
//@ This will have quadratic cost. Optimize later.
for (bool success = rendererGroupInstanceMultiHash.TryGetFirstValue(rendererGroupID, out var i, out var it); success;)
{
if (instance.Equals(i))
{
rendererGroupInstanceMultiHash.Remove(it);
break;
}
success = rendererGroupInstanceMultiHash.TryGetNextValue(out i, ref it);
}
}
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
private struct FreeRendererGroupInstancesJob : IJob
{
[ReadOnly] public NativeArray<int> rendererGroupsID;
public InstanceAllocators instanceAllocators;
public CPUInstanceData instanceData;
public CPUSharedInstanceData sharedInstanceData;
public NativeParallelMultiHashMap<int, InstanceHandle> rendererGroupInstanceMultiHash;
public void Execute()
{
foreach (var rendererGroupID in rendererGroupsID)
{
for (bool success = rendererGroupInstanceMultiHash.TryGetFirstValue(rendererGroupID, out var instance, out var it); success;)
{
SharedInstanceHandle sharedInstance = instanceData.Get_SharedInstance(instance);
int sharedInstanceIndex = sharedInstanceData.SharedInstanceToIndex(sharedInstance);
int refCount = sharedInstanceData.refCounts[sharedInstanceIndex];
Assert.IsTrue(refCount > 0);
if (refCount > 1)
{
sharedInstanceData.refCounts[sharedInstanceIndex] = refCount - 1;
}
else
{
sharedInstanceData.Remove(sharedInstance);
instanceAllocators.FreeSharedInstance(sharedInstance);
}
instanceData.Remove(instance);
instanceAllocators.FreeInstance(instance);
success = rendererGroupInstanceMultiHash.TryGetNextValue(out instance, ref it);
}
rendererGroupInstanceMultiHash.Remove(rendererGroupID);
}
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
private unsafe struct UpdateRendererInstancesJob : IJobParallelFor
{

17
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceData/InstanceDataSystem.cs

@ -475,24 +475,21 @@ namespace UnityEngine.Rendering
m_InstanceData.EnsureFreeInstances(newInstancesCount);
m_SharedInstanceData.EnsureFreeInstances(newSharedInstancesCount);
new ReallocateInstancesJob { implicitInstanceIndices = implicitInstanceIndices, rendererGroupInstanceMultiHash = m_RendererGroupInstanceMultiHash,
instanceAllocators = m_InstanceAllocators, sharedInstanceData = m_SharedInstanceData, instanceData = m_InstanceData,
rendererGroupIDs = rendererData.rendererGroupID, packedRendererData = rendererData.packedRendererData, instanceOffsets = rendererData.instancesOffset,
instanceCounts = rendererData.instancesCount, instances = instances }.Run();
InstanceDataSystemBurst.ReallocateInstances(implicitInstanceIndices, rendererData.rendererGroupID, rendererData.packedRendererData,
rendererData.instancesOffset, rendererData.instancesCount, ref m_InstanceAllocators, ref m_InstanceData,
ref m_SharedInstanceData, ref instances, ref m_RendererGroupInstanceMultiHash);
}
public void FreeRendererGroupInstances(NativeArray<int> rendererGroupsID)
{
new FreeRendererGroupInstancesJob { rendererGroupInstanceMultiHash = m_RendererGroupInstanceMultiHash,
instanceAllocators = m_InstanceAllocators, sharedInstanceData = m_SharedInstanceData, instanceData = m_InstanceData,
rendererGroupsID = rendererGroupsID }.Run();
InstanceDataSystemBurst.FreeRendererGroupInstances(rendererGroupsID.AsReadOnly(), ref m_InstanceAllocators, ref m_InstanceData,
ref m_SharedInstanceData, ref m_RendererGroupInstanceMultiHash);
}
public void FreeInstances(NativeArray<InstanceHandle> instances)
{
new FreeInstancesJob { rendererGroupInstanceMultiHash = m_RendererGroupInstanceMultiHash,
instanceAllocators = m_InstanceAllocators, sharedInstanceData = m_SharedInstanceData, instanceData = m_InstanceData,
instances = instances }.Run();
InstanceDataSystemBurst.FreeInstances(instances.AsReadOnly(), ref m_InstanceAllocators, ref m_InstanceData,
ref m_SharedInstanceData, ref m_RendererGroupInstanceMultiHash);
}
public JobHandle ScheduleUpdateInstanceDataJob(NativeArray<InstanceHandle> instances, in GPUDrivenRendererGroupData rendererData, NativeParallelHashMap<int, GPUInstanceIndex> lodGroupDataMap)

191
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceData/InstanceDataSystemBurst.cs

@ -0,0 +1,191 @@
using Unity.Collections;
using Unity.Burst;
using UnityEngine.Assertions;
namespace UnityEngine.Rendering
{
[BurstCompile]
internal static class InstanceDataSystemBurst
{
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
public static void ReallocateInstances(bool implicitInstanceIndices, in NativeArray<int> rendererGroupIDs, in NativeArray<GPUDrivenPackedRendererData> packedRendererData,
in NativeArray<int> instanceOffsets, in NativeArray<int> instanceCounts, ref InstanceAllocators instanceAllocators, ref CPUInstanceData instanceData,
ref CPUSharedInstanceData sharedInstanceData, ref NativeArray<InstanceHandle> instances,
ref NativeParallelMultiHashMap<int, InstanceHandle> rendererGroupInstanceMultiHash)
{
for (int i = 0; i < rendererGroupIDs.Length; ++i)
{
var rendererGroupID = rendererGroupIDs[i];
var hasTree = packedRendererData[i].hasTree;
int instanceCount;
int instanceOffset;
if (implicitInstanceIndices)
{
instanceCount = 1;
instanceOffset = i;
}
else
{
instanceCount = instanceCounts[i];
instanceOffset = instanceOffsets[i];
}
SharedInstanceHandle sharedInstance;
if (rendererGroupInstanceMultiHash.TryGetFirstValue(rendererGroupID, out var instance, out var it))
{
sharedInstance = instanceData.Get_SharedInstance(instance);
int currentInstancesCount = sharedInstanceData.Get_RefCount(sharedInstance);
int instancesToFreeCount = currentInstancesCount - instanceCount;
if (instancesToFreeCount > 0)
{
bool success = true;
int freedInstancesCount = 0;
for (int j = 0; j < instanceCount; ++j)
success = rendererGroupInstanceMultiHash.TryGetNextValue(out instance, ref it);
Assert.IsTrue(success);
while (success)
{
var idx = instanceData.InstanceToIndex(instance);
instanceData.Remove(instance);
instanceAllocators.FreeInstance(instance);
rendererGroupInstanceMultiHash.Remove(it);
++freedInstancesCount;
success = rendererGroupInstanceMultiHash.TryGetNextValue(out instance, ref it);
}
Assert.AreEqual(instancesToFreeCount, freedInstancesCount);
}
}
else
{
sharedInstance = instanceAllocators.AllocateSharedInstance();
sharedInstanceData.AddNoGrow(sharedInstance);
}
if (instanceCount > 0)
{
sharedInstanceData.Set_RefCount(sharedInstance, instanceCount);
for (int j = 0; j < instanceCount; ++j)
{
int instanceIndex = instanceOffset + j;
if (instances[instanceIndex].valid)
continue;
InstanceHandle newInstance;
if (!hasTree)
newInstance = instanceAllocators.AllocateInstance(InstanceType.MeshRenderer);
else
newInstance = instanceAllocators.AllocateInstance(InstanceType.SpeedTree);
instanceData.AddNoGrow(newInstance);
int index = instanceData.InstanceToIndex(newInstance);
instanceData.sharedInstances[index] = sharedInstance;
instanceData.movedInCurrentFrameBits.Set(index, false);
instanceData.movedInPreviousFrameBits.Set(index, false);
instanceData.visibleInPreviousFrameBits.Set(index, false);
rendererGroupInstanceMultiHash.Add(rendererGroupID, newInstance);
instances[instanceIndex] = newInstance;
}
}
else
{
sharedInstanceData.Remove(sharedInstance);
instanceAllocators.FreeSharedInstance(sharedInstance);
}
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
public static void FreeRendererGroupInstances(in NativeArray<int>.ReadOnly rendererGroupsID, ref InstanceAllocators instanceAllocators, ref CPUInstanceData instanceData,
ref CPUSharedInstanceData sharedInstanceData, ref NativeParallelMultiHashMap<int, InstanceHandle> rendererGroupInstanceMultiHash)
{
foreach (var rendererGroupID in rendererGroupsID)
{
for (bool success = rendererGroupInstanceMultiHash.TryGetFirstValue(rendererGroupID, out var instance, out var it); success;)
{
SharedInstanceHandle sharedInstance = instanceData.Get_SharedInstance(instance);
int sharedInstanceIndex = sharedInstanceData.SharedInstanceToIndex(sharedInstance);
int refCount = sharedInstanceData.refCounts[sharedInstanceIndex];
Assert.IsTrue(refCount > 0);
if (refCount > 1)
{
sharedInstanceData.refCounts[sharedInstanceIndex] = refCount - 1;
}
else
{
sharedInstanceData.Remove(sharedInstance);
instanceAllocators.FreeSharedInstance(sharedInstance);
}
var idx = instanceData.InstanceToIndex(instance);
instanceData.Remove(instance);
instanceAllocators.FreeInstance(instance);
success = rendererGroupInstanceMultiHash.TryGetNextValue(out instance, ref it);
}
rendererGroupInstanceMultiHash.Remove(rendererGroupID);
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
public static void FreeInstances(in NativeArray<InstanceHandle>.ReadOnly instances, ref InstanceAllocators instanceAllocators, ref CPUInstanceData instanceData,
ref CPUSharedInstanceData sharedInstanceData, ref NativeParallelMultiHashMap<int, InstanceHandle> rendererGroupInstanceMultiHash)
{
foreach (var instance in instances)
{
if (!instanceData.IsValidInstance(instance))
continue;
int instanceIndex = instanceData.InstanceToIndex(instance);
SharedInstanceHandle sharedInstance = instanceData.sharedInstances[instanceIndex];
int sharedInstanceIndex = sharedInstanceData.SharedInstanceToIndex(sharedInstance);
int refCount = sharedInstanceData.refCounts[sharedInstanceIndex];
var rendererGroupID = sharedInstanceData.rendererGroupIDs[sharedInstanceIndex];
Assert.IsTrue(refCount > 0);
if (refCount > 1)
{
sharedInstanceData.refCounts[sharedInstanceIndex] = refCount - 1;
}
else
{
sharedInstanceData.Remove(sharedInstance);
instanceAllocators.FreeSharedInstance(sharedInstance);
}
instanceData.Remove(instance);
instanceAllocators.FreeInstance(instance);
//@ This will have quadratic cost. Optimize later.
for (bool success = rendererGroupInstanceMultiHash.TryGetFirstValue(rendererGroupID, out var i, out var it); success;)
{
if (instance.Equals(i))
{
rendererGroupInstanceMultiHash.Remove(it);
break;
}
success = rendererGroupInstanceMultiHash.TryGetNextValue(out i, ref it);
}
}
}
}
}

2
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceData/InstanceDataSystemBurst.cs.meta

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 302f596d55264be4ba359e52ec407766

10
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceOcclusionCuller.cs

@ -74,8 +74,10 @@ namespace UnityEngine.Rendering
[GenerateHLSL(needAccessors = false)]
internal enum InstanceOcclusionTestDebugCounter
{
Occluded,
NotOccluded,
InstancesOccluded,
InstancesNotOccluded,
PrimitivesOccluded,
PrimitivesNotOccluded,
Count,
}
@ -93,7 +95,7 @@ namespace UnityEngine.Rendering
public uint firstIndex;
public uint baseVertex;
public uint firstInstanceGlobalIndex;
public uint maxInstanceCount;
public uint maxInstanceCountAndTopology; // [31:3]=max_instance_count, [2:0]=topology
}
internal struct IndirectBufferAllocInfo
@ -280,7 +282,7 @@ namespace UnityEngine.Rendering
occluderDepthPyramid = RTHandles.Alloc(
occluderDepthPyramidSize.x, occluderDepthPyramidSize.y,
format: GraphicsFormat.R32_SFloat,
dimension: TextureDimension.Tex2D,
dimension: TextureDimension.Tex2D,
filterMode: FilterMode.Point,
wrapMode: TextureWrapMode.Clamp,
enableRandomWrite: true,

10
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/InstanceOcclusionCuller.cs.hlsl

@ -7,9 +7,11 @@
//
// UnityEngine.Rendering.InstanceOcclusionTestDebugCounter: static fields
//
#define INSTANCEOCCLUSIONTESTDEBUGCOUNTER_OCCLUDED (0)
#define INSTANCEOCCLUSIONTESTDEBUGCOUNTER_NOT_OCCLUDED (1)
#define INSTANCEOCCLUSIONTESTDEBUGCOUNTER_COUNT (2)
#define INSTANCEOCCLUSIONTESTDEBUGCOUNTER_INSTANCES_OCCLUDED (0)
#define INSTANCEOCCLUSIONTESTDEBUGCOUNTER_INSTANCES_NOT_OCCLUDED (1)
#define INSTANCEOCCLUSIONTESTDEBUGCOUNTER_PRIMITIVES_OCCLUDED (2)
#define INSTANCEOCCLUSIONTESTDEBUGCOUNTER_PRIMITIVES_NOT_OCCLUDED (3)
#define INSTANCEOCCLUSIONTESTDEBUGCOUNTER_COUNT (4)
// Generated from UnityEngine.Rendering.IndirectDrawInfo
// PackingRules = Exact
@ -19,7 +21,7 @@ struct IndirectDrawInfo
uint firstIndex;
uint baseVertex;
uint firstInstanceGlobalIndex;
uint maxInstanceCount;
uint maxInstanceCountAndTopology;
};
// Generated from UnityEngine.Rendering.IndirectInstanceInfo

106
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/LODGroupDataPool.cs

@ -86,52 +86,6 @@ namespace UnityEngine.Rendering
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
internal unsafe struct AllocateOrGetLODGroupDataInstancesJob : IJob
{
[ReadOnly] public NativeArray<int> lodGroupsID;
public NativeList<LODGroupData> lodGroupsData;
public NativeList<LODGroupCullingData> lodGroupCullingData;
public NativeParallelHashMap<int, GPUInstanceIndex> lodGroupDataHash;
public NativeList<GPUInstanceIndex> freeLODGroupDataHandles;
[WriteOnly] public NativeArray<GPUInstanceIndex> lodGroupInstances;
[NativeDisableUnsafePtrRestriction] public int* previousRendererCount;
public void Execute()
{
int freeHandlesCount = freeLODGroupDataHandles.Length;
int lodDataLength = lodGroupsData.Length;
for (int i = 0; i < lodGroupsID.Length; ++i)
{
int lodGroupID = lodGroupsID[i];
if (!lodGroupDataHash.TryGetValue(lodGroupID, out var lodGroupInstance))
{
if (freeHandlesCount == 0)
lodGroupInstance = new GPUInstanceIndex() { index = lodDataLength++ };
else
lodGroupInstance = freeLODGroupDataHandles[--freeHandlesCount];
lodGroupDataHash.TryAdd(lodGroupID, lodGroupInstance);
}
else
{
*previousRendererCount += lodGroupsData.ElementAt(lodGroupInstance.index).rendererCount;
}
lodGroupInstances[i] = lodGroupInstance;
}
freeLODGroupDataHandles.ResizeUninitialized(freeHandlesCount);
lodGroupsData.ResizeUninitialized(lodDataLength);
lodGroupCullingData.ResizeUninitialized(lodDataLength);
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
internal unsafe struct UpdateLODGroupDataJob : IJobParallelFor
{
@ -219,38 +173,6 @@ namespace UnityEngine.Rendering
}
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
internal unsafe struct FreeLODGroupDataJob : IJob
{
[ReadOnly] public NativeArray<int> destroyedLODGroupsID;
public NativeList<LODGroupData> lodGroupsData;
public NativeParallelHashMap<int, GPUInstanceIndex> lodGroupDataHash;
public NativeList<GPUInstanceIndex> freeLODGroupDataHandles;
[NativeDisableUnsafePtrRestriction] public int* removedRendererCount;
public void Execute()
{
foreach (int lodGroupID in destroyedLODGroupsID)
{
if (lodGroupDataHash.TryGetValue(lodGroupID, out var lodGroupInstance))
{
Assert.IsTrue(lodGroupInstance.valid);
lodGroupDataHash.Remove(lodGroupID);
freeLODGroupDataHandles.Add(lodGroupInstance);
ref LODGroupData lodGroupData = ref lodGroupsData.ElementAt(lodGroupInstance.index);
Assert.IsTrue(lodGroupData.valid);
*removedRendererCount += lodGroupData.rendererCount;
lodGroupData.valid = false;
}
}
}
}
internal class LODGroupDataPool : IDisposable
{
private NativeList<LODGroupData> m_LODGroupData;
@ -329,18 +251,9 @@ namespace UnityEngine.Rendering
var lodGroupInstances = new NativeArray<GPUInstanceIndex>(inputData.lodGroupID.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
int previousRendererCount = 0;
new AllocateOrGetLODGroupDataInstancesJob
{
lodGroupsID = inputData.lodGroupID,
lodGroupsData = m_LODGroupData,
lodGroupCullingData = m_LODGroupCullingData,
lodGroupDataHash = m_LODGroupDataHash,
freeLODGroupDataHandles = m_FreeLODGroupDataHandles,
lodGroupInstances = lodGroupInstances,
previousRendererCount = &previousRendererCount
}.Run();
int previousRendererCount = LODGroupDataPoolBurst.AllocateOrGetLODGroupDataInstances(inputData.lodGroupID,
ref m_LODGroupData, ref m_LODGroupCullingData,
ref m_LODGroupDataHash, ref m_FreeLODGroupDataHandles, ref lodGroupInstances);
m_CrossfadedRendererCount -= previousRendererCount;
Assert.IsTrue(m_CrossfadedRendererCount >= 0);
@ -367,21 +280,12 @@ namespace UnityEngine.Rendering
lodGroupInstances.Dispose();
}
public unsafe void FreeLODGroupData(NativeArray<int> destroyedLODGroupsID)
public void FreeLODGroupData(NativeArray<int> destroyedLODGroupsID)
{
if (destroyedLODGroupsID.Length == 0)
return;
int removedRendererCount = 0;
new FreeLODGroupDataJob
{
destroyedLODGroupsID = destroyedLODGroupsID,
lodGroupsData = m_LODGroupData,
lodGroupDataHash = m_LODGroupDataHash,
freeLODGroupDataHandles = m_FreeLODGroupDataHandles,
removedRendererCount = &removedRendererCount
}.Run();
int removedRendererCount = LODGroupDataPoolBurst.FreeLODGroupData(destroyedLODGroupsID, ref m_LODGroupData, ref m_LODGroupDataHash, ref m_FreeLODGroupDataHandles);
m_CrossfadedRendererCount -= removedRendererCount;
Assert.IsTrue(m_CrossfadedRendererCount >= 0);

72
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/LODGroupDataPoolBurst.cs

@ -0,0 +1,72 @@
using Unity.Collections;
using Unity.Burst;
using UnityEngine.Assertions;
namespace UnityEngine.Rendering
{
[BurstCompile]
internal static class LODGroupDataPoolBurst
{
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
public static int FreeLODGroupData(in NativeArray<int> destroyedLODGroupsID, ref NativeList<LODGroupData> lodGroupsData,
ref NativeParallelHashMap<int, GPUInstanceIndex> lodGroupDataHash, ref NativeList<GPUInstanceIndex> freeLODGroupDataHandles)
{
int removedRendererCount = 0;
foreach (int lodGroupID in destroyedLODGroupsID)
{
if (lodGroupDataHash.TryGetValue(lodGroupID, out var lodGroupInstance))
{
Assert.IsTrue(lodGroupInstance.valid);
lodGroupDataHash.Remove(lodGroupID);
freeLODGroupDataHandles.Add(lodGroupInstance);
ref LODGroupData lodGroupData = ref lodGroupsData.ElementAt(lodGroupInstance.index);
Assert.IsTrue(lodGroupData.valid);
removedRendererCount += lodGroupData.rendererCount;
lodGroupData.valid = false;
}
}
return removedRendererCount;
}
[BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
public static int AllocateOrGetLODGroupDataInstances(in NativeArray<int> lodGroupsID, ref NativeList<LODGroupData> lodGroupsData, ref NativeList<LODGroupCullingData> lodGroupCullingData,
ref NativeParallelHashMap<int, GPUInstanceIndex> lodGroupDataHash, ref NativeList<GPUInstanceIndex> freeLODGroupDataHandles, ref NativeArray<GPUInstanceIndex> lodGroupInstances)
{
int freeHandlesCount = freeLODGroupDataHandles.Length;
int lodDataLength = lodGroupsData.Length;
int previousRendererCount = 0;
for (int i = 0; i < lodGroupsID.Length; ++i)
{
int lodGroupID = lodGroupsID[i];
if (!lodGroupDataHash.TryGetValue(lodGroupID, out var lodGroupInstance))
{
if (freeHandlesCount == 0)
lodGroupInstance = new GPUInstanceIndex() { index = lodDataLength++ };
else
lodGroupInstance = freeLODGroupDataHandles[--freeHandlesCount];
lodGroupDataHash.TryAdd(lodGroupID, lodGroupInstance);
}
else
{
previousRendererCount += lodGroupsData.ElementAt(lodGroupInstance.index).rendererCount;
}
lodGroupInstances[i] = lodGroupInstance;
}
freeLODGroupDataHandles.ResizeUninitialized(freeHandlesCount);
lodGroupsData.ResizeUninitialized(lodDataLength);
lodGroupCullingData.ResizeUninitialized(lodDataLength);
return previousRendererCount;
}
}
}

2
Packages/com.unity.render-pipelines.core/Runtime/GPUDriven/LODGroupDataPoolBurst.cs.meta

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ad57195e4230c9344a64d902de871991

3
Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeReferenceVolume.cs

@ -1685,6 +1685,9 @@ namespace UnityEngine.Rendering
//Ensure that all currently loaded scenes belong to the same set.
foreach (var data in perSceneDataList)
{
if (UnityEditor.SceneManagement.EditorSceneManager.IsPreviewScene(data.gameObject.scene))
continue; // Ignore preview scenes - they are needed to make closed subscenes work
var set = ProbeVolumeBakingSet.GetBakingSetForScene(data.gameObject.scene);
if (set != bakingSet)
return false;

1
Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolume.hlsl

@ -749,6 +749,7 @@ void EvaluateAPVL1L2(APVSample apvSample, float3 N, out float3 diffuseLighting)
// -------------------------------------------------------------
void EvaluateAdaptiveProbeVolume(APVSample apvSample, float3 normalWS, out float3 bakeDiffuseLighting)
{
bakeDiffuseLighting = float3(0.0f, 0.0f, 0.0f);
if (apvSample.status != APV_SAMPLE_STATUS_INVALID)
{
apvSample.Decode();

4
Packages/com.unity.render-pipelines.core/Runtime/Lighting/ProbeVolume/ProbeVolumePerSceneData.cs

@ -95,7 +95,7 @@ namespace UnityEngine.Rendering
void OnEnable()
{
#if UNITY_EDITOR
#if UNITY_EDITOR
// In the editor, always refresh the GUID as it may become out of date is scene is duplicated or other weird things
// This field is serialized, so it will be available in standalones, where it can't change anymore.
// Only change the GUID if the new one is valid.
@ -105,7 +105,7 @@ namespace UnityEngine.Rendering
sceneGUID = newGUID;
EditorUtility.SetDirty(this);
}
#endif
#endif
ProbeReferenceVolume.instance.RegisterPerSceneData(this);
}

1
Packages/com.unity.render-pipelines.core/Runtime/PostProcessing/LensFlareDataSRP.cs

@ -1,4 +1,3 @@
using NUnit.Framework;
using UnityEngine.Serialization;
namespace UnityEngine.Rendering

4
Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/IRenderGraphBuilder.cs

@ -228,6 +228,10 @@ namespace UnityEngine.Rendering.RenderGraphModule
/// to match the index passed to SetInputAttachment for this texture.
///
/// </summary>
/// <remarks>
/// This API is not universally supported across all platforms. In particular, using input attachments in combination with MSAA may be unsupported on certain targets.
/// To ensure compatibility, use `RenderGraphUtils.IsFramebufferFetchSupportedOnCurrentPlatform` to verify support at runtime, as platform capabilities may vary.
/// </remarks>
/// <param name="tex">Texture to use during this pass.</param>
/// <param name="index">Index the shader will use to access this texture.</param>
/// <param name="flags">How this pass will access the texture. Default value is set to AccessFlag.Read. Writing is currently not supported on any platform. </param>

21
Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraph.cs

@ -529,7 +529,7 @@ namespace UnityEngine.Rendering.RenderGraphModule
nativeCompiler?.Cleanup();
m_CompilationCache?.Clear();
DelegateHashCodeUtils.ClearCache();
}
@ -751,6 +751,25 @@ namespace UnityEngine.Rendering.RenderGraphModule
return m_Resources.CreateTexture(m_Resources.GetTextureResourceDesc(texture.handle));
}
/// <summary>
/// Create a new Render Graph Texture resource using the descriptor from another texture.
/// </summary>
/// <remarks>
/// This API cannot be called during the Render Graph execution, please call it outside of SetRenderFunc().
/// </remarks>
/// <param name="texture">Texture from which the descriptor should be used.</param>
/// <param name="name">The destination texture name.</param>
/// <param name="clear">Texture needs to be cleared on first use.</param>
/// <returns>A new TextureHandle.</returns>
public TextureHandle CreateTexture(TextureHandle texture, string name, bool clear = false)
{
var destinationDesc = GetTextureDesc(texture);
destinationDesc.name = name;
destinationDesc.clearBuffer = clear;
return m_Resources.CreateTexture(destinationDesc);
}
/// <summary>
/// Create a new Render Graph Texture if the passed handle is invalid and use said handle as output.
/// If the passed handle is valid, no texture is created.

22
Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphBuilders.cs

@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using UnityEngine.Experimental.Rendering;
using static UnityEngine.Rendering.RenderGraphModule.RenderGraph;
namespace UnityEngine.Rendering.RenderGraphModule
{
@ -399,6 +400,8 @@ namespace UnityEngine.Rendering.RenderGraphModule
public void SetInputAttachment(TextureHandle tex, int index, AccessFlags flags, int mipLevel, int depthSlice)
{
CheckFrameBufferFetchEmulationIsSupported(tex);
CheckUseFragment(tex, false);
ResourceHandle result = UseResource(tex.handle, flags);
// Note the version for the attachments is a bit arbitrary so we just use the latest for now
@ -514,6 +517,25 @@ namespace UnityEngine.Rendering.RenderGraphModule
}
}
[Conditional("DEVELOPMENT_BUILD"), Conditional("UNITY_EDITOR")]
void CheckFrameBufferFetchEmulationIsSupported(in TextureHandle tex)
{
if (enableValidityChecks)
{
if (!Util.RenderGraphUtils.IsFramebufferFetchEmulationSupportedOnCurrentPlatform())
{
throw new InvalidOperationException($"This API is not supported on the current platform: {SystemInfo.graphicsDeviceType}");
}
if (!Util.RenderGraphUtils.IsFramebufferFetchEmulationMSAASupportedOnCurrentPlatform())
{
var sourceInfo = m_RenderGraph.GetRenderTargetInfo(tex);
if (sourceInfo.bindMS)
throw new InvalidOperationException($"This API is not supported with MSAA attachments on the current platform: {SystemInfo.graphicsDeviceType}");
}
}
}
public void SetShadingRateImageAttachment(in TextureHandle sriTextureHandle)
{
CheckNotUseFragment(sriTextureHandle);

49
Packages/com.unity.render-pipelines.core/Runtime/RenderGraph/RenderGraphUtilsBlit.cs

@ -17,6 +17,9 @@ namespace UnityEngine.Rendering.RenderGraphModule.Util
/// <returns>Returns true if the shader features required by the copy pass is supported for MSAA, otherwise will it return false.</returns>
public static bool CanAddCopyPassMSAA()
{
if (!IsFramebufferFetchEmulationMSAASupportedOnCurrentPlatform())
return false;
return Blitter.CanCopyMSAA();
}
@ -27,9 +30,53 @@ namespace UnityEngine.Rendering.RenderGraphModule.Util
/// <returns>Returns true if the shader features required by the copy pass is supported for MSAA, otherwise will it return false.</returns>
public static bool CanAddCopyPassMSAA(in TextureDesc sourceDesc)
{
if (!IsFramebufferFetchEmulationMSAASupportedOnCurrentPlatform())
return false;
return Blitter.CanCopyMSAA(sourceDesc);
}
internal static bool IsFramebufferFetchEmulationSupportedOnCurrentPlatform()
{
#if PLATFORM_WEBGL
if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES3)
return false;
#endif
return true;
}
internal static bool IsFramebufferFetchEmulationMSAASupportedOnCurrentPlatform()
{
// TODO: Temporarily disable this utility pending a more efficient solution for supporting or disabling framebuffer fetch emulation on PS4/PS5.
return (SystemInfo.graphicsDeviceType != GraphicsDeviceType.PlayStation4
&& SystemInfo.graphicsDeviceType != GraphicsDeviceType.PlayStation5 && SystemInfo.graphicsDeviceType != GraphicsDeviceType.PlayStation5NGGC);
}
/// <summary>
/// Determines whether framebuffer fetch is supported on the current platform for the given texture.
/// This includes checking both general support for framebuffer fetch emulation and specific support
/// for multisampled (MSAA) textures.
/// </summary>
/// <param name="graph">The RenderGraph adding this pass to.</param>
/// <param name="tex">The texture handle to validate for framebuffer fetch compatibility.</param>
/// <returns>
/// Returns true if framebuffer fetch is supported on the current platform for the given texture;
/// otherwise, returns false.
/// </returns>
public static bool IsFramebufferFetchSupportedOnCurrentPlatform(this RenderGraph graph, in TextureHandle tex)
{
if (!IsFramebufferFetchEmulationSupportedOnCurrentPlatform())
return false;
if (!IsFramebufferFetchEmulationMSAASupportedOnCurrentPlatform())
{
var sourceInfo = graph.GetRenderTargetInfo(tex);
if (sourceInfo.msaaSamples > 1)
return sourceInfo.bindMS;
}
return true;
}
class CopyPassData
{
public bool isMSAA;
@ -90,7 +137,7 @@ namespace UnityEngine.Rendering.RenderGraphModule.Util
// It would have 1 if the MSAA pass is not able to be used for target and 2 otherwise.
// https://docs.unity3d.com/2017.4/Documentation/Manual/SL-ShaderCompileTargets.html
// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-to-get-sample-position
if (isMSAA && !Blitter.CanCopyMSAA(sourceDesc))
if (isMSAA && !CanAddCopyPassMSAA(sourceDesc))
throw new ArgumentException("Target does not support MSAA for AddCopyPass. Please use the blit alternative or use non MSAA textures.");
using (var builder = graph.AddRasterRenderPass<CopyPassData>(passName, out var passData, file, line))

29
Packages/com.unity.render-pipelines.core/Runtime/RenderPipelineResources/GPUDriven/InstanceOcclusionCullingKernels.compute

@ -61,7 +61,7 @@ SphereBound LoadInstanceBoundingSphere(uint instanceID)
{
float4 data = asfloat(_InstanceDataBuffer.Load4(_BoundingSphereInstanceDataAddress + instanceID * 16));
SphereBound b;
b.center = data.xyz;
b.center = data.xyz;
b.radius = data.w;
return b;
}
@ -105,7 +105,7 @@ void CopyInstances(uint dispatchIdx : SV_DispatchThreadID)
uint argsBase = DRAW_ARGS_INDEX(dispatchIdx);
_DrawArgs[argsBase + 0] = drawInfo.indexCount; // IndirectDrawIndexedArgs.indexCountPerInstance
_DrawArgs[argsBase + 1] = drawInfo.maxInstanceCount << _InstanceMultiplierShift; // IndirectDrawIndexedArgs.instanceCount
_DrawArgs[argsBase + 1] = (drawInfo.maxInstanceCountAndTopology >> 3) << _InstanceMultiplierShift; // IndirectDrawIndexedArgs.instanceCount
_DrawArgs[argsBase + 2] = drawInfo.firstIndex; // IndirectDrawIndexedArgs.startIndex
_DrawArgs[argsBase + 3] = drawInfo.baseVertex; // IndirectDrawIndexedArgs.baseVertexIndex
_DrawArgs[argsBase + 4] = 0; // IndirectDrawIndexedArgs.startInstance
@ -120,6 +120,19 @@ void CopyInstances(uint dispatchIdx : SV_DispatchThreadID)
}
}
uint GetPrimitiveCount(uint indexCount, uint topology, bool nativeQuads)
{
switch (topology)
{
case /*MeshTopology.Triangles*/ 0: return indexCount / 3;
case /*MeshTopology.Quads*/ 2: return nativeQuads ? (indexCount / 4) : (indexCount / 4 * 2);
case /*MeshTopology.Lines*/ 3: return indexCount / 2;
case /*MeshTopology.LineStrip*/ 4: return (indexCount >= 1) ? (indexCount - 1) : 0;
case /*MeshTopology.Points*/ 5: return indexCount;
default: return 0;
}
}
[numthreads(64,1,1)]
void CullInstances(uint instanceInfoOffset : SV_DispatchThreadID)
{
@ -157,7 +170,7 @@ void CullInstances(uint instanceInfoOffset : SV_DispatchThreadID)
isOccludedInAll = false;
}
isVisible = !isOccludedInAll;
#ifdef OCCLUSION_FIRST_PASS
// if we failed the occlusion check, then add to the list for the second pass
if (!isVisible)
@ -173,8 +186,16 @@ void CullInstances(uint instanceInfoOffset : SV_DispatchThreadID)
if (_DebugCounterIndex >= 0)
{
// TODO: sum each within wave, first thread in wave issues atomic add to memory
int counterIndex = isVisible ? INSTANCEOCCLUSIONTESTDEBUGCOUNTER_NOT_OCCLUDED : INSTANCEOCCLUSIONTESTDEBUGCOUNTER_OCCLUDED;
int counterIndex = isVisible ? INSTANCEOCCLUSIONTESTDEBUGCOUNTER_INSTANCES_NOT_OCCLUDED : INSTANCEOCCLUSIONTESTDEBUGCOUNTER_INSTANCES_OCCLUDED;
InterlockedAdd(_OcclusionDebugCounters[_DebugCounterIndex*INSTANCEOCCLUSIONTESTDEBUGCOUNTER_COUNT + counterIndex], 1);
IndirectDrawInfo drawInfo = LoadDrawInfo(drawOffset);
uint argsBase = DRAW_ARGS_INDEX(drawOffset);
uint indexCount = _DrawArgs[argsBase + 0]; // IndirectDrawIndexedArgs.indexCountPerInstance
uint topology = drawInfo.maxInstanceCountAndTopology & 7;
uint primitiveCount = GetPrimitiveCount(indexCount, topology, false);
counterIndex = isVisible ? INSTANCEOCCLUSIONTESTDEBUGCOUNTER_PRIMITIVES_NOT_OCCLUDED : INSTANCEOCCLUSIONTESTDEBUGCOUNTER_PRIMITIVES_OCCLUDED;
InterlockedAdd(_OcclusionDebugCounters[_DebugCounterIndex*INSTANCEOCCLUSIONTESTDEBUGCOUNTER_COUNT + counterIndex], primitiveCount);
}
if (isVisible)

45
Packages/com.unity.render-pipelines.core/Runtime/Volume/VolumeManager.cs

@ -137,11 +137,23 @@ namespace UnityEngine.Rendering
.OrderBy(i => i.Item1)
.ToList();
}
Type[] m_BaseComponentTypeArray;
/// <summary>
/// The current list of all available types that derive from <see cref="VolumeComponent"/>.
/// </summary>
public Type[] baseComponentTypeArray { get; internal set; } // internal only for tests
public Type[] baseComponentTypeArray
{
get
{
if (isInitialized)
return m_BaseComponentTypeArray;
throw new InvalidOperationException($"{nameof(VolumeManager)}.{nameof(instance)}.{nameof(baseComponentTypeArray)} cannot be called before the {nameof(VolumeManager)} is initialized. (See {nameof(VolumeManager)}.{nameof(instance)}.{nameof(isInitialized)} and {nameof(RenderPipelineManager)} for creation callback).");
}
internal set => m_BaseComponentTypeArray = value; // internal only for tests
}
/// <summary>
/// Global default profile that provides default values for volume components. VolumeManager applies
@ -242,13 +254,19 @@ namespace UnityEngine.Rendering
Debug.Assert(m_CreatedVolumeStacks.Count == 0);
LoadBaseTypes(GraphicsSettings.currentRenderPipelineAssetType);
InitializeInternal(globalDefaultVolumeProfile, qualityDefaultVolumeProfile);
}
//This is called by test where the basetypes are tuned for the purpose of the test.
internal void InitializeInternal(VolumeProfile globalDefaultVolumeProfile = null, VolumeProfile qualityDefaultVolumeProfile = null)
{
InitializeVolumeComponents();
globalDefaultProfile = globalDefaultVolumeProfile;
qualityDefaultProfile = qualityDefaultVolumeProfile;
EvaluateVolumeDefaultState();
m_DefaultStack = CreateStack();
m_DefaultStack = CreateStackInternal();
stack = m_DefaultStack;
isInitialized = true;
@ -347,9 +365,17 @@ namespace UnityEngine.Rendering
/// <seealso cref="VolumeStack"/>
/// <seealso cref="Update(VolumeStack,Transform,LayerMask)"/>
public VolumeStack CreateStack()
{
if (!isInitialized)
throw new InvalidOperationException($"{nameof(VolumeManager)}.{nameof(instance)}.{nameof(CreateStack)}() cannot be called before the {nameof(VolumeManager)} is initialized. (See {nameof(VolumeManager)}.{nameof(instance)}.{nameof(isInitialized)} and {nameof(RenderPipelineManager)} for creation callback).");
return CreateStackInternal();
}
VolumeStack CreateStackInternal()
{
var stack = new VolumeStack();
stack.Reload(baseComponentTypeArray);
stack.Reload(m_BaseComponentTypeArray);
m_CreatedVolumeStacks.Add(stack);
return stack;
}
@ -421,15 +447,18 @@ namespace UnityEngine.Rendering
list.Add(t);
}
baseComponentTypeArray = list.ToArray();
m_BaseComponentTypeArray = list.ToArray();
}
}
internal void InitializeVolumeComponents()
{
if (m_BaseComponentTypeArray == null || m_BaseComponentTypeArray.Length == 0)
return;
// Call custom static Init method if present
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
foreach (var type in baseComponentTypeArray)
foreach (var type in m_BaseComponentTypeArray)
{
var initMethod = type.GetMethod("Init", flags);
if (initMethod != null)
@ -440,9 +469,9 @@ namespace UnityEngine.Rendering
}
// Evaluate static default values for VolumeComponents, which is the baseline to reset the values to at the start of Update.
internal void EvaluateVolumeDefaultState()
void EvaluateVolumeDefaultState()
{
if (baseComponentTypeArray == null || baseComponentTypeArray.Length == 0)
if (m_BaseComponentTypeArray == null || m_BaseComponentTypeArray.Length == 0)
return;
using var profilerScope = k_ProfilerMarkerEvaluateVolumeDefaultState.Auto();
@ -453,7 +482,7 @@ namespace UnityEngine.Rendering
// First, default-construct all VolumeComponents
List<VolumeComponent> componentsDefaultStateList = new();
foreach (var type in baseComponentTypeArray)
foreach (var type in m_BaseComponentTypeArray)
{
componentsDefaultStateList.Add((VolumeComponent) ScriptableObject.CreateInstance(type));
}

18
Packages/com.unity.render-pipelines.core/Runtime/XR/XRPass.cs

@ -24,6 +24,7 @@ namespace UnityEngine.Experimental.Rendering
internal int cullingPassId;
internal bool copyDepth;
internal bool hasMotionVectorPass;
internal bool spaceWarpRightHandedNDC;
#if ENABLE_VR && ENABLE_XR_MODULE
internal UnityEngine.XR.XRDisplaySubsystem.XRRenderPass xrSdkRenderPass;
@ -105,6 +106,22 @@ namespace UnityEngine.Experimental.Rendering
/// </summary>
public bool hasMotionVectorPass { get; private set; }
/// <summary>
/// Reports which NDC convention the render pipeline should use when calculating motion vectors.
/// if <c>true</c>, motion vector data must use the right-handed NDC space. If <c>false</c> motion vector data
/// must use the left-handed NDC space.
/// </summary>
/// <remarks>
/// The render pipeline must write motion vector data to the <see cref="UnityEngine.XR.XRDisplaySubsystem.XRRenderPass.motionVectorRenderTarget"/>.
///
/// > [!NOTE]
/// > The OpenXR specification doesn't specify which coordinate space convention to use for the
/// > motion vector data. Unity only supports SpaceWarp when using the Vulkan graphics API, which uses the right-handed convention for normalized device coordinates, but
/// > devices still can choose either convention for motion data when the
/// > application is using the Vulkan graphics API.
/// </remarks>
public bool spaceWarpRightHandedNDC { get; private set; }
/// <summary>
/// If true, is the first pass of a xr camera
/// </summary>
@ -480,6 +497,7 @@ namespace UnityEngine.Experimental.Rendering
motionVectorRenderTarget = new RenderTargetIdentifier(createInfo.motionVectorRenderTarget, 0, CubemapFace.Unknown, -1);
motionVectorRenderTargetDesc = createInfo.motionVectorRenderTargetDesc;
hasMotionVectorPass = createInfo.hasMotionVectorPass;
spaceWarpRightHandedNDC = createInfo.spaceWarpRightHandedNDC;
m_OcclusionMesh.SetMaterial(createInfo.occlusionMeshMaterial);
occlusionMeshScale = createInfo.occlusionMeshScale;
foveatedRenderingInfo = createInfo.foveatedRenderingInfo;

1
Packages/com.unity.render-pipelines.core/Runtime/XR/XRSystem.cs

@ -533,6 +533,7 @@ namespace UnityEngine.Experimental.Rendering
multipassId = layout.GetActivePasses().Count,
cullingPassId = xrRenderPass.cullingPassIndex,
copyDepth = xrRenderPass.shouldFillOutDepth,
spaceWarpRightHandedNDC = xrRenderPass.spaceWarpRightHandedNDC,
xrSdkRenderPass = xrRenderPass
};

2
Packages/com.unity.render-pipelines.core/package.json

@ -14,5 +14,5 @@
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.rendering.light-transport": "1.0.1"
},
"_fingerprint": "71b4bdac1964f74b866160605ee9150cf79ab359"
"_fingerprint": "943f3af6fe14719bad5cae2cf73687f86e685e1b"
}

64
Packages/com.unity.render-pipelines.high-definition/Editor/Material/Decal/DecalProjectorEditor.cs

@ -630,9 +630,9 @@ namespace UnityEditor.Rendering.HighDefinition
m_SizeValues[axe].floatValue = newSize;
}
internal void MinMaxSliderWithFields(GUIContent label, ref float minValue, ref float maxValue, float minLimit, float maxLimit)
internal void MinMaxSliderWithFields(Rect rect, GUIContent label, ref float minValue, ref float maxValue, float minLimit, float maxLimit)
{
var rect = EditorGUILayout.GetControlRect();
// Reserve label space and push the slider rect to the right
rect = EditorGUI.PrefixLabel(rect, label);
const float fieldWidth = 40, padding = 4;
@ -662,6 +662,45 @@ namespace UnityEditor.Rendering.HighDefinition
}
}
void DoRenderingLayerMask()
{
Rect rect = EditorGUILayout.GetControlRect(true, 18f);
EditorGUI.BeginProperty(rect, k_DecalLayerMaskContent, m_DecalLayerMask);
var mask = m_DecalLayerMask.uintValue;
EditorGUI.BeginChangeCheck();
mask = EditorGUI.RenderingLayerMaskField(rect, k_DecalLayerMaskContent, (RenderingLayerMask)mask, EditorStyles.layerMaskField);
if (EditorGUI.EndChangeCheck())
{
m_DecalLayerMask.intValue = unchecked((int) mask);
serializedObject.ApplyModifiedProperties();
}
EditorGUI.EndProperty();
}
void DoAngleFade()
{
// The slider edits 2 different properties. Both can be overridden separately.
var rect = EditorGUILayout.GetControlRect();
EditorGUI.BeginProperty(rect, k_AngleFadeContent, m_StartAngleFadeProperty);
EditorGUI.BeginProperty(rect, k_AngleFadeContent, m_EndAngleFadeProperty);
float angleFadeMinValue = m_StartAngleFadeProperty.floatValue;
float angleFadeMaxValue = m_EndAngleFadeProperty.floatValue;
EditorGUI.BeginChangeCheck();
MinMaxSliderWithFields(rect,k_AngleFadeContent, ref angleFadeMinValue, ref angleFadeMaxValue, 0.0f, 180.0f);
if (EditorGUI.EndChangeCheck())
{
m_StartAngleFadeProperty.floatValue = angleFadeMinValue;
m_EndAngleFadeProperty.floatValue = angleFadeMaxValue;
serializedObject.ApplyModifiedProperties();
}
EditorGUI.EndProperty();
EditorGUI.EndProperty();
}
public override void OnInspectorGUI()
{
bool supportDecals = false;
@ -735,14 +774,7 @@ namespace UnityEditor.Rendering.HighDefinition
decalLayerEnabled = supportDecals && hdrp.currentPlatformRenderPipelineSettings.supportDecalLayers;
using (new EditorGUI.DisabledScope(!decalLayerEnabled))
{
var mask = m_DecalLayerMask.uintValue;
EditorGUI.BeginChangeCheck();
mask = EditorGUILayout.RenderingLayerMaskField(k_DecalLayerMaskContent, mask);
if (EditorGUI.EndChangeCheck())
{
m_DecalLayerMask.intValue = unchecked((int) mask);
EditorUtility.SetDirty(m_DecalLayerMask.serializedObject.targetObject);
}
DoRenderingLayerMask();
}
}
@ -758,15 +790,7 @@ namespace UnityEditor.Rendering.HighDefinition
EditorGUILayout.PropertyField(m_FadeScaleProperty, k_FadeScaleContent);
using (new EditorGUI.DisabledScope(!decalLayerEnabled))
{
float angleFadeMinValue = m_StartAngleFadeProperty.floatValue;
float angleFadeMaxValue = m_EndAngleFadeProperty.floatValue;
EditorGUI.BeginChangeCheck();
MinMaxSliderWithFields(k_AngleFadeContent, ref angleFadeMinValue, ref angleFadeMaxValue, 0.0f, 180.0f);
if (EditorGUI.EndChangeCheck())
{
m_StartAngleFadeProperty.floatValue = angleFadeMinValue;
m_EndAngleFadeProperty.floatValue = angleFadeMaxValue;
}
DoAngleFade();
}
if (!decalLayerEnabled)
@ -985,7 +1009,7 @@ namespace UnityEditor.Rendering.HighDefinition
}
if (shader != null)
{
{
var material = new Material(shader);
AssetDatabase.CreateAsset(material, materialName);
ProjectWindowUtil.ShowCreatedAsset(material);

4
Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/FogVolumePropertyBlock.cs

@ -20,6 +20,7 @@ namespace UnityEditor.Rendering.HighDefinition.ShaderGraph
public static GUIContent blendMode = new GUIContent("Blend Mode", "Determines how the fog volume will blend with other fogs in the scene.");
public static GUIContent singleScatteringAlbedo = new GUIContent("Single Scattering Albedo", "The color this fog scatters light to.");
public static GUIContent fogDistance = new GUIContent("Fog Distance", "Density at the base of the fog. Determines how far you can see through the fog in meters.");
public static GUIContent debugSymbolsText = new GUIContent("Debug Symbols", "When enabled, HDRP activates d3d11 debug symbols for this Shader.");
}
protected override string title => "Fog Volume Options";
@ -35,6 +36,9 @@ namespace UnityEditor.Rendering.HighDefinition.ShaderGraph
// AddProperty(Styles.singleScatteringAlbedo, () => fogData.singleScatteringAlbedo, (newValue) => fogData.singleScatteringAlbedo = newValue);
// AddProperty(Styles.fogDistance, () => fogData.fogDistance, (newValue) => fogData.fogDistance = newValue);
AddProperty(Styles.blendMode, () => fogData.blendMode, (newValue) => fogData.blendMode = newValue);
if (Unsupported.IsDeveloperMode())
AddProperty(Styles.debugSymbolsText, () => systemData.debugSymbols, (newValue) => systemData.debugSymbols = newValue);
}
}
}

8
Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/FogVolumeSubTarget.cs

@ -172,7 +172,7 @@ namespace UnityEditor.Rendering.HighDefinition.ShaderGraph
{
// Definition
displayName = HDShaderPassNames.s_FogVolumeVoxelizeStr,
referenceName = "SHADERPASS_FOGVOLUME_VOXELIZATION",
referenceName = "SHADERPASS_FOG_VOLUME_VOXELIZATION",
lightMode = HDShaderPassNames.s_FogVolumeVoxelizeStr,
useInPreview = false,
@ -200,7 +200,7 @@ namespace UnityEditor.Rendering.HighDefinition.ShaderGraph
{
// Definition
displayName = "ShaderGraphPreview",
referenceName = "SHADERPASS_FOGVOLUME_PREVIEW",
referenceName = "SHADERPASS_FOG_VOLUME_PREVIEW",
lightMode = "ShaderGraphPreview",
useInPreview = true,
@ -228,7 +228,7 @@ namespace UnityEditor.Rendering.HighDefinition.ShaderGraph
{
// Definition
displayName = HDShaderPassNames.s_VolumetricFogVFXOverdrawDebugStr,
referenceName = "SHADERPASS_FOGVOLUME_OVERDRAW_DEBUG",
referenceName = "SHADERPASS_FOG_VOLUME_OVERDRAW_DEBUG",
lightMode = HDShaderPassNames.s_VolumetricFogVFXOverdrawDebugStr,
useInPreview = true,
@ -308,6 +308,7 @@ namespace UnityEditor.Rendering.HighDefinition.ShaderGraph
const string kPacking = "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl";
const string kColor = "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl";
const string kFunctions = "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl";
const string kVoxelizationTransforms = "Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/VoxelizationTransforms.hlsl";
const string kVoxelizePass = "Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/ShaderPassVoxelize.hlsl";
const string kPreviewPass = "Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/ShaderPassPreview.hlsl";
const string kOverdrawPass = "Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/OverdrawDebug.hlsl";
@ -318,6 +319,7 @@ namespace UnityEditor.Rendering.HighDefinition.ShaderGraph
{ kColor, IncludeLocation.Pregraph },
{ kFunctions, IncludeLocation.Pregraph },
{ CoreIncludes.MinimalCorePregraph },
{ kVoxelizationTransforms, IncludeLocation.Pregraph },
{ kVoxelizePass, IncludeLocation.Postgraph },
};

2
Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/OverdrawDebug.hlsl

@ -1,4 +1,4 @@
#if SHADERPASS != SHADERPASS_FOGVOLUME_OVERDRAW_DEBUG
#if SHADERPASS != SHADERPASS_FOG_VOLUME_OVERDRAW_DEBUG
#error SHADERPASS_is_not_correctly_define
#endif

2
Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/ShaderPassPreview.hlsl

@ -1,4 +1,4 @@
#if SHADERPASS != SHADERPASS_FOGVOLUME_PREVIEW
#if SHADERPASS != SHADERPASS_FOG_VOLUME_PREVIEW
#error SHADERPASS_is_not_correctly_define
#endif

13
Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/ShaderPassVoxelize.hlsl

@ -1,4 +1,4 @@
#if SHADERPASS != SHADERPASS_FOGVOLUME_VOXELIZATION
#if SHADERPASS != SHADERPASS_FOG_VOLUME_VOXELIZATION
#error SHADERPASS_is_not_correctly_define
#endif
@ -91,14 +91,13 @@ VertexToFragment Vert(uint instanceId : INSTANCEID_SEMANTIC, uint vertexId : VER
return output;
}
FragInputs BuildFragInputs(VertexToFragment v2f, float3 voxelPositionOS, float3 voxelClipSpace)
FragInputs BuildFragInputs(VertexToFragment v2f, float3 voxelPositionWS, float3 voxelClipSpace)
{
FragInputs output;
ZERO_INITIALIZE(FragInputs, output);
float3 positionWS = mul(UNITY_MATRIX_M, float4(voxelPositionOS, 1)).xyz;
output.positionSS = v2f.positionCS;
output.positionRWS = output.positionPredisplacementRWS = positionWS;
output.positionRWS = output.positionPredisplacementRWS = voxelPositionWS;
output.positionPixel = uint2(v2f.positionCS.xy);
output.texCoord0 = float4(saturate(voxelClipSpace * 0.5 + 0.5), 0);
output.tangentToWorld = k_identity3x3;
@ -140,9 +139,11 @@ void Frag(VertexToFragment v2f, out float4 outColor : SV_Target0)
float3 rayoriginWS = GetCurrentViewPosition();
float3 voxelCenterWS = rayoriginWS + sliceDistance * raycenterDirWS;
// Build rotation matrix from normalized OBB axes to transform the world space position
float3x3 obbFrame = float3x3(_VolumetricMaterialObbRight.xyz, _VolumetricMaterialObbUp.xyz, cross(_VolumetricMaterialObbRight.xyz, _VolumetricMaterialObbUp.xyz));
float3 voxelCenterBS = mul(voxelCenterWS - _VolumetricMaterialObbCenter.xyz + _WorldSpaceCameraPos.xyz, transpose(obbFrame));
// Rotate world position around the center of the local fog OBB
float3 voxelCenterBS = mul(GetAbsolutePositionWS(voxelCenterWS - _VolumetricMaterialObbCenter.xyz), transpose(obbFrame));
float3 voxelCenterCS = (voxelCenterBS * rcp(_VolumetricMaterialObbExtents.xyz));
// Still need to clip pixels outside of the box because of the froxel buffer shape
@ -150,7 +151,7 @@ void Frag(VertexToFragment v2f, out float4 outColor : SV_Target0)
if (!overlap)
clip(-1);
FragInputs fragInputs = BuildFragInputs(v2f, voxelCenterBS, voxelCenterCS);
FragInputs fragInputs = BuildFragInputs(v2f, voxelCenterWS, voxelCenterCS);
GetVolumeData(fragInputs, v2f.viewDirectionWS, albedo, extinction);
// Accumulate volume parameters

36
Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/VoxelizationTransforms.hlsl

@ -0,0 +1,36 @@
#pragma once
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricLighting/HDRenderPipeline.VolumetricLighting.cs.hlsl"
// Overrides the transform functions that would use object matrices in the fog as they are not available due to the indirect draw
// Instead we can re-build the object matrix from the OBB of the fog object
float4x4 BuildWorldToObjectMatrixFromLocalFogOBB()
{
float3x3 rotation = float3x3(
_VolumetricMaterialObbRight.xyz,
_VolumetricMaterialObbUp.xyz,
cross(_VolumetricMaterialObbRight.xyz, _VolumetricMaterialObbUp.xyz)
);
// inverse rotation
rotation = transpose(rotation);
// inverse translation
float3 inverseTranslation = -(mul(_VolumetricMaterialObbCenter.xyz, rotation));
// Build matrix
float4x4 objectMatrix = 0;
objectMatrix._m00_m10_m20 = rotation[0];
objectMatrix._m01_m11_m21 = rotation[1];
objectMatrix._m02_m12_m22 = rotation[2];
objectMatrix._m03_m13_m23_m33 = float4(inverseTranslation, 1);
return objectMatrix;
}
float3 TransformWorldToObjectFog(float3 positionRWS)
{
float3 posWS = GetAbsolutePositionWS(positionRWS);
return mul(BuildWorldToObjectMatrixFromLocalFogOBB(), float4(posWS, 1)).xyz;
}

7
Packages/com.unity.render-pipelines.high-definition/Editor/Material/FogVolume/ShaderGraph/VoxelizationTransforms.hlsl.meta

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 623770b432f006f49af1b65f726bf86f
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Packages/com.unity.render-pipelines.high-definition/Editor/Material/ShaderGraph/Templates/Pixel.template.hlsl

@ -25,12 +25,20 @@ SurfaceDescriptionInputs FragInputsToSurfaceDescriptionInputs(FragInputs input,
$SurfaceDescriptionInputs.TangentSpaceViewDirection: float3x3 tangentSpaceTransform = float3x3(output.WorldSpaceTangent,output.WorldSpaceBiTangent,output.WorldSpaceNormal);
$SurfaceDescriptionInputs.TangentSpaceViewDirection: output.TangentSpaceViewDirection = TransformWorldToTangent(output.WorldSpaceViewDirection, tangentSpaceTransform);
$SurfaceDescriptionInputs.WorldSpacePosition: output.WorldSpacePosition = input.positionRWS;
#if SHADERPASS != SHADERPASS_FOG_VOLUME_VOXELIZATION
$SurfaceDescriptionInputs.ObjectSpacePosition: output.ObjectSpacePosition = TransformWorldToObject(input.positionRWS);
#else
$SurfaceDescriptionInputs.ObjectSpacePosition: output.ObjectSpacePosition = TransformWorldToObjectFog(input.positionRWS);
#endif
$SurfaceDescriptionInputs.ViewSpacePosition: output.ViewSpacePosition = TransformWorldToView(input.positionRWS);
$SurfaceDescriptionInputs.TangentSpacePosition: output.TangentSpacePosition = float3(0.0f, 0.0f, 0.0f);
$SurfaceDescriptionInputs.AbsoluteWorldSpacePosition: output.AbsoluteWorldSpacePosition = GetAbsolutePositionWS(input.positionRWS);
$SurfaceDescriptionInputs.WorldSpacePositionPredisplacement: output.WorldSpacePositionPredisplacement = input.positionPredisplacementRWS;
#if SHADERPASS != SHADERPASS_FOG_VOLUME_VOXELIZATION
$SurfaceDescriptionInputs.ObjectSpacePositionPredisplacement: output.ObjectSpacePositionPredisplacement = TransformWorldToObject(input.positionPredisplacementRWS);
#else
$SurfaceDescriptionInputs.ObjectSpacePositionPredisplacement: output.ObjectSpacePositionPredisplacement = TransformWorldToObjectFog(input.positionPredisplacementRWS);
#endif
$SurfaceDescriptionInputs.ViewSpacePositionPredisplacement: output.ViewSpacePositionPredisplacement = TransformWorldToView(input.positionPredisplacementRWS);
$SurfaceDescriptionInputs.TangentSpacePositionPredisplacement: output.TangentSpacePositionPredisplacement = float3(0.0f, 0.0f, 0.0f);
$SurfaceDescriptionInputs.AbsoluteWorldSpacePositionPredisplacement: output.AbsoluteWorldSpacePositionPredisplacement = GetAbsolutePositionWS(input.positionPredisplacementRWS);

6
Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.Debug.cs

@ -1482,6 +1482,7 @@ namespace UnityEngine.Rendering.HighDefinition
public bool decalsEnabled;
public BufferHandle perVoxelOffset;
public BufferHandle lightList;
public DBufferOutput dbuffer;
public GBufferOutput gbuffer;
public TextureHandle depthBuffer;
@ -1564,6 +1565,8 @@ namespace UnityEngine.Rendering.HighDefinition
passData.decalsEnabled = (hdCamera.frameSettings.IsEnabled(FrameSettingsField.Decals)) && (DecalSystem.m_DecalDatasCount > 0);
passData.perVoxelOffset = builder.ReadBuffer(lightLists.perVoxelOffset);
passData.lightList = builder.ReadBuffer(lightLists.lightList);
passData.dbuffer = ReadDBuffer(dbuffer, builder);
passData.clearColorTexture = Compositor.CompositionManager.GetClearTextureForStackedCamera(hdCamera); // returns null if is not a stacked camera
@ -1583,6 +1586,9 @@ namespace UnityEngine.Rendering.HighDefinition
BindDefaultTexturesLightingBuffers(context.defaultResources, context.cmd);
if (data.lightList.IsValid())
context.cmd.SetGlobalBuffer(HDShaderIDs.g_vLightListTile, data.lightList);
BindDBufferGlobalData(data.dbuffer, context);
DrawOpaqueRendererList(context, data.frameSettings, data.opaqueRendererList);

3
Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/HDRenderPipeline.RenderGraph.cs

@ -45,8 +45,7 @@ namespace UnityEngine.Rendering.HighDefinition
// Caution: We require sun light here as some skies use the sun light to render, it means that UpdateSkyEnvironment must be called after PrepareLightsForGPU.
// TODO: Try to arrange code so we can trigger this call earlier and use async compute here to run sky convolution during other passes (once we move convolution shader to compute).
if (!m_CurrentDebugDisplaySettings.IsMatcapViewEnabled(hdCamera))
m_SkyManager.UpdateEnvironment(m_RenderGraph, hdCamera, GetMainLight(), m_CurrentDebugDisplaySettings);
m_SkyManager.UpdateEnvironment(m_RenderGraph, hdCamera, GetMainLight(), m_CurrentDebugDisplaySettings);
// We need to initialize the MipChainInfo here, so it will be available to any render graph pass that wants to use it during setup
// Be careful, ComputePackedMipChainInfo needs the render texture size and not the viewport size. Otherwise it would compute the wrong size.

3
Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/RaytracingLightLoop.hlsl

@ -24,7 +24,8 @@ void LightLoop( float3 V, PositionInputs posInput, PreLightData preLightData, BS
{
// Init LightLoop output structure
ZERO_INITIALIZE(LightLoopOutput, lightLoopOutput);
ApplyCameraRelativeXR(posInput.positionWS);
LightLoopContext context;
context.contactShadow = 1.0;
context.shadowContext = InitShadowContext();

3
Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs

@ -34,5 +34,8 @@ namespace UnityEngine.Rendering.HighDefinition
Constant,
FullScreenDebug,
PBRSky,
FogVolumePreview,
FogVolumeVoxelization,
FogVolumeOverdrawDebug,
}
}

3
Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl

@ -35,6 +35,9 @@
#define SHADERPASS_CONSTANT (25)
#define SHADERPASS_FULL_SCREEN_DEBUG (26)
#define SHADERPASS_PBRSKY (27)
#define SHADERPASS_FOG_VOLUME_PREVIEW (28)
#define SHADERPASS_FOG_VOLUME_VOXELIZATION (29)
#define SHADERPASS_FOG_VOLUME_OVERDRAW_DEBUG (30)
#endif

58
Packages/com.unity.render-pipelines.high-definition/Runtime/Sky/SkyManager.cs

@ -1236,41 +1236,49 @@ namespace UnityEngine.Rendering.HighDefinition
m_CurrentDebugDisplaySettings = debugSettings;
m_CurrentSunLight = sunLight;
SkyAmbientMode ambientMode = hdCamera.volumeStack.GetComponent<VisualEnvironment>().skyAmbientMode.value;
if (debugSettings.IsMatcapViewEnabled(hdCamera))
{
HDRenderPipeline.SetGlobalTexture(renderGraph, HDShaderIDs._SkyTexture, m_BlackCubemapArray);
HDRenderPipeline.SetGlobalBuffer(renderGraph, HDShaderIDs._AmbientProbeData, m_BlackAmbientProbeBuffer);
}
else
{
SkyAmbientMode ambientMode = hdCamera.volumeStack.GetComponent<VisualEnvironment>().skyAmbientMode.value;
UpdateEnvironment(renderGraph, hdCamera, hdCamera.lightingSky, sunLight, m_UpdateRequired, ambientMode == SkyAmbientMode.Dynamic, false, ambientMode);
UpdateEnvironment(renderGraph, hdCamera, hdCamera.lightingSky, sunLight, m_UpdateRequired, ambientMode == SkyAmbientMode.Dynamic, false, ambientMode);
// Preview camera will have a different sun, therefore the hash for the static lighting sky will change and force a recomputation
// because we only maintain one static sky. Since we don't care that the static lighting may be a bit different in the preview we never recompute
// and we use the one from the main camera.
bool forceStaticUpdate = false;
m_ActiveStaticSky = m_StaticLightingSkies.GetValueOrDefault(SceneManager.GetActiveScene().GetHashCode(), null);
// Preview camera will have a different sun, therefore the hash for the static lighting sky will change and force a recomputation
// because we only maintain one static sky. Since we don't care that the static lighting may be a bit different in the preview we never recompute
// and we use the one from the main camera.
bool forceStaticUpdate = false;
m_ActiveStaticSky = m_StaticLightingSkies.GetValueOrDefault(SceneManager.GetActiveScene().GetHashCode(), null);
#if UNITY_EDITOR
// In the editor, we might need the static sky ready for baking lightmaps/lightprobes regardless of the current ambient mode so we force it to update in this case if it's not been computed yet..
// We always force an update of the static sky when we're in scene view mode. Previous behaviour was to prevent forced updates if the hash of the static sky was non-null, but this was preventing
// the lightmapper from updating in response to changes in environment. See GFXGI-237 for a better description of this issue.
// In the editor, we might need the static sky ready for baking lightmaps/lightprobes regardless of the current ambient mode so we force it to update in this case if it's not been computed yet..
// We always force an update of the static sky when we're in scene view mode. Previous behaviour was to prevent forced updates if the hash of the static sky was non-null, but this was preventing
// the lightmapper from updating in response to changes in environment. See GFXGI-237 for a better description of this issue.
forceStaticUpdate = hdCamera.camera.cameraType == CameraType.SceneView;
forceStaticUpdate = hdCamera.camera.cameraType == CameraType.SceneView;
#endif
if ((ambientMode == SkyAmbientMode.Static || forceStaticUpdate) && hdCamera.camera.cameraType != CameraType.Preview)
{
if (m_ActiveStaticSky != null)
if ((ambientMode == SkyAmbientMode.Static || forceStaticUpdate) && hdCamera.camera.cameraType != CameraType.Preview)
{
m_StaticLightingSky.skySettings = m_ActiveStaticSky.skySettings;
m_StaticLightingSky.cloudSettings = m_ActiveStaticSky.cloudSettings;
m_StaticLightingSky.volumetricClouds = m_ActiveStaticSky.volumetricClouds;
if (m_ActiveStaticSky != null)
{
m_StaticLightingSky.skySettings = m_ActiveStaticSky.skySettings;
m_StaticLightingSky.cloudSettings = m_ActiveStaticSky.cloudSettings;
m_StaticLightingSky.volumetricClouds = m_ActiveStaticSky.volumetricClouds;
}
UpdateEnvironment(renderGraph, hdCamera, m_StaticLightingSky, sunLight, m_StaticSkyUpdateRequired || m_UpdateRequired, true, true, SkyAmbientMode.Static);
m_StaticSkyUpdateRequired = false;
}
UpdateEnvironment(renderGraph, hdCamera, m_StaticLightingSky, sunLight, m_StaticSkyUpdateRequired || m_UpdateRequired, true, true, SkyAmbientMode.Static);
m_StaticSkyUpdateRequired = false;
}
m_UpdateRequired = false;
m_UpdateRequired = false;
SetGlobalSkyData(renderGraph, hdCamera.lightingSky, m_BuiltinParameters);
SetGlobalSkyData(renderGraph, hdCamera.lightingSky, m_BuiltinParameters);
// Keep global setter for now. We should probably remove it and set it explicitly where needed like any other resource. As is it breaks resource lifetime contract with render graph.
HDRenderPipeline.SetGlobalTexture(renderGraph, HDShaderIDs._SkyTexture, GetReflectionTexture(hdCamera.lightingSky));
HDRenderPipeline.SetGlobalBuffer(renderGraph, HDShaderIDs._AmbientProbeData, GetDiffuseAmbientProbeBuffer(hdCamera));
// Keep global setter for now. We should probably remove it and set it explicitly where needed like any other resource. As is it breaks resource lifetime contract with render graph.
HDRenderPipeline.SetGlobalTexture(renderGraph, HDShaderIDs._SkyTexture, GetReflectionTexture(hdCamera.lightingSky));
HDRenderPipeline.SetGlobalBuffer(renderGraph, HDShaderIDs._AmbientProbeData, GetDiffuseAmbientProbeBuffer(hdCamera));
}
}
static void UpdateBuiltinParameters(ref BuiltinSkyParameters builtinParameters, SkyUpdateContext skyContext, HDCamera hdCamera, Light sunLight, DebugDisplaySettings debugSettings)

2
Packages/com.unity.render-pipelines.high-definition/package.json

@ -100,5 +100,5 @@
]
}
],
"_fingerprint": "840db4b587bbd894c751a83052cd5c5a11fba2f2"
"_fingerprint": "3672d1571dfd5f4d1627647460e0e4e2f11422ae"
}

53
Packages/com.unity.rendering.light-transport/Runtime/UnifiedRayTracing/Common/TerrainToMesh.cs

@ -10,54 +10,15 @@ namespace UnityEngine.Rendering.UnifiedRayTracing
{
static private AsyncTerrainToMeshRequest MakeAsyncTerrainToMeshRequest(int width, int height, Vector3 heightmapScale, float[,] heightmap, bool[,] holes)
{
int vertexCount = width * height;
int vertexCount = width * height;
var job = new ComputeTerrainMeshJob();
job.heightmap = new NativeArray<float>(vertexCount, Allocator.Persistent);
for (int i = 0; i < vertexCount; ++i)
job.heightmap[i] = heightmap[i / (width), i % (width)];
//WW1MOD This crashes when baking 4k terrains, as it tries to allocate a *2GB* Buffer!.. which is fine *here* but when it gets uploaded to GPU, it goes crashy or error, depending on dx-API/Driver
//Note heightmap size is always pow2+1
//the "else" part is the original code
if (height == 4097)
{
const int halfSize = 2049;
int _vertexCount = halfSize * halfSize;
Debug.Log("Downsizing Terrain heightmap mesh output to 2k to prevent crashes");
job.heightmap = new NativeArray<float>(_vertexCount, Allocator.Persistent);
for (int i = 0; i < _vertexCount; ++i)
{
float h0 = heightmap[((i*2)+0) / (width), ((i*2)+0) % (width)];
float h1 = heightmap[((i*2)+1) / (width), ((i*2)+0) % (width)];
float h2 = heightmap[((i*2)+0) / (width), ((i*2)+1) % (width)];
float h3 = heightmap[((i*2)+1) / (width), ((i*2)+1) % (width)];
job.heightmap[i] = (h0 + h1 + h2 + h3) / 4f;
}
job.holes = new NativeArray<bool>((halfSize - 1) * (halfSize - 1), Allocator.Persistent);
for (int i = 0; i < (halfSize - 1) * (halfSize - 1); ++i)
{
bool h0 = holes[((i*2)+0) / (width - 1), ((i*2)+0) % (width - 1)];
bool h1 = holes[((i*2)+1) / (width - 1), ((i*2)+0) % (width - 1)];
bool h2 = holes[((i*2)+0) / (width - 1), ((i*2)+1) % (width - 1)];
bool h3 = holes[((i*2)+1) / (width - 1), ((i*2)+1) % (width - 1)];
job.holes[i] = h0 || h1 || h2 || h3;
}
height = width = halfSize;
vertexCount = _vertexCount;
}
else
{
job.heightmap = new NativeArray<float>(vertexCount, Allocator.Persistent);
for (int i = 0; i < vertexCount; ++i)
job.heightmap[i] = heightmap[i / (width), i % (width)];
job.holes = new NativeArray<bool>((width - 1) * (height - 1), Allocator.Persistent);
for (int i = 0; i < (width - 1) * (height - 1); ++i)
job.holes[i] = holes[i / (width - 1), i % (width - 1)];
}
job.holes = new NativeArray<bool>((width - 1) * (height - 1), Allocator.Persistent);
for (int i = 0; i < (width - 1) * (height - 1); ++i)
job.holes[i] = holes[i / (width - 1), i % (width - 1)];
job.width = width;
job.height = height;

1
Packages/com.unity.rendering.light-transport/Tests/Editor/UnifiedRayTracing/AccelStructTests.cs

@ -170,6 +170,7 @@ namespace UnityEngine.Rendering.UnifiedRayTracing.Tests
}
[Test]
[Timeout(360000)]
public void AddInstance_MeshWith2GBWorthOfVertices_Throws()
{
var resources = new RayTracingResources();

2
Packages/com.unity.rendering.light-transport/package.json

@ -15,5 +15,5 @@
"pathtracing",
"monte-carlo"
],
"_fingerprint": "ec31b4120e30d44c7f702fa7bfa50d70b562cd4a"
"_fingerprint": "e647573c7d2ae78386ecb3f9f962738597f13fcf"
}

2
Packages/com.unity.shadergraph/package.json

@ -43,5 +43,5 @@
"path": "Samples~/UGUIShaders"
}
],
"_fingerprint": "e5d3455aa13376f767ad6bf5f3faab2073877176"
"_fingerprint": "8d13f365c6632c6b398ae9cd01d13bcee9880a3b"
}

16
Packages/com.unity.ugui/Runtime/UGUI/UI/Core/Image.cs

@ -935,15 +935,15 @@ namespace UnityEngine.UI
internal SecondarySpriteTexture [] secondaryTextures => m_SecondaryTextures; // Internal for testing only
static void ClearArray(SecondarySpriteTexture[] array)
static void ClearArray(ref SecondarySpriteTexture[] array)
{
Array.Resize(ref array, 0);
array = Array.Empty<SecondarySpriteTexture>();
}
bool CheckSecondaryTexturesChanged(Sprite sprite)
{
var changed = CheckSecondaryTexturesChanged(sprite, ref s_TempNewSecondaryTextures);
ClearArray(s_TempNewSecondaryTextures);
ClearArray(ref s_TempNewSecondaryTextures);
return changed;
}
@ -979,7 +979,7 @@ namespace UnityEngine.UI
}
else
{
ClearArray(newSecondaryTextures);
ClearArray(ref newSecondaryTextures);
}
// If the list of secondary textures has not changed then return
@ -1017,7 +1017,7 @@ namespace UnityEngine.UI
}
}
ClearArray(s_TempNewSecondaryTextures);
ClearArray(ref s_TempNewSecondaryTextures);
}
/// <summary>
@ -1925,6 +1925,12 @@ namespace UnityEngine.UI
float x = local.x / activeSprite.texture.width;
float y = local.y / activeSprite.texture.height;
// Locations outside the image are always considered valid.
// This guarantees that the behavior remains consistent with the case where alphaHitTestMinimumThreshold <= 0.
// Without this check, we would continue to sample a pixel outside the texture.
if (x < 0 || x > 1 || y < 0 || y > 1)
return true;
try
{
return activeSprite.texture.GetPixelBilinear(x, y).a >= alphaHitTestMinimumThreshold;

1
Packages/com.unity.ugui/Runtime/UGUI/UI/Core/Slider.cs

@ -533,6 +533,7 @@ namespace UnityEngine.UI
return;
m_Value = newValue;
MarkDirty();
UpdateVisuals();
if (sendCallback)
{

2
Packages/com.unity.ugui/package.json

@ -19,5 +19,5 @@
"com.unity.modules.ui": "1.0.0",
"com.unity.modules.imgui": "1.0.0"
},
"_fingerprint": "57cef44123c7486b2e2f08dc6535aecf6c34b8ef"
"_fingerprint": "1a71b488df3ebf0445532ad09fea67fd1a895ab4"
}

1
Packages/com.unity.visualeffectgraph/Editor/Inspector/VFXSlotContainerEditor.cs

@ -442,6 +442,7 @@ class VFXSlotContainerEditor : Editor
{ VFXValueType.Int32, new Color32(125, 110, 191, 255) },
{ VFXValueType.Matrix4x4, new Color32(118, 118, 118, 255) },
{ VFXValueType.Mesh, new Color32(130, 223, 226, 255) },
{ VFXValueType.SkinnedMeshRenderer, new Color32(130, 223, 226, 255) },
{ VFXValueType.None, new Color32(118, 118, 118, 255) },
{ VFXValueType.Spline, new Color32(130, 223, 226, 255) },
{ VFXValueType.Texture2D, new Color32(250, 137, 137, 255) },

2
Packages/com.unity.visualeffectgraph/package.json

@ -36,5 +36,5 @@
]
}
],
"_fingerprint": "aecde9dec67d1cb56e53e3135229de90e9d94fb6"
"_fingerprint": "1610c4dd914dcb46d906bfe48b8db559fd045331"
}
Loading…
Cancel
Save