Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
## [1.2.0] - 2024-03-22

### Changed

* fixed the issue with LOD objects being culled when the camera is static

### Fixed

* Entities Graphics should now never run out of space in the NewChunks buffer.
* A null reference exception thrown in some cases when using MeshRenderers with missing materials and/or meshes
  • Loading branch information
Unity Technologies committed Mar 22, 2024
1 parent df4de17 commit 9a14fc4
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 84 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,20 @@ uid: changelog

# Changelog

## [1.2.0] - 2024-03-22

## [1.2.0-pre.12] - 2024-02-13
### Changed

* fixed the issue with LOD objects being culled when the camera is static

### Fixed

* Entities Graphics should now never run out of space in the NewChunks buffer.
* A null reference exception thrown in some cases when using MeshRenderers with missing materials and/or meshes


## [1.2.0-pre.12] - 2024-02-13

### Added

* `RenderMeshUnmanaged` an unmanaged IComponentData using the new UnityObjRef<T> for big performance gains in baking!
Expand Down
128 changes: 61 additions & 67 deletions Unity.Entities.Graphics/EntitiesGraphicsCulling.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,91 +141,85 @@ public void Execute(in ArchetypeChunk archetypeChunk, int unfilteredChunkIndex,
int diff = (int)chunkCullingData.MovementGraceFixed16 - CameraMoveDistanceFixed16;
chunkCullingData.MovementGraceFixed16 = (ushort)math.max(0, diff);

var graceExpired = chunkCullingData.MovementGraceFixed16 == 0;
var forceLodChanged = forceLowLOD != chunkCullingData.ForceLowLODPrevious;

if (graceExpired || forceLodChanged || DistanceScaleChanged)
{
chunkEntityLodEnabled.Enabled[0] = 0;
chunkEntityLodEnabled.Enabled[1] = 0;
chunkEntityLodEnabled.Enabled[0] = 0;
chunkEntityLodEnabled.Enabled[1] = 0;

#if UNITY_EDITOR
stats.LodChunksTested++;
stats.LodChunksTested++;
#endif
var chunk = chunkHeader.ArchetypeChunk;
var chunk = chunkHeader.ArchetypeChunk;

var rootLODRanges = chunk.GetNativeArray(ref RootLODRanges);
var rootLODReferencePoints = chunk.GetNativeArray(ref RootLODReferencePoints);
var lodRanges = chunk.GetNativeArray(ref LODRanges);
var lodReferencePoints = chunk.GetNativeArray(ref LODReferencePoints);
var rootLODRanges = chunk.GetNativeArray(ref RootLODRanges);
var rootLODReferencePoints = chunk.GetNativeArray(ref RootLODReferencePoints);
var lodRanges = chunk.GetNativeArray(ref LODRanges);
var lodReferencePoints = chunk.GetNativeArray(ref LODReferencePoints);

float graceDistance = float.MaxValue;
float graceDistance = float.MaxValue;

for (int i = 0; i < chunkInstanceCount; i++)
{
var rootLODRange = rootLODRanges[i];
var rootLODReferencePoint = rootLODReferencePoints[i];
for (int i = 0; i < chunkInstanceCount; i++)
{
var rootLODRange = rootLODRanges[i];
var rootLODReferencePoint = rootLODReferencePoints[i];

var rootLodDistance =
math.select(
DistanceScale *
math.length(LODParams.cameraPos - rootLODReferencePoint.Value),
DistanceScale, isOrtho);
var rootLodDistance =
math.select(
DistanceScale *
math.length(LODParams.cameraPos - rootLODReferencePoint.Value),
DistanceScale, isOrtho);

float rootMinDist = math.select(rootLODRange.LOD.MinDist, 0.0f, forceLowLOD == 1);
float rootMaxDist = rootLODRange.LOD.MaxDist;
float rootMinDist = math.select(rootLODRange.LOD.MinDist, 0.0f, forceLowLOD == 1);
float rootMaxDist = rootLODRange.LOD.MaxDist;

graceDistance = math.min(math.abs(rootLodDistance - rootMinDist), graceDistance);
graceDistance = math.min(math.abs(rootLodDistance - rootMaxDist), graceDistance);
graceDistance = math.min(math.abs(rootLodDistance - rootMinDist), graceDistance);
graceDistance = math.min(math.abs(rootLodDistance - rootMaxDist), graceDistance);

var rootLodIntersect = (rootLodDistance < rootMaxDist) && (rootLodDistance >= rootMinDist);
var rootLodIntersect = (rootLodDistance < rootMaxDist) && (rootLodDistance >= rootMinDist);

if (rootLodIntersect)
if (rootLodIntersect)
{
var lodRange = lodRanges[i];
if (lodRange.LODMask < MaximumLODLevelMask)
{
continue;
}
if (lodRange.LODMask == MaximumLODLevelMask)
{
var lodRange = lodRanges[i];
if (lodRange.LODMask < MaximumLODLevelMask)
{
continue;
}
if (lodRange.LODMask == MaximumLODLevelMask)
{
// Expand maximum LOD range to cover all higher LODs
lodRange.MinDist = 0.0f;
}
var lodReferencePoint = lodReferencePoints[i];

var instanceDistance =
math.select(
DistanceScale *
math.length(LODParams.cameraPos -
lodReferencePoint.Value), DistanceScale,
lodRange.MinDist = 0.0f;
}
var lodReferencePoint = lodReferencePoints[i];

var instanceDistance =
math.select(
DistanceScale *
math.length(LODParams.cameraPos - lodReferencePoint.Value), DistanceScale,
isOrtho);

var instanceLodIntersect =
(instanceDistance < lodRange.MaxDist) &&
(instanceDistance >= lodRange.MinDist);

graceDistance = math.min(math.abs(instanceDistance - lodRange.MinDist),
graceDistance);
graceDistance = math.min(math.abs(instanceDistance - lodRange.MaxDist),
graceDistance);

if (instanceLodIntersect)
{
var index = i;
var wordIndex = index >> 6;
var bitIndex = index & 0x3f;
var lodWord = chunkEntityLodEnabled.Enabled[wordIndex];

lodWord |= 1UL << bitIndex;
chunkEntityLodEnabled.Enabled[wordIndex] = lodWord;
}
var instanceLodIntersect =
(instanceDistance < lodRange.MaxDist) &&
(instanceDistance >= lodRange.MinDist);

graceDistance = math.min(math.abs(instanceDistance - lodRange.MinDist),
graceDistance);
graceDistance = math.min(math.abs(instanceDistance - lodRange.MaxDist),
graceDistance);

if (instanceLodIntersect)
{
var index = i;
var wordIndex = index >> 6;
var bitIndex = index & 0x3f;
var lodWord = chunkEntityLodEnabled.Enabled[wordIndex];

lodWord |= 1UL << bitIndex;
chunkEntityLodEnabled.Enabled[wordIndex] = lodWord;
}
}

chunkCullingData.MovementGraceFixed16 = Fixed16CamDistance.FromFloatFloor(graceDistance);
chunkCullingData.ForceLowLODPrevious = forceLowLOD;
}

chunkCullingData.MovementGraceFixed16 = Fixed16CamDistance.FromFloatFloor(graceDistance);
chunkCullingData.ForceLowLODPrevious = forceLowLOD;

}


Expand Down
11 changes: 8 additions & 3 deletions Unity.Entities.Graphics/EntitiesGraphicsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ private JobHandle RegisterMaterialsAndMeshes(JobHandle inputDeps)
var id = m_RendererSystem.RegisterMaterial(material);
if (id == BatchMaterialID.Null)
{
Debug.LogWarning($"Registering material {(material != null ? material.Value.ToString() : "null")} at index {i} inside a RenderMeshArray failed.");
Debug.LogWarning($"Registering material {(material ? material.Value.ToString() : "null")} at index {i} inside a RenderMeshArray failed.");
}

brgRenderArray.UniqueMaterials.Add(id);
Expand All @@ -553,7 +553,7 @@ private JobHandle RegisterMaterialsAndMeshes(JobHandle inputDeps)
var mesh = renderArray.MeshesInternal[i];
var id = m_RendererSystem.RegisterMesh(mesh);
if (id == BatchMeshID.Null)
Debug.LogWarning($"Registering mesh {(mesh != null ? mesh.Value.ToString() : "null")} at index {i} inside a RenderMeshArray failed.");
Debug.LogWarning($"Registering mesh {(mesh ? mesh.Value.ToString() : "null")} at index {i} inside a RenderMeshArray failed.");

brgRenderArray.UniqueMeshes.Add(id);
}
Expand Down Expand Up @@ -1835,7 +1835,12 @@ private JobHandle UpdateAllBatches(JobHandle inputDependencies)
Profiler.EndSample();

var numNewChunksArray = new NativeArray<int>(1, Allocator.TempJob);
int totalChunks = m_EntitiesGraphicsRenderedQuery.CalculateChunkCountWithoutFiltering();
int totalChunksWithNormalQuery = m_EntitiesGraphicsRenderedQuery.CalculateChunkCountWithoutFiltering();
// One meta-entity = one chunk of normal entities, so use CalculateEntityCount
int totalChunksWithMetaEntityQuery = m_MetaEntitiesForHybridRenderableChunksQuery.CalculateEntityCountWithoutFiltering();
// For some reason, the counts returned by these queries may not always match in edge cases.
// Use the larger of the two counts to ensure we never run out of space.
int totalChunks = math.max(totalChunksWithNormalQuery, totalChunksWithMetaEntityQuery);
var newChunks = new NativeArray<ArchetypeChunk>(
totalChunks,
Allocator.TempJob,
Expand Down
37 changes: 29 additions & 8 deletions ValidationExceptions.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
{
"ErrorExceptions": [
{
"ValidationTest": "API Validation",
"ExceptionMessage": "Breaking changes require a new major version.",
"PackageVersion": "1.2.0-pre.12"
}
],
"WarningExceptions": []
"ErrorExceptions": [
{
"ValidationTest": "API Updater Configuration Validation",
"ExceptionMessage": "stdout:\nAPIUpdater Configuration Validation\n-----------------------------------\n\nConfiguration Validation Tests (Failed: 0, Total: 1, Ignored 0):\n----------------------------------------------------------------\n\n\nAuto Generated Tests (Failed: 1, Total: 1, Ignored 0):\n------------------------------------------------------\n1) Expected updates not applied for configuration:\n[*] System.SByte [*] Unity.Rendering.MaterialMeshInfo::Submesh -> * Unity.Rendering.MaterialMeshInfo::SubMesh\n\nInput : unsafe class Test : object { System.SByte Method(System.SByte memberValue, Unity.Rendering.MaterialMeshInfo obj) { System.SByte local = obj.Submesh; return Method(obj.Submesh, obj); } }\nExpected: unsafe class Test : object { System.UInt16 Method(System.UInt16 memberValue, Unity.Rendering.MaterialMeshInfo obj) { System.UInt16 local = obj.SubMesh; return Method(obj.SubMesh, obj); } }\nActual : unsafe class Test : object { System.SByte Method(System.SByte memberValue, Unity.Rendering.MaterialMeshInfo obj) { System.SByte local = obj.SubMesh; return Method(obj.SubMesh, obj); } }\n\n\nBase type validation (Failed: 0, Total: 0, Ignored 0):\n------------------------------------------------------\nstderr:\n",
"PackageVersion": "1.2.0"
},
{
"ValidationTest": "API Validation",
"ExceptionMessage": "Breaking changes require a new major version.",
"PackageVersion": "1.2.0"
}
],
"WarningExceptions": [
{
"ValidationTest": "Manifest Validation",
"ExceptionMessage": "Package dependency [email protected] must be promoted to production before this package is promoted to production. (Except for core packages)",
"PackageVersion": "1.2.0"
},
{
"ValidationTest": "Folder Structure Validation",
"ExceptionMessage": "The Resources Directory should not be used in packages. For more guidance, please visit https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity6.html",
"PackageVersion": "1.2.0"
},
{
"ValidationTest": "Package Lifecycle Validation",
"ExceptionMessage": "com.unity.entities.graphics has never been promoted to production before. Please contact Release Management through slack in #devs-pkg-promotion to promote the first version of your package before trying to use this automated pipeline. Read more about this error and potential solutions at https://docs.unity3d.com/Packages/com.unity.package-validation-suite@latest/index.html?preview=1&subfolder=/manual/lifecycle_validation_error.html#the-very-first-version-of-a-package-must-be-promoted-by-release-management",
"PackageVersion": "1.2.0"
}
]
}
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "com.unity.entities.graphics",
"displayName": "Entities Graphics",
"version": "1.2.0-pre.12",
"version": "1.2.0",
"unity": "2022.3",
"unityRelease": "11f1",
"description": "The Entities Graphics package provides systems and components for drawing meshes using DOTS, including support for instanced mesh rendering and LOD.",
"dependencies": {
"com.unity.entities": "1.2.0-pre.12",
"com.unity.entities": "1.2.0",
"com.unity.modules.particlesystem": "1.0.0",
"com.unity.render-pipelines.core": "14.0.9"
},
Expand All @@ -17,15 +17,15 @@
"unity"
],
"_upm": {
"changelog": "### Added\n\n* `RenderMeshUnmanaged` an unmanaged IComponentData using the new UnityObjRef<T> for big performance gains in baking!\n* Support for light probe anchor overrides\n\n### Changed\n\n* MaterialMeshInfo.SubMesh chaned from sbyte to ushort, allowing for the full range of submesh indices.\n* The sharedcomponents `Lightmaps` and `RenderMeshArray` now store UnityObjRef<T> instead.\n\n### Deprecated\n\n* The baking sharedcomponent `RenderMesh` is now obsolete, in favor of a new `RenderMeshUnmanaged`.\n\n### Fixed\n\n* Improved handling of smaller transforms\n* Light probes now use the center of world bounding box as the reference point, same as game objects\n* Materials sometimes not correctly baked when using ENABLE_MESH_RENDERER_SUBMESH_DATA_SHARING"
"changelog": "### Changed\n\n* fixed the issue with LOD objects being culled when the camera is static\n\n### Fixed\n\n* Entities Graphics should now never run out of space in the NewChunks buffer.\n* A null reference exception thrown in some cases when using MeshRenderers with missing materials and/or meshes"
},
"upmCi": {
"footprint": "22f7abd51ca2ffd95a065b596f1181dfa8a4bb35"
"footprint": "8c29b61b26490f1fa6cbfbe876e7bbde992f6711"
},
"documentationUrl": "https://docs.unity3d.com/Packages/[email protected]/manual/index.html",
"repository": {
"url": "https://github.cds.internal.unity3d.com/unity/dots.git",
"type": "git",
"revision": "1ae43e0525b8a09c7fe52ab40c762938a4937244"
"revision": "ea4236421d61011e37e71d22108c5e4e70cf71d7"
}
}

0 comments on commit 9a14fc4

Please sign in to comment.