Skip to content
This repository has been archived by the owner on Dec 13, 2022. It is now read-only.

Commit

Permalink
Changed DX viewer to support instanced rendering
Browse files Browse the repository at this point in the history
Changed the DX viewer system to use instanced rendering as the default rendering for multiple models and removed the batch size principle
  • Loading branch information
seb-eis committed Mar 29, 2021
1 parent a19d17d commit ccfe51f
Show file tree
Hide file tree
Showing 16 changed files with 248 additions and 195 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -268,5 +268,29 @@ public static void Load<T>(this IEnumerable<T> source)

enumerator.Dispose();
}

/// <summary>
/// Splits an <see cref="IEnumerable{T}"/> into multiple sub enumerations of specified size where the last entry may me smaller
/// </summary>
/// <param name="self"></param>
/// <param name="size"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static IEnumerable<IEnumerable<T>> ToChunks<T>(this IEnumerable<T> self, int size)
{
IEnumerable<T> EnumerateChunk(IEnumerator<T> value)
{
for (var i = 0; i < size; i++)
{
yield return value.Current;
if (!value.MoveNext()) yield break;
}
}
using var enumerator = self.GetEnumerator();
while (enumerator.MoveNext())
{
yield return EnumerateChunk(enumerator);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,15 @@ public interface ISimulationLibrary : IDisposable
/// </summary>
/// <param name="journalMode"></param>
void SetJournalMode(DbJournalMode journalMode);

/// <summary>
/// Ensures that all <see cref="InteropEntityBase"/> instances of the context are in the object state
/// </summary>
void EnsureInteropObjectsAreInObjectState();

/// <summary>
/// Ensures that all <see cref="InteropEntityBase"/> instances of the context are in the binary state
/// </summary>
void EnsureInteropObjectsAreInBinaryState();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ public SimulationDbContext(string optionsBuilderParameterString)
/// <inheritdoc cref="ISimulationLibrary.SaveChanges" />
public override int SaveChanges()
{
using var marshalService = new MarshalService();
MutateTrackedInteropEntities(interopEntity => interopEntity.ChangePropertyStatesToBinaries(marshalService));
EnsureInteropObjectsAreInBinaryState();
return base.SaveChanges();
}

Expand Down Expand Up @@ -89,6 +88,20 @@ public void SetJournalMode(DbJournalMode journalMode)
}
}

/// <inheritdoc />
public void EnsureInteropObjectsAreInObjectState()
{
using var marshalService = new MarshalService();
MutateTrackedInteropEntities(interopEntity => interopEntity.ChangePropertyStatesToObjects(marshalService));
}

/// <inheritdoc />
public void EnsureInteropObjectsAreInBinaryState()
{
using var marshalService = new MarshalService();
MutateTrackedInteropEntities(interopEntity => interopEntity.ChangePropertyStatesToBinaries(marshalService));
}

/// <summary>
/// Performs the passed action on all tracked entities of type <see cref="InteropEntityBase" />
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,11 @@

namespace Mocassin.Model.Translator.ModelContext
{
/// <summary>
/// Defines status flags for the <see cref="IProjectModelContext" />
/// </summary>
[Flags]
public enum ProjectContextFlags
{
/// <summary>
/// Defines that the context is only partial build
/// </summary>
PartialContext = 1,

/// <summary>
/// Defines that the context is complete
/// </summary>
FullContext = 1 << 1,

/// <summary>
/// Defines that the context components are completely interlinked
/// </summary>
LinkedContext = 1 << 2,

/// <summary>
/// Defines that the context can be used for job translations
/// </summary>
TranslatableContext = FullContext | LinkedContext
}

/// <summary>
/// Represents a full project data context that contains all data described within the model managers
/// </summary>
public interface IProjectModelContext
{
/// <summary>
/// Get the currently set <see cref="ProjectContextFlags" />
/// </summary>
ProjectContextFlags ContextFlags { get; }

/// <summary>
/// Get a boolean value if the context is rdy for component interlinking
/// </summary>
bool IsLinkable { get; }

/// <summary>
/// Get boolean value if the context can be used for job translations
/// </summary>
bool IsTranslatable { get; }

/// <summary>
/// Access to the project services the model context was generated from
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,6 @@ namespace Mocassin.Model.Translator.ModelContext
/// <inheritdoc />
public class ProjectModelContext : IProjectModelContext
{
/// <inheritdoc />
public ProjectContextFlags ContextFlags { get; set; }

/// <inheritdoc />
public bool IsLinkable => ContextFlags.HasFlag(ProjectContextFlags.FullContext);

/// <inheritdoc />
public bool IsTranslatable => ContextFlags.HasFlag(ProjectContextFlags.TranslatableContext);

/// <inheritdoc />
public IModelProject ModelProject { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,7 @@ private MeshGeometry3D CreatePolygonFanGeometry(ICollection<Fractional3D> positi

/// <summary>
/// Adds multiple mesh transforms to a <see cref="DxSceneBuilder" /> and performs batching based on the
/// <see cref="DxSceneBatchingMode" /> preference of the scene host
/// <see cref="DxInstanceRenderMode" /> preference of the scene host
/// </summary>
/// <param name="sceneBuilder"></param>
/// <param name="geometry"></param>
Expand All @@ -982,51 +982,29 @@ private MeshGeometry3D CreatePolygonFanGeometry(ICollection<Fractional3D> positi
protected virtual void AddMeshElementsToScene(DxSceneBuilder sceneBuilder, MeshGeometry3D geometry, MaterialCore material, IList<Matrix> matrices,
Action<SceneNode> callback = null)
{
if (matrices.Count == 1)
switch (SceneHost.InstanceRenderMode)
{
sceneBuilder.AddMeshTransforms(geometry, material, matrices, callback);
return;
}

var batchSize = GetMeshBatchSize(SceneHost.SceneBatchingMode);
switch (batchSize)
{
case 1:
case DxInstanceRenderMode.Individual:
sceneBuilder.AddMeshTransforms(geometry, material, matrices, callback);
return;
case int.MaxValue:
sceneBuilder.AddBatchedMeshTransforms(geometry, material, matrices, callback);
return;
}
break;
case DxInstanceRenderMode.Instanced:
sceneBuilder.AddInstancedMeshTransforms(geometry, material, matrices, callback);
break;
case DxInstanceRenderMode.Batched:
var tmp = new List<Matrix>();
foreach (var chunk in matrices.ToChunks(1024))
{
tmp.AddRange(chunk);
sceneBuilder.AddBatchedMeshTransforms(geometry, material, tmp, callback);
tmp.Clear();
}

var tmpMatrices = new List<Matrix>(batchSize);
for (var i = 0; i < matrices.Count; i += batchSize)
{
for (var j = i; j < matrices.Count && tmpMatrices.Count < batchSize; j++) tmpMatrices.Add(matrices[j]);
sceneBuilder.AddBatchedMeshTransforms(geometry, material, tmpMatrices, callback);
tmpMatrices.Clear();
break;
default:
throw new ArgumentOutOfRangeException();
}
}

/// <summary>
/// Translates the <see cref="DxSceneBatchingMode" /> setting of the scene host to an actual model count
/// </summary>
/// <param name="batchingMode"></param>
/// <returns></returns>
protected virtual int GetMeshBatchSize(DxSceneBatchingMode batchingMode)
{
return batchingMode switch
{
DxSceneBatchingMode.None => 1,
DxSceneBatchingMode.Low => 64,
DxSceneBatchingMode.Moderate => 256,
DxSceneBatchingMode.High => 1024,
DxSceneBatchingMode.Extreme => 2048,
DxSceneBatchingMode.Unlimited => int.MaxValue,
_ => throw new ArgumentOutOfRangeException(nameof(batchingMode), batchingMode, null)
};
}

/// <summary>
/// Get a configuration and attachment callback <see cref="Action{T}" /> for a <see cref="SceneNode" /> using the
/// provided <see cref="IDxSceneItemConfig" />
Expand Down Expand Up @@ -1063,16 +1041,16 @@ void ConfigNodeAndAttach(SceneNode sceneNode)
{
switch (sceneNode)
{
case BatchedMeshNode batchedMeshNode:
batchedMeshNode.CullMode = cullMode;
batchedMeshNode.WireframeColor = wireframeColor;
batchedMeshNode.RenderWireframe = isWireFrameVisible;
break;
case MeshNode meshNode:
meshNode.CullMode = cullMode;
meshNode.WireframeColor = wireframeColor;
meshNode.RenderWireframe = isWireFrameVisible;
break;
case BatchedMeshNode batchedMeshNode:
batchedMeshNode.CullMode = cullMode;
batchedMeshNode.WireframeColor = wireframeColor;
batchedMeshNode.RenderWireframe = isWireFrameVisible;
break;
}

baseConfigurator.Invoke(sceneNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,24 @@ protected void ChangeNodeScaling(SceneNode sceneNode, ref Matrix rescalingMatrix
switch (sceneNode)
{
case MeshNode meshNode:
meshNode.ModelMatrix = RescaleModelMatrixAtOrigin(meshNode.ModelMatrix, ref rescalingMatrix);
if (meshNode.Instances?.Count == 0)
{
meshNode.ModelMatrix = RescaleModelMatrixAtOrigin(meshNode.ModelMatrix, ref rescalingMatrix);
}
else
{
if (meshNode.Instances is { })
{
var instances = meshNode.Instances;
meshNode.Instances = null;
for (var i = 0; i < instances.Count; i++)
{
instances[i] = RescaleModelMatrixAtOrigin(instances[i], ref rescalingMatrix);
}

meshNode.Instances = instances;
}
}
break;
case BatchedMeshNode batchedNode:
var geometries = new BatchedMeshGeometryConfig[batchedNode.Geometries.Length];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ namespace Mocassin.UI.GUI.Controls.DxVisualizer.Viewport.Base
public interface IDxSceneHost : INotifyPropertyChanged, IDisposable
{
/// <summary>
/// Get the <see cref="DxSceneBatchingMode" /> preference the scene host has
/// Get the <see cref="DxInstanceRenderMode" /> preference the scene host has
/// </summary>
DxSceneBatchingMode SceneBatchingMode { get; }
DxInstanceRenderMode InstanceRenderMode { get; }

/// <summary>
/// Get the <see cref="IDxSceneController" /> that manages the scene
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
Margin="{StaticResource App.Margin.VerticalStack}"
IsChecked="{Binding EnableInfiniteSpin}" />

<TextBlock Grid.Row="13" Grid.Column="0" Text="Camera Type" VerticalAlignment="Center"
<TextBlock Grid.Row="13" Grid.Column="0" Text="Camera type" VerticalAlignment="Center"
Margin="{StaticResource App.Margin.VerticalStack}" />
<ComboBox Grid.Row="13" Grid.Column="2" IsEditable="True" Margin="{StaticResource App.Margin.VerticalStack}"
ItemsSource="{Binding CameraTypes}" SelectedItem="{Binding DxCameraType}" />
Expand Down Expand Up @@ -214,19 +214,10 @@
</TextBox.InputBindings>
</TextBox>

<TextBlock Grid.Row="22" Grid.Column="0" Text="Batching mode" VerticalAlignment="Center"
Margin="{StaticResource App.Margin.VerticalStack}">
<TextBlock.ToolTip>
<TextBlock TextAlignment="Justify" TextWrapping="Wrap" Width="500">
<Run
Text="Set how much model batching the scene controller can do to reduce draw-calls and scene management time." />
<Run
Text="Recommendation: Use 'None/Low' for GPUs with a very small VRAM size (e.g. iGPUs) and avoid using 'None' when displaying 1000+ objects." />
</TextBlock>
</TextBlock.ToolTip>
</TextBlock>
<TextBlock Grid.Row="22" Grid.Column="0" Text="Draw mode" VerticalAlignment="Center"
Margin="{StaticResource App.Margin.VerticalStack}"/>
<ComboBox Grid.Row="22" Grid.Column="2" IsEditable="True" Margin="{StaticResource App.Margin.VerticalStack}"
ItemsSource="{Binding SceneBatchingModes}" SelectedItem="{Binding SceneBatchingMode}" />
ItemsSource="{Binding SceneBatchingModes}" SelectedItem="{Binding InstanceRenderMode}" />

<TextBlock Grid.Row="23" Grid.Column="0" Text="Manual camera" VerticalAlignment="Center"
Margin="{StaticResource App.Margin.VerticalStack}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class DxViewportViewModel : ViewModelBase, IDxSceneHost
private Color lightColor = Colors.White;
private DxSceneLightSetting lightSetting = DxSceneLightSetting.None;
private MSAALevel msaaLevel = MSAALevel.Four;
private DxSceneBatchingMode sceneBatchingMode = DxSceneBatchingMode.Low;
private DxInstanceRenderMode instanceRenderMode = DxInstanceRenderMode.Instanced;
private bool showCoordinateSystem = true;
private bool showRenderInformation;
private bool showViewCube = true;
Expand Down Expand Up @@ -108,13 +108,13 @@ public CameraRotationMode CameraRotationMode
}

/// <inheritdoc />
public DxSceneBatchingMode SceneBatchingMode
public DxInstanceRenderMode InstanceRenderMode
{
get => sceneBatchingMode;
get => instanceRenderMode;
set
{
if (sceneBatchingMode == value) return;
SetProperty(ref sceneBatchingMode, value);
if (instanceRenderMode == value) return;
SetProperty(ref instanceRenderMode, value);
InvalidateSceneCommand?.Execute(null);
}
}
Expand Down Expand Up @@ -404,9 +404,9 @@ public bool IsControlHostOverlayActive
public IEnumerable<DxSceneLightSetting> SceneLightSettings => EnumerateLightSettings();

/// <summary>
/// Get the selectable <see cref="SceneBatchingMode" />
/// Get the selectable <see cref="InstanceRenderMode" />
/// </summary>
public IEnumerable<DxSceneBatchingMode> SceneBatchingModes => EnumerateBatchingModes();
public IEnumerable<DxInstanceRenderMode> SceneBatchingModes => EnumerateInstanceRenderModes();

/// <summary>
/// Get the <see cref="ObservableElement3DCollection" /> that supplies the <see cref="Element3D" /> containing light
Expand Down Expand Up @@ -751,17 +751,14 @@ protected virtual IEnumerable<DxSceneLightSetting> EnumerateLightSettings()
}

/// <summary>
/// Enumerates the selectable <see cref="DxSceneBatchingMode" /> preferences
/// Enumerates the selectable <see cref="DxInstanceRenderMode" /> preferences
/// </summary>
/// <returns></returns>
protected virtual IEnumerable<DxSceneBatchingMode> EnumerateBatchingModes()
{
yield return DxSceneBatchingMode.None;
yield return DxSceneBatchingMode.Low;
yield return DxSceneBatchingMode.Moderate;
yield return DxSceneBatchingMode.High;
yield return DxSceneBatchingMode.Extreme;
yield return DxSceneBatchingMode.Unlimited;
protected virtual IEnumerable<DxInstanceRenderMode> EnumerateInstanceRenderModes()
{
yield return DxInstanceRenderMode.Instanced;
yield return DxInstanceRenderMode.Individual;
yield return DxInstanceRenderMode.Batched;
}

/// <summary>
Expand Down
Loading

0 comments on commit ccfe51f

Please sign in to comment.