feat(render): add meshlet rendering and ECS query ref API

Introduces meshlet-based rendering pipeline with new HLSL structures and push constant layouts. Refactors meshlet upload/cooking, updates RenderGraphContext for global/view/instance data, and enhances ECS QueryBuilder with ref returns and [UnscopedRef] for fluent chaining. Improves resource management and disposal patterns, updates D3D12 interop for compatibility, and refines test/app infrastructure. Includes dependency updates, bug fixes, and code cleanups.
This commit is contained in:
2026-03-25 20:27:46 +09:00
parent b729ca86f5
commit 447a4e6904
28 changed files with 407 additions and 165 deletions

View File

@@ -636,6 +636,10 @@ public ref partial struct QueryBuilder : IDisposable
{
Dispose();
}
else
{
Clear();
}
return query;
}

View File

@@ -340,7 +340,7 @@ public abstract class SystemGroup : ISystem
public sealed class DefaultSystemGroup : SystemGroup;
public sealed class SystemManager
public sealed class SystemManager : IDisposable
{
private readonly World _world;
@@ -415,4 +415,9 @@ public sealed class SystemManager
system.Cleanup(in systemAPI);
}
}
public void Dispose()
{
CleanupAll(default);
}
}

View File

@@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Ghost.Entities;
@@ -10,12 +11,13 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAll<T0>()
[UnscopedRef]
public ref QueryBuilder WithAll<T0>()
where T0 : unmanaged, IComponent
{
_all.Add(ComponentTypeID<T0>.Value);
return this;
return ref this;
}
/// <summary>
@@ -23,13 +25,14 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAllRW<T0>()
[UnscopedRef]
public ref QueryBuilder WithAllRW<T0>()
where T0 : unmanaged, IComponent
{
_all.Add(ComponentTypeID<T0>.Value);
_rw.Add(ComponentTypeID<T0>.Value);
return this;
return ref this;
}
/// <summary>
@@ -37,12 +40,13 @@ public ref partial struct QueryBuilder
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAny<T0>()
[UnscopedRef]
public ref QueryBuilder WithAny<T0>()
where T0 : unmanaged, IComponent
{
_any.Add(ComponentTypeID<T0>.Value);
return this;
return ref this;
}
/// <summary>
@@ -50,12 +54,13 @@ public ref partial struct QueryBuilder
/// Targets entities that do not have any of the specified component types.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAbsent<T0>()
[UnscopedRef]
public ref QueryBuilder WithAbsent<T0>()
where T0 : unmanaged, IComponent
{
_absent.Add(ComponentTypeID<T0>.Value);
return this;
return ref this;
}
/// <summary>
@@ -63,12 +68,13 @@ public ref partial struct QueryBuilder
/// Targets entities that do not have any of the specified component types, or those component(s) are disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithNone<T0>()
[UnscopedRef]
public ref QueryBuilder WithNone<T0>()
where T0 : unmanaged, IComponent
{
_none.Add(ComponentTypeID<T0>.Value);
return this;
return ref this;
}
/// <summary>
@@ -76,12 +82,13 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) are disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithDisabled<T0>()
[UnscopedRef]
public ref QueryBuilder WithDisabled<T0>()
where T0 : unmanaged, IEnableableComponent
{
_disabled.Add(ComponentTypeID<T0>.Value);
return this;
return ref this;
}
/// <summary>
@@ -89,12 +96,13 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithPresent<T0>()
[UnscopedRef]
public ref QueryBuilder WithPresent<T0>()
where T0 : unmanaged, IComponent
{
_present.Add(ComponentTypeID<T0>.Value);
return this;
return ref this;
}
/// <summary>
@@ -102,13 +110,14 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithPresentRW<T0>()
[UnscopedRef]
public ref QueryBuilder WithPresentRW<T0>()
where T0 : unmanaged, IComponent
{
_present.Add(ComponentTypeID<T0>.Value);
_rw.Add(ComponentTypeID<T0>.Value);
return this;
return ref this;
}
/// <summary>
@@ -116,14 +125,15 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAll<T0, T1>()
[UnscopedRef]
public ref QueryBuilder WithAll<T0, T1>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_all.Add(ComponentTypeID<T0>.Value);
_all.Add(ComponentTypeID<T1>.Value);
return this;
return ref this;
}
/// <summary>
@@ -131,7 +141,8 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAllRW<T0, T1>()
[UnscopedRef]
public ref QueryBuilder WithAllRW<T0, T1>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
@@ -140,7 +151,7 @@ public ref partial struct QueryBuilder
_all.Add(ComponentTypeID<T1>.Value);
_rw.Add(ComponentTypeID<T1>.Value);
return this;
return ref this;
}
/// <summary>
@@ -148,14 +159,15 @@ public ref partial struct QueryBuilder
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAny<T0, T1>()
[UnscopedRef]
public ref QueryBuilder WithAny<T0, T1>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_any.Add(ComponentTypeID<T0>.Value);
_any.Add(ComponentTypeID<T1>.Value);
return this;
return ref this;
}
/// <summary>
@@ -163,14 +175,15 @@ public ref partial struct QueryBuilder
/// Targets entities that do not have any of the specified component types.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAbsent<T0, T1>()
[UnscopedRef]
public ref QueryBuilder WithAbsent<T0, T1>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_absent.Add(ComponentTypeID<T0>.Value);
_absent.Add(ComponentTypeID<T1>.Value);
return this;
return ref this;
}
/// <summary>
@@ -178,14 +191,15 @@ public ref partial struct QueryBuilder
/// Targets entities that do not have any of the specified component types, or those component(s) are disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithNone<T0, T1>()
[UnscopedRef]
public ref QueryBuilder WithNone<T0, T1>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_none.Add(ComponentTypeID<T0>.Value);
_none.Add(ComponentTypeID<T1>.Value);
return this;
return ref this;
}
/// <summary>
@@ -193,14 +207,15 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) are disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithDisabled<T0, T1>()
[UnscopedRef]
public ref QueryBuilder WithDisabled<T0, T1>()
where T0 : unmanaged, IEnableableComponent
where T1 : unmanaged, IEnableableComponent
{
_disabled.Add(ComponentTypeID<T0>.Value);
_disabled.Add(ComponentTypeID<T1>.Value);
return this;
return ref this;
}
/// <summary>
@@ -208,14 +223,15 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithPresent<T0, T1>()
[UnscopedRef]
public ref QueryBuilder WithPresent<T0, T1>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
_present.Add(ComponentTypeID<T0>.Value);
_present.Add(ComponentTypeID<T1>.Value);
return this;
return ref this;
}
/// <summary>
@@ -223,7 +239,8 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithPresentRW<T0, T1>()
[UnscopedRef]
public ref QueryBuilder WithPresentRW<T0, T1>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
{
@@ -232,7 +249,7 @@ public ref partial struct QueryBuilder
_present.Add(ComponentTypeID<T1>.Value);
_rw.Add(ComponentTypeID<T1>.Value);
return this;
return ref this;
}
/// <summary>
@@ -240,7 +257,8 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAll<T0, T1, T2>()
[UnscopedRef]
public ref QueryBuilder WithAll<T0, T1, T2>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
@@ -249,7 +267,7 @@ public ref partial struct QueryBuilder
_all.Add(ComponentTypeID<T1>.Value);
_all.Add(ComponentTypeID<T2>.Value);
return this;
return ref this;
}
/// <summary>
@@ -257,7 +275,8 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAllRW<T0, T1, T2>()
[UnscopedRef]
public ref QueryBuilder WithAllRW<T0, T1, T2>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
@@ -269,7 +288,7 @@ public ref partial struct QueryBuilder
_all.Add(ComponentTypeID<T2>.Value);
_rw.Add(ComponentTypeID<T2>.Value);
return this;
return ref this;
}
/// <summary>
@@ -277,7 +296,8 @@ public ref partial struct QueryBuilder
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAny<T0, T1, T2>()
[UnscopedRef]
public ref QueryBuilder WithAny<T0, T1, T2>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
@@ -286,7 +306,7 @@ public ref partial struct QueryBuilder
_any.Add(ComponentTypeID<T1>.Value);
_any.Add(ComponentTypeID<T2>.Value);
return this;
return ref this;
}
/// <summary>
@@ -294,7 +314,8 @@ public ref partial struct QueryBuilder
/// Targets entities that do not have any of the specified component types.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAbsent<T0, T1, T2>()
[UnscopedRef]
public ref QueryBuilder WithAbsent<T0, T1, T2>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
@@ -303,7 +324,7 @@ public ref partial struct QueryBuilder
_absent.Add(ComponentTypeID<T1>.Value);
_absent.Add(ComponentTypeID<T2>.Value);
return this;
return ref this;
}
/// <summary>
@@ -311,7 +332,8 @@ public ref partial struct QueryBuilder
/// Targets entities that do not have any of the specified component types, or those component(s) are disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithNone<T0, T1, T2>()
[UnscopedRef]
public ref QueryBuilder WithNone<T0, T1, T2>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
@@ -320,7 +342,7 @@ public ref partial struct QueryBuilder
_none.Add(ComponentTypeID<T1>.Value);
_none.Add(ComponentTypeID<T2>.Value);
return this;
return ref this;
}
/// <summary>
@@ -328,7 +350,8 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) are disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithDisabled<T0, T1, T2>()
[UnscopedRef]
public ref QueryBuilder WithDisabled<T0, T1, T2>()
where T0 : unmanaged, IEnableableComponent
where T1 : unmanaged, IEnableableComponent
where T2 : unmanaged, IEnableableComponent
@@ -337,7 +360,7 @@ public ref partial struct QueryBuilder
_disabled.Add(ComponentTypeID<T1>.Value);
_disabled.Add(ComponentTypeID<T2>.Value);
return this;
return ref this;
}
/// <summary>
@@ -345,7 +368,8 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithPresent<T0, T1, T2>()
[UnscopedRef]
public ref QueryBuilder WithPresent<T0, T1, T2>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
@@ -354,7 +378,7 @@ public ref partial struct QueryBuilder
_present.Add(ComponentTypeID<T1>.Value);
_present.Add(ComponentTypeID<T2>.Value);
return this;
return ref this;
}
/// <summary>
@@ -362,7 +386,8 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithPresentRW<T0, T1, T2>()
[UnscopedRef]
public ref QueryBuilder WithPresentRW<T0, T1, T2>()
where T0 : unmanaged, IComponent
where T1 : unmanaged, IComponent
where T2 : unmanaged, IComponent
@@ -374,7 +399,7 @@ public ref partial struct QueryBuilder
_present.Add(ComponentTypeID<T2>.Value);
_rw.Add(ComponentTypeID<T2>.Value);
return this;
return ref this;
}
}

View File

@@ -4,6 +4,7 @@
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ include file="Helpers.ttinclude" #>
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Ghost.Entities;
@@ -21,14 +22,15 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAll<<#= generics #>>()
[UnscopedRef]
public ref QueryBuilder WithAll<<#= generics #>>()
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_all.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
return ref this;
}
/// <summary>
@@ -36,7 +38,8 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAllRW<<#= generics #>>()
[UnscopedRef]
public ref QueryBuilder WithAllRW<<#= generics #>>()
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
@@ -44,7 +47,7 @@ public ref partial struct QueryBuilder
_rw.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
return ref this;
}
/// <summary>
@@ -52,14 +55,15 @@ public ref partial struct QueryBuilder
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAny<<#= generics #>>()
[UnscopedRef]
public ref QueryBuilder WithAny<<#= generics #>>()
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_any.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
return ref this;
}
/// <summary>
@@ -67,14 +71,15 @@ public ref partial struct QueryBuilder
/// Targets entities that do not have any of the specified component types.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithAbsent<<#= generics #>>()
[UnscopedRef]
public ref QueryBuilder WithAbsent<<#= generics #>>()
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_absent.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
return ref this;
}
/// <summary>
@@ -82,14 +87,15 @@ public ref partial struct QueryBuilder
/// Targets entities that do not have any of the specified component types, or those component(s) are disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithNone<<#= generics #>>()
[UnscopedRef]
public ref QueryBuilder WithNone<<#= generics #>>()
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_none.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
return ref this;
}
/// <summary>
@@ -97,14 +103,15 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types and those component(s) are disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithDisabled<<#= generics #>>()
[UnscopedRef]
public ref QueryBuilder WithDisabled<<#= generics #>>()
<#= enableRestrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_disabled.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
return ref this;
}
/// <summary>
@@ -112,14 +119,15 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithPresent<<#= generics #>>()
[UnscopedRef]
public ref QueryBuilder WithPresent<<#= generics #>>()
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
_present.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
return ref this;
}
/// <summary>
@@ -127,7 +135,8 @@ public ref partial struct QueryBuilder
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public QueryBuilder WithPresentRW<<#= generics #>>()
[UnscopedRef]
public ref QueryBuilder WithPresentRW<<#= generics #>>()
<#= restrictions #>
{
<# for (var j = 0; j < i; j++) { #>
@@ -135,7 +144,7 @@ public ref partial struct QueryBuilder
_rw.Add(ComponentTypeID<T<#= j #>>.Value);
<# } #>
return this;
return ref this;
}
<# } #>

View File

@@ -268,6 +268,9 @@ public partial class World : IDisposable, IEquatable<World>
}
}
_componentManager.Dispose();
_systemManager.Dispose();
s_freeWorldSlots.Enqueue(_id);
s_worlds[_id] = null;