From 77e92d28e89f88665e2ea84c734ea0b60c918558 Mon Sep 17 00:00:00 2001 From: Phill Date: Tue, 15 Apr 2025 16:29:22 -0400 Subject: [PATCH 1/3] initial refactor --- .../Functions/RenderEnginePluginFunction.cs | 73 +++++++++++++++++++ source/MaterialData.cs | 58 +++++++++++++++ source/RenderEntity.cs | 65 +++++++++++++++++ source/RendererCombination.cs | 55 ++++++++++++++ source/RendererEnginePlugin.cs | 19 +++++ source/Rendering.csproj | 8 +- 6 files changed, 274 insertions(+), 4 deletions(-) create mode 100644 source/Functions/RenderEnginePluginFunction.cs create mode 100644 source/MaterialData.cs create mode 100644 source/RenderEntity.cs create mode 100644 source/RendererCombination.cs create mode 100644 source/RendererEnginePlugin.cs diff --git a/source/Functions/RenderEnginePluginFunction.cs b/source/Functions/RenderEnginePluginFunction.cs new file mode 100644 index 0000000..34d8d38 --- /dev/null +++ b/source/Functions/RenderEnginePluginFunction.cs @@ -0,0 +1,73 @@ +using System; +using Worlds; + +namespace Rendering.Functions +{ + public unsafe readonly struct RenderEnginePluginFunction : IEquatable + { +#if NET + private readonly delegate* unmanaged function; + + public RenderEnginePluginFunction(delegate* unmanaged function) + { + this.function = function; + } +#else + private readonly delegate* function; + + public PluginBeforeRendering(delegate* function) + { + this.function = function; + } +#endif + + public readonly void Invoke(World world, uint materialEntity, Span entities) + { + function(new(world, materialEntity, entities)); + } + + public readonly override bool Equals(object? obj) + { + return obj is RenderEnginePluginFunction plugin && Equals(plugin); + } + + public readonly bool Equals(RenderEnginePluginFunction other) + { + return (nint)function == (nint)other.function; + } + + public readonly override int GetHashCode() + { + return ((nint)function).GetHashCode(); + } + + public static bool operator ==(RenderEnginePluginFunction left, RenderEnginePluginFunction right) + { + return left.Equals(right); + } + + public static bool operator !=(RenderEnginePluginFunction left, RenderEnginePluginFunction right) + { + return !(left == right); + } + + public readonly struct Input + { + public readonly World world; + public readonly uint materialEntity; + + private readonly RenderEntity* entities; + private readonly int count; + + public readonly Span Entities => new(entities, count); + + public Input(World world, uint materialEntity, Span entities) + { + this.world = world; + this.materialEntity = materialEntity; + this.entities = entities.GetPointer(); + count = entities.Length; + } + } + } +} \ No newline at end of file diff --git a/source/MaterialData.cs b/source/MaterialData.cs new file mode 100644 index 0000000..e028754 --- /dev/null +++ b/source/MaterialData.cs @@ -0,0 +1,58 @@ +using Materials; +using Materials.Components; +using System; +using Worlds; + +namespace Rendering +{ + public readonly struct MaterialData : IEquatable + { + public readonly uint entity; + public readonly ushort version; + public readonly sbyte order; + + public MaterialData(uint entity, ushort version, sbyte order) + { + this.entity = entity; + this.version = version; + this.order = order; + } + + public MaterialData(uint entity, IsMaterial component) + { + this.entity = entity; + version = component.version; + order = component.order; + } + + public readonly override bool Equals(object? obj) + { + return obj is MaterialData data && Equals(data); + } + + public readonly bool Equals(MaterialData other) + { + return entity == other.entity && version == other.version; + } + + public readonly Material Get(World world) + { + return new Entity(world, entity).As(); + } + + public readonly override int GetHashCode() + { + return HashCode.Combine(entity, version); + } + + public static bool operator ==(MaterialData left, MaterialData right) + { + return left.Equals(right); + } + + public static bool operator !=(MaterialData left, MaterialData right) + { + return !(left == right); + } + } +} \ No newline at end of file diff --git a/source/RenderEntity.cs b/source/RenderEntity.cs new file mode 100644 index 0000000..4017069 --- /dev/null +++ b/source/RenderEntity.cs @@ -0,0 +1,65 @@ +using System; + +namespace Rendering +{ + public readonly struct RenderEntity : IEquatable + { + public readonly uint entity; + public readonly uint meshEntity; + public readonly uint vertexShaderEntity; + public readonly uint fragmentShaderEntity; + public readonly ushort meshVersion; + public readonly ushort vertexShaderVersion; + public readonly ushort fragmentShaderVersion; + + public RenderEntity(uint entity, uint meshEntity, uint vertexShaderEntity, uint fragmentShaderEntity, ushort meshVersion, ushort vertexShaderVersion, ushort fragmentShaderVersion) + { + this.entity = entity; + this.meshEntity = meshEntity; + this.vertexShaderEntity = vertexShaderEntity; + this.fragmentShaderEntity = fragmentShaderEntity; + this.meshVersion = meshVersion; + this.vertexShaderVersion = vertexShaderVersion; + this.fragmentShaderVersion = fragmentShaderVersion; + } + + public readonly override bool Equals(object? obj) + { + return obj is RenderEntity entity && Equals(entity); + } + + public readonly bool Equals(RenderEntity other) + { + return entity == other.entity && + meshEntity == other.meshEntity && + vertexShaderEntity == other.vertexShaderEntity && + fragmentShaderEntity == other.fragmentShaderEntity && + meshVersion == other.meshVersion && + vertexShaderVersion == other.vertexShaderVersion && + fragmentShaderVersion == other.fragmentShaderVersion; + } + + public readonly override int GetHashCode() + { + HashCode hash = new(); + hash.Add(entity); + hash.Add(meshEntity); + hash.Add(vertexShaderEntity); + hash.Add(fragmentShaderEntity); + hash.Add(meshVersion); + hash.Add(vertexShaderVersion); + hash.Add(fragmentShaderVersion); + return hash.ToHashCode(); + } + + public static bool operator ==(RenderEntity left, RenderEntity right) + { + return left.Equals(right); + } + + public static bool operator !=(RenderEntity left, RenderEntity right) + { + return !(left == right); + } + } +} \ No newline at end of file diff --git a/source/RendererCombination.cs b/source/RendererCombination.cs new file mode 100644 index 0000000..5f737ee --- /dev/null +++ b/source/RendererCombination.cs @@ -0,0 +1,55 @@ +using System; + +namespace Rendering +{ + public struct RendererCombination : IEquatable + { + public uint materialEntity; + public uint meshEntity; + public uint vertexShaderEntity; + public uint fragmentShaderEntity; + + public readonly ulong Key => ((ulong)materialEntity << 32) | meshEntity; + + public RendererCombination(uint materialEntity, uint meshEntity, uint vertexShaderEntity, uint fragmentShaderEntity) + { + this.materialEntity = materialEntity; + this.meshEntity = meshEntity; + this.vertexShaderEntity = vertexShaderEntity; + this.fragmentShaderEntity = fragmentShaderEntity; + } + + public readonly override bool Equals(object? obj) + { + return obj is RendererCombination combination && Equals(combination); + } + + public readonly bool Equals(RendererCombination other) + { + return materialEntity == other.materialEntity && meshEntity == other.meshEntity && vertexShaderEntity == other.vertexShaderEntity && fragmentShaderEntity == other.fragmentShaderEntity; + } + + public readonly override int GetHashCode() + { + unchecked + { + int hash = 17; + hash = hash * 23 + (int)materialEntity; + hash = hash * 23 + (int)meshEntity; + hash = hash * 23 + (int)vertexShaderEntity; + hash = hash * 23 + (int)fragmentShaderEntity; + return hash; + } + } + + public static bool operator ==(RendererCombination left, RendererCombination right) + { + return left.Equals(right); + } + + public static bool operator !=(RendererCombination left, RendererCombination right) + { + return !(left == right); + } + } +} \ No newline at end of file diff --git a/source/RendererEnginePlugin.cs b/source/RendererEnginePlugin.cs new file mode 100644 index 0000000..ab3916a --- /dev/null +++ b/source/RendererEnginePlugin.cs @@ -0,0 +1,19 @@ +using Rendering.Functions; +using Worlds; + +namespace Rendering +{ + public readonly partial struct RenderEnginePlugin : IEntity + { + public RenderEnginePlugin(World world, RenderEnginePluginFunction function) + { + this.world = world; + value = world.CreateEntity(function); + } + + void IEntity.Describe(ref Archetype archetype) + { + archetype.AddComponentType(); + } + } +} \ No newline at end of file diff --git a/source/Rendering.csproj b/source/Rendering.csproj index 7bd1b80..a1e142d 100644 --- a/source/Rendering.csproj +++ b/source/Rendering.csproj @@ -11,13 +11,13 @@ https://github.com/simulation-tree/rendering True True - + - - - + + + Analyzer false From ed3dd406ca066092a156bd34af87189dd3c89c39 Mon Sep 17 00:00:00 2001 From: Phill Date: Thu, 17 Apr 2025 18:26:55 -0400 Subject: [PATCH 2/3] add overloads to create through a static function --- source/RendererEnginePlugin.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/source/RendererEnginePlugin.cs b/source/RendererEnginePlugin.cs index ab3916a..bc34f83 100644 --- a/source/RendererEnginePlugin.cs +++ b/source/RendererEnginePlugin.cs @@ -11,9 +11,25 @@ public RenderEnginePlugin(World world, RenderEnginePluginFunction function) value = world.CreateEntity(function); } + public unsafe RenderEnginePlugin(World world, delegate* unmanaged function) + { + this.world = world; + value = world.CreateEntity(new RenderEnginePluginFunction(function)); + } + void IEntity.Describe(ref Archetype archetype) { archetype.AddComponentType(); } + + public static RenderEnginePlugin Create(World world, RenderEnginePluginFunction function) + { + return new(world, function); + } + + public unsafe static RenderEnginePlugin Create(World world, delegate* unmanaged function) + { + return new(world, function); + } } } \ No newline at end of file From ee941014f5f547d8e29a632a31d86fb965396d13 Mon Sep 17 00:00:00 2001 From: Phill Date: Mon, 21 Apr 2025 13:51:56 -0400 Subject: [PATCH 3/3] sort based on render groups instead of materials --- source/Functions/RenderEnginePluginFunction.cs | 10 +++++----- source/MaterialData.cs | 2 +- source/RenderEntity.cs | 18 +++++++++++------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/source/Functions/RenderEnginePluginFunction.cs b/source/Functions/RenderEnginePluginFunction.cs index 34d8d38..b86e065 100644 --- a/source/Functions/RenderEnginePluginFunction.cs +++ b/source/Functions/RenderEnginePluginFunction.cs @@ -21,9 +21,9 @@ public PluginBeforeRendering(delegate* function) } #endif - public readonly void Invoke(World world, uint materialEntity, Span entities) + public readonly void Invoke(World world, sbyte renderGroup, Span entities) { - function(new(world, materialEntity, entities)); + function(new(world, renderGroup, entities)); } public readonly override bool Equals(object? obj) @@ -54,17 +54,17 @@ public readonly override int GetHashCode() public readonly struct Input { public readonly World world; - public readonly uint materialEntity; + public readonly sbyte renderGroup; private readonly RenderEntity* entities; private readonly int count; public readonly Span Entities => new(entities, count); - public Input(World world, uint materialEntity, Span entities) + public Input(World world, sbyte renderGroup, Span entities) { this.world = world; - this.materialEntity = materialEntity; + this.renderGroup = renderGroup; this.entities = entities.GetPointer(); count = entities.Length; } diff --git a/source/MaterialData.cs b/source/MaterialData.cs index e028754..cfb518b 100644 --- a/source/MaterialData.cs +++ b/source/MaterialData.cs @@ -22,7 +22,7 @@ public MaterialData(uint entity, IsMaterial component) { this.entity = entity; version = component.version; - order = component.order; + order = component.renderGroup; } public readonly override bool Equals(object? obj) diff --git a/source/RenderEntity.cs b/source/RenderEntity.cs index 4017069..d34e407 100644 --- a/source/RenderEntity.cs +++ b/source/RenderEntity.cs @@ -6,16 +6,18 @@ namespace Rendering { public readonly uint entity; public readonly uint meshEntity; + public readonly uint materialEntity; public readonly uint vertexShaderEntity; public readonly uint fragmentShaderEntity; public readonly ushort meshVersion; public readonly ushort vertexShaderVersion; public readonly ushort fragmentShaderVersion; - public RenderEntity(uint entity, uint meshEntity, uint vertexShaderEntity, uint fragmentShaderEntity, ushort meshVersion, ushort vertexShaderVersion, ushort fragmentShaderVersion) + public RenderEntity(uint entity, uint meshEntity, uint materialEntity, uint vertexShaderEntity, uint fragmentShaderEntity, ushort meshVersion, ushort vertexShaderVersion, ushort fragmentShaderVersion) { this.entity = entity; this.meshEntity = meshEntity; + this.materialEntity = materialEntity; this.vertexShaderEntity = vertexShaderEntity; this.fragmentShaderEntity = fragmentShaderEntity; this.meshVersion = meshVersion; @@ -31,12 +33,13 @@ public readonly override bool Equals(object? obj) public readonly bool Equals(RenderEntity other) { return entity == other.entity && - meshEntity == other.meshEntity && - vertexShaderEntity == other.vertexShaderEntity && - fragmentShaderEntity == other.fragmentShaderEntity && - meshVersion == other.meshVersion && - vertexShaderVersion == other.vertexShaderVersion && - fragmentShaderVersion == other.fragmentShaderVersion; + meshEntity == other.meshEntity && + materialEntity == other.materialEntity && + vertexShaderEntity == other.vertexShaderEntity && + fragmentShaderEntity == other.fragmentShaderEntity && + meshVersion == other.meshVersion && + vertexShaderVersion == other.vertexShaderVersion && + fragmentShaderVersion == other.fragmentShaderVersion; } public readonly override int GetHashCode() @@ -44,6 +47,7 @@ public readonly override int GetHashCode() HashCode hash = new(); hash.Add(entity); hash.Add(meshEntity); + hash.Add(materialEntity); hash.Add(vertexShaderEntity); hash.Add(fragmentShaderEntity); hash.Add(meshVersion);