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:
@@ -1,4 +1,4 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("Ghost.Shader.Test")]
|
[assembly: InternalsVisibleTo("Ghost.Shader.Test")]
|
||||||
[assembly: InternalsVisibleTo("Ghost.Graphics")]
|
[assembly: InternalsVisibleTo("Ghost.Graphics.Test")]
|
||||||
@@ -48,6 +48,6 @@ internal partial class ConsoleViewModel : ObservableObject
|
|||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void ClearLogs()
|
private void ClearLogs()
|
||||||
{
|
{
|
||||||
Logger.Clear();
|
//Logger.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Misaki.HighPerformance" Version="1.0.4" />
|
<PackageReference Include="Misaki.HighPerformance" Version="1.0.5" />
|
||||||
<PackageReference Include="Misaki.HighPerformance.Jobs" Version="1.5.3" />
|
<PackageReference Include="Misaki.HighPerformance.Jobs" Version="1.5.3" />
|
||||||
<PackageReference Include="Misaki.HighPerformance.LowLevel" Version="1.5.2">
|
<PackageReference Include="Misaki.HighPerformance.LowLevel" Version="1.5.4">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ public class RenderExtractionSystem : ISystem
|
|||||||
var rtSize = new uint2(rtResult.Value.TextureDescription.Width, rtResult.Value.TextureDescription.Height);
|
var rtSize = new uint2(rtResult.Value.TextureDescription.Width, rtResult.Value.TextureDescription.Height);
|
||||||
var aspectScreen = (float)rtSize.x / rtSize.y;
|
var aspectScreen = (float)rtSize.x / rtSize.y;
|
||||||
|
|
||||||
|
// TODO: Classify transparent objects into a separate render list and render via oit.
|
||||||
var renderList = new RenderList(1, 64, Allocator.FreeList);
|
var renderList = new RenderList(1, 64, Allocator.FreeList);
|
||||||
var transparentRenderList = new RenderList(1, 64, Allocator.FreeList);
|
var transparentRenderList = new RenderList(1, 64, Allocator.FreeList);
|
||||||
var shadowCasterRenderList = new RenderList(1, 64, Allocator.FreeList);
|
var shadowCasterRenderList = new RenderList(1, 64, Allocator.FreeList);
|
||||||
@@ -215,7 +216,7 @@ public class RenderExtractionSystem : ISystem
|
|||||||
depthTarget = camRef.depthTarget,
|
depthTarget = camRef.depthTarget,
|
||||||
opaqueRenderList = renderList,
|
opaqueRenderList = renderList,
|
||||||
shadowCasterRenderList = shadowCasterRenderList,
|
shadowCasterRenderList = shadowCasterRenderList,
|
||||||
transparentRenderList = default, // TODO: Classify transparent objects into a separate render list and render via oit.
|
transparentRenderList = transparentRenderList,
|
||||||
renderFunc = camRef.renderFunc,
|
renderFunc = camRef.renderFunc,
|
||||||
view = new RenderView
|
view = new RenderView
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -636,6 +636,10 @@ public ref partial struct QueryBuilder : IDisposable
|
|||||||
{
|
{
|
||||||
Dispose();
|
Dispose();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ public abstract class SystemGroup : ISystem
|
|||||||
|
|
||||||
public sealed class DefaultSystemGroup : SystemGroup;
|
public sealed class DefaultSystemGroup : SystemGroup;
|
||||||
|
|
||||||
public sealed class SystemManager
|
public sealed class SystemManager : IDisposable
|
||||||
{
|
{
|
||||||
private readonly World _world;
|
private readonly World _world;
|
||||||
|
|
||||||
@@ -415,4 +415,9 @@ public sealed class SystemManager
|
|||||||
system.Cleanup(in systemAPI);
|
system.Cleanup(in systemAPI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
CleanupAll(default);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Ghost.Entities;
|
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.
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAll<T0>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAll<T0>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_all.Add(ComponentTypeID<T0>.Value);
|
_all.Add(ComponentTypeID<T0>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAllRW<T0>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAllRW<T0>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_all.Add(ComponentTypeID<T0>.Value);
|
_all.Add(ComponentTypeID<T0>.Value);
|
||||||
_rw.Add(ComponentTypeID<T0>.Value);
|
_rw.Add(ComponentTypeID<T0>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAny<T0>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAny<T0>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_any.Add(ComponentTypeID<T0>.Value);
|
_any.Add(ComponentTypeID<T0>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -50,12 +54,13 @@ public ref partial struct QueryBuilder
|
|||||||
/// Targets entities that do not have any of the specified component types.
|
/// Targets entities that do not have any of the specified component types.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAbsent<T0>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAbsent<T0>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_absent.Add(ComponentTypeID<T0>.Value);
|
_absent.Add(ComponentTypeID<T0>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that do not have any of the specified component types, or those component(s) are disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithNone<T0>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithNone<T0>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_none.Add(ComponentTypeID<T0>.Value);
|
_none.Add(ComponentTypeID<T0>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types and those component(s) are disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithDisabled<T0>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithDisabled<T0>()
|
||||||
where T0 : unmanaged, IEnableableComponent
|
where T0 : unmanaged, IEnableableComponent
|
||||||
{
|
{
|
||||||
_disabled.Add(ComponentTypeID<T0>.Value);
|
_disabled.Add(ComponentTypeID<T0>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithPresent<T0>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithPresent<T0>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_present.Add(ComponentTypeID<T0>.Value);
|
_present.Add(ComponentTypeID<T0>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithPresentRW<T0>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithPresentRW<T0>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_present.Add(ComponentTypeID<T0>.Value);
|
_present.Add(ComponentTypeID<T0>.Value);
|
||||||
_rw.Add(ComponentTypeID<T0>.Value);
|
_rw.Add(ComponentTypeID<T0>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAll<T0, T1>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAll<T0, T1>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_all.Add(ComponentTypeID<T0>.Value);
|
_all.Add(ComponentTypeID<T0>.Value);
|
||||||
_all.Add(ComponentTypeID<T1>.Value);
|
_all.Add(ComponentTypeID<T1>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAllRW<T0, T1>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAllRW<T0, T1>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
@@ -140,7 +151,7 @@ public ref partial struct QueryBuilder
|
|||||||
_all.Add(ComponentTypeID<T1>.Value);
|
_all.Add(ComponentTypeID<T1>.Value);
|
||||||
_rw.Add(ComponentTypeID<T1>.Value);
|
_rw.Add(ComponentTypeID<T1>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAny<T0, T1>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAny<T0, T1>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_any.Add(ComponentTypeID<T0>.Value);
|
_any.Add(ComponentTypeID<T0>.Value);
|
||||||
_any.Add(ComponentTypeID<T1>.Value);
|
_any.Add(ComponentTypeID<T1>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -163,14 +175,15 @@ public ref partial struct QueryBuilder
|
|||||||
/// Targets entities that do not have any of the specified component types.
|
/// Targets entities that do not have any of the specified component types.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAbsent<T0, T1>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAbsent<T0, T1>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_absent.Add(ComponentTypeID<T0>.Value);
|
_absent.Add(ComponentTypeID<T0>.Value);
|
||||||
_absent.Add(ComponentTypeID<T1>.Value);
|
_absent.Add(ComponentTypeID<T1>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that do not have any of the specified component types, or those component(s) are disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithNone<T0, T1>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithNone<T0, T1>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_none.Add(ComponentTypeID<T0>.Value);
|
_none.Add(ComponentTypeID<T0>.Value);
|
||||||
_none.Add(ComponentTypeID<T1>.Value);
|
_none.Add(ComponentTypeID<T1>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types and those component(s) are disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithDisabled<T0, T1>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithDisabled<T0, T1>()
|
||||||
where T0 : unmanaged, IEnableableComponent
|
where T0 : unmanaged, IEnableableComponent
|
||||||
where T1 : unmanaged, IEnableableComponent
|
where T1 : unmanaged, IEnableableComponent
|
||||||
{
|
{
|
||||||
_disabled.Add(ComponentTypeID<T0>.Value);
|
_disabled.Add(ComponentTypeID<T0>.Value);
|
||||||
_disabled.Add(ComponentTypeID<T1>.Value);
|
_disabled.Add(ComponentTypeID<T1>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithPresent<T0, T1>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithPresent<T0, T1>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
_present.Add(ComponentTypeID<T0>.Value);
|
_present.Add(ComponentTypeID<T0>.Value);
|
||||||
_present.Add(ComponentTypeID<T1>.Value);
|
_present.Add(ComponentTypeID<T1>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithPresentRW<T0, T1>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithPresentRW<T0, T1>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
{
|
{
|
||||||
@@ -232,7 +249,7 @@ public ref partial struct QueryBuilder
|
|||||||
_present.Add(ComponentTypeID<T1>.Value);
|
_present.Add(ComponentTypeID<T1>.Value);
|
||||||
_rw.Add(ComponentTypeID<T1>.Value);
|
_rw.Add(ComponentTypeID<T1>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAll<T0, T1, T2>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAll<T0, T1, T2>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
where T2 : unmanaged, IComponent
|
where T2 : unmanaged, IComponent
|
||||||
@@ -249,7 +267,7 @@ public ref partial struct QueryBuilder
|
|||||||
_all.Add(ComponentTypeID<T1>.Value);
|
_all.Add(ComponentTypeID<T1>.Value);
|
||||||
_all.Add(ComponentTypeID<T2>.Value);
|
_all.Add(ComponentTypeID<T2>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAllRW<T0, T1, T2>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAllRW<T0, T1, T2>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
where T2 : unmanaged, IComponent
|
where T2 : unmanaged, IComponent
|
||||||
@@ -269,7 +288,7 @@ public ref partial struct QueryBuilder
|
|||||||
_all.Add(ComponentTypeID<T2>.Value);
|
_all.Add(ComponentTypeID<T2>.Value);
|
||||||
_rw.Add(ComponentTypeID<T2>.Value);
|
_rw.Add(ComponentTypeID<T2>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAny<T0, T1, T2>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAny<T0, T1, T2>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
where T2 : unmanaged, IComponent
|
where T2 : unmanaged, IComponent
|
||||||
@@ -286,7 +306,7 @@ public ref partial struct QueryBuilder
|
|||||||
_any.Add(ComponentTypeID<T1>.Value);
|
_any.Add(ComponentTypeID<T1>.Value);
|
||||||
_any.Add(ComponentTypeID<T2>.Value);
|
_any.Add(ComponentTypeID<T2>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -294,7 +314,8 @@ public ref partial struct QueryBuilder
|
|||||||
/// Targets entities that do not have any of the specified component types.
|
/// Targets entities that do not have any of the specified component types.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAbsent<T0, T1, T2>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAbsent<T0, T1, T2>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
where T2 : unmanaged, IComponent
|
where T2 : unmanaged, IComponent
|
||||||
@@ -303,7 +324,7 @@ public ref partial struct QueryBuilder
|
|||||||
_absent.Add(ComponentTypeID<T1>.Value);
|
_absent.Add(ComponentTypeID<T1>.Value);
|
||||||
_absent.Add(ComponentTypeID<T2>.Value);
|
_absent.Add(ComponentTypeID<T2>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that do not have any of the specified component types, or those component(s) are disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithNone<T0, T1, T2>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithNone<T0, T1, T2>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
where T2 : unmanaged, IComponent
|
where T2 : unmanaged, IComponent
|
||||||
@@ -320,7 +342,7 @@ public ref partial struct QueryBuilder
|
|||||||
_none.Add(ComponentTypeID<T1>.Value);
|
_none.Add(ComponentTypeID<T1>.Value);
|
||||||
_none.Add(ComponentTypeID<T2>.Value);
|
_none.Add(ComponentTypeID<T2>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types and those component(s) are disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithDisabled<T0, T1, T2>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithDisabled<T0, T1, T2>()
|
||||||
where T0 : unmanaged, IEnableableComponent
|
where T0 : unmanaged, IEnableableComponent
|
||||||
where T1 : unmanaged, IEnableableComponent
|
where T1 : unmanaged, IEnableableComponent
|
||||||
where T2 : unmanaged, IEnableableComponent
|
where T2 : unmanaged, IEnableableComponent
|
||||||
@@ -337,7 +360,7 @@ public ref partial struct QueryBuilder
|
|||||||
_disabled.Add(ComponentTypeID<T1>.Value);
|
_disabled.Add(ComponentTypeID<T1>.Value);
|
||||||
_disabled.Add(ComponentTypeID<T2>.Value);
|
_disabled.Add(ComponentTypeID<T2>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithPresent<T0, T1, T2>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithPresent<T0, T1, T2>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
where T2 : unmanaged, IComponent
|
where T2 : unmanaged, IComponent
|
||||||
@@ -354,7 +378,7 @@ public ref partial struct QueryBuilder
|
|||||||
_present.Add(ComponentTypeID<T1>.Value);
|
_present.Add(ComponentTypeID<T1>.Value);
|
||||||
_present.Add(ComponentTypeID<T2>.Value);
|
_present.Add(ComponentTypeID<T2>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithPresentRW<T0, T1, T2>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithPresentRW<T0, T1, T2>()
|
||||||
where T0 : unmanaged, IComponent
|
where T0 : unmanaged, IComponent
|
||||||
where T1 : unmanaged, IComponent
|
where T1 : unmanaged, IComponent
|
||||||
where T2 : unmanaged, IComponent
|
where T2 : unmanaged, IComponent
|
||||||
@@ -374,7 +399,7 @@ public ref partial struct QueryBuilder
|
|||||||
_present.Add(ComponentTypeID<T2>.Value);
|
_present.Add(ComponentTypeID<T2>.Value);
|
||||||
_rw.Add(ComponentTypeID<T2>.Value);
|
_rw.Add(ComponentTypeID<T2>.Value);
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
<#@ import namespace="System.Linq" #>
|
<#@ import namespace="System.Linq" #>
|
||||||
<#@ import namespace="System.Text" #>
|
<#@ import namespace="System.Text" #>
|
||||||
<#@ include file="Helpers.ttinclude" #>
|
<#@ include file="Helpers.ttinclude" #>
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Ghost.Entities;
|
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.
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAll<<#= generics #>>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAll<<#= generics #>>()
|
||||||
<#= restrictions #>
|
<#= restrictions #>
|
||||||
{
|
{
|
||||||
<# for (var j = 0; j < i; j++) { #>
|
<# for (var j = 0; j < i; j++) { #>
|
||||||
_all.Add(ComponentTypeID<T<#= j #>>.Value);
|
_all.Add(ComponentTypeID<T<#= j #>>.Value);
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAllRW<<#= generics #>>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAllRW<<#= generics #>>()
|
||||||
<#= restrictions #>
|
<#= restrictions #>
|
||||||
{
|
{
|
||||||
<# for (var j = 0; j < i; j++) { #>
|
<# for (var j = 0; j < i; j++) { #>
|
||||||
@@ -44,7 +47,7 @@ public ref partial struct QueryBuilder
|
|||||||
_rw.Add(ComponentTypeID<T<#= j #>>.Value);
|
_rw.Add(ComponentTypeID<T<#= j #>>.Value);
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have at least one of the specified component types and those component(s) must be enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAny<<#= generics #>>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAny<<#= generics #>>()
|
||||||
<#= restrictions #>
|
<#= restrictions #>
|
||||||
{
|
{
|
||||||
<# for (var j = 0; j < i; j++) { #>
|
<# for (var j = 0; j < i; j++) { #>
|
||||||
_any.Add(ComponentTypeID<T<#= j #>>.Value);
|
_any.Add(ComponentTypeID<T<#= j #>>.Value);
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -67,14 +71,15 @@ public ref partial struct QueryBuilder
|
|||||||
/// Targets entities that do not have any of the specified component types.
|
/// Targets entities that do not have any of the specified component types.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithAbsent<<#= generics #>>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithAbsent<<#= generics #>>()
|
||||||
<#= restrictions #>
|
<#= restrictions #>
|
||||||
{
|
{
|
||||||
<# for (var j = 0; j < i; j++) { #>
|
<# for (var j = 0; j < i; j++) { #>
|
||||||
_absent.Add(ComponentTypeID<T<#= j #>>.Value);
|
_absent.Add(ComponentTypeID<T<#= j #>>.Value);
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that do not have any of the specified component types, or those component(s) are disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithNone<<#= generics #>>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithNone<<#= generics #>>()
|
||||||
<#= restrictions #>
|
<#= restrictions #>
|
||||||
{
|
{
|
||||||
<# for (var j = 0; j < i; j++) { #>
|
<# for (var j = 0; j < i; j++) { #>
|
||||||
_none.Add(ComponentTypeID<T<#= j #>>.Value);
|
_none.Add(ComponentTypeID<T<#= j #>>.Value);
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types and those component(s) are disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithDisabled<<#= generics #>>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithDisabled<<#= generics #>>()
|
||||||
<#= enableRestrictions #>
|
<#= enableRestrictions #>
|
||||||
{
|
{
|
||||||
<# for (var j = 0; j < i; j++) { #>
|
<# for (var j = 0; j < i; j++) { #>
|
||||||
_disabled.Add(ComponentTypeID<T<#= j #>>.Value);
|
_disabled.Add(ComponentTypeID<T<#= j #>>.Value);
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithPresent<<#= generics #>>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithPresent<<#= generics #>>()
|
||||||
<#= restrictions #>
|
<#= restrictions #>
|
||||||
{
|
{
|
||||||
<# for (var j = 0; j < i; j++) { #>
|
<# for (var j = 0; j < i; j++) { #>
|
||||||
_present.Add(ComponentTypeID<T<#= j #>>.Value);
|
_present.Add(ComponentTypeID<T<#= j #>>.Value);
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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.
|
/// Targets entities that have all of the specified component types, regardless of whether those component(s) are enabled or disabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public QueryBuilder WithPresentRW<<#= generics #>>()
|
[UnscopedRef]
|
||||||
|
public ref QueryBuilder WithPresentRW<<#= generics #>>()
|
||||||
<#= restrictions #>
|
<#= restrictions #>
|
||||||
{
|
{
|
||||||
<# for (var j = 0; j < i; j++) { #>
|
<# for (var j = 0; j < i; j++) { #>
|
||||||
@@ -135,7 +144,7 @@ public ref partial struct QueryBuilder
|
|||||||
_rw.Add(ComponentTypeID<T<#= j #>>.Value);
|
_rw.Add(ComponentTypeID<T<#= j #>>.Value);
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
return this;
|
return ref this;
|
||||||
}
|
}
|
||||||
|
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|||||||
@@ -268,6 +268,9 @@ public partial class World : IDisposable, IEquatable<World>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_componentManager.Dispose();
|
||||||
|
_systemManager.Dispose();
|
||||||
|
|
||||||
s_freeWorldSlots.Enqueue(_id);
|
s_freeWorldSlots.Enqueue(_id);
|
||||||
s_worlds[_id] = null;
|
s_worlds[_id] = null;
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ namespace Ghost.Graphics.D3D12;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// D3D12 implementation of command queue interface
|
/// D3D12 implementation of command queue interface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal unsafe class D3D12CommandQueue : D3D12Object<ID3D12CommandQueue1>, ICommandQueue
|
internal unsafe class D3D12CommandQueue : D3D12Object<ID3D12CommandQueue>, ICommandQueue
|
||||||
{
|
{
|
||||||
private UniquePtr<ID3D12Fence1> _fence;
|
private UniquePtr<ID3D12Fence> _fence;
|
||||||
|
|
||||||
private readonly AutoResetEvent _fenceEvent;
|
private readonly AutoResetEvent _fenceEvent;
|
||||||
private ulong _fenceValue;
|
private ulong _fenceValue;
|
||||||
@@ -22,7 +22,7 @@ internal unsafe class D3D12CommandQueue : D3D12Object<ID3D12CommandQueue1>, ICom
|
|||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ID3D12CommandQueue1* CreateCommandQueue(ID3D12Device14* device, CommandQueueType type)
|
private static ID3D12CommandQueue* CreateCommandQueue(ID3D12Device14* device, CommandQueueType type)
|
||||||
{
|
{
|
||||||
var queueDesc = new D3D12_COMMAND_QUEUE_DESC
|
var queueDesc = new D3D12_COMMAND_QUEUE_DESC
|
||||||
{
|
{
|
||||||
@@ -31,7 +31,7 @@ internal unsafe class D3D12CommandQueue : D3D12Object<ID3D12CommandQueue1>, ICom
|
|||||||
Flags = D3D12_COMMAND_QUEUE_FLAGS.D3D12_COMMAND_QUEUE_FLAG_NONE,
|
Flags = D3D12_COMMAND_QUEUE_FLAGS.D3D12_COMMAND_QUEUE_FLAG_NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
ID3D12CommandQueue1* pQueue = default;
|
ID3D12CommandQueue* pQueue = default;
|
||||||
ThrowIfFailed(device->CreateCommandQueue(&queueDesc, __uuidof(pQueue), (void**)&pQueue));
|
ThrowIfFailed(device->CreateCommandQueue(&queueDesc, __uuidof(pQueue), (void**)&pQueue));
|
||||||
return pQueue;
|
return pQueue;
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ internal unsafe class D3D12CommandQueue : D3D12Object<ID3D12CommandQueue1>, ICom
|
|||||||
_fenceEvent = new AutoResetEvent(false);
|
_fenceEvent = new AutoResetEvent(false);
|
||||||
_fenceValue = 0;
|
_fenceValue = 0;
|
||||||
|
|
||||||
ID3D12Fence1* pFence = default;
|
ID3D12Fence* pFence = default;
|
||||||
ThrowIfFailed(device.NativeObject.Get()->CreateFence(0, D3D12_FENCE_FLAGS.D3D12_FENCE_FLAG_NONE, __uuidof(pFence), (void**)&pFence));
|
ThrowIfFailed(device.NativeObject.Get()->CreateFence(0, D3D12_FENCE_FLAGS.D3D12_FENCE_FLAG_NONE, __uuidof(pFence), (void**)&pFence));
|
||||||
|
|
||||||
_fence.Attach(pFence);
|
_fence.Attach(pFence);
|
||||||
|
|||||||
@@ -160,6 +160,16 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (_commandBufferReturnQueue.TryDequeue(out var entry))
|
||||||
|
{
|
||||||
|
entry.commandBuffer.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (_commandBufferPool.TryDequeue(out var cmd))
|
||||||
|
{
|
||||||
|
cmd.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
_resourceDatabase.ReleaseAllResourcesImmediately();
|
_resourceDatabase.ReleaseAllResourcesImmediately();
|
||||||
|
|
||||||
_resourceAllocator.Dispose();
|
_resourceAllocator.Dispose();
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ internal unsafe class D3D12RenderDevice : D3D12Object<ID3D12Device14>, IRenderDe
|
|||||||
|
|
||||||
public SharedPtr<IDXGIFactory7> DXGIFactory => _dxgiFactory.Share();
|
public SharedPtr<IDXGIFactory7> DXGIFactory => _dxgiFactory.Share();
|
||||||
public SharedPtr<IDXGIAdapter1> Adapter => _adapter.Share();
|
public SharedPtr<IDXGIAdapter1> Adapter => _adapter.Share();
|
||||||
public SharedPtr<ID3D12CommandQueue1> NativeGraphicsQueue => _graphicsQueue.NativeObject;
|
public SharedPtr<ID3D12CommandQueue> NativeGraphicsQueue => _graphicsQueue.NativeObject;
|
||||||
public SharedPtr<ID3D12CommandQueue1> NativeComputeQueue => _computeQueue.NativeObject;
|
public SharedPtr<ID3D12CommandQueue> NativeComputeQueue => _computeQueue.NativeObject;
|
||||||
public SharedPtr<ID3D12CommandQueue1> NativeCopyQueue => _copyQueue.NativeObject;
|
public SharedPtr<ID3D12CommandQueue> NativeCopyQueue => _copyQueue.NativeObject;
|
||||||
|
|
||||||
public D3D12RenderDevice()
|
public D3D12RenderDevice()
|
||||||
:base(CreateDevice(out var dxgiFactory, out var adapter))
|
:base(CreateDevice(out var dxgiFactory, out var adapter))
|
||||||
|
|||||||
@@ -53,8 +53,9 @@ internal static unsafe class D3D12Utility
|
|||||||
var ptr = uPtr.Get();
|
var ptr = uPtr.Get();
|
||||||
if (ptr != null)
|
if (ptr != null)
|
||||||
{
|
{
|
||||||
|
Debug.Assert(ptr != other);
|
||||||
var refCount = ptr->Release();
|
var refCount = ptr->Release();
|
||||||
Debug.Assert((refCount != 0) || (ptr != other));
|
Debug.Assert(refCount == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uPtr = new UniquePtr<T>(other);
|
uPtr = new UniquePtr<T>(other);
|
||||||
@@ -68,7 +69,7 @@ internal static unsafe class D3D12Utility
|
|||||||
if (ptr != null)
|
if (ptr != null)
|
||||||
{
|
{
|
||||||
var refCount = ptr->Release();
|
var refCount = ptr->Release();
|
||||||
Debug.Assert(refCount != 0);
|
//Debug.Assert(refCount == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -433,7 +434,7 @@ internal static unsafe class D3D12Utility
|
|||||||
{
|
{
|
||||||
var flags = D3D12_RESOURCE_FLAG_NONE;
|
var flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
if (usage.HasFlag(BufferUsage.Raw) || usage.HasFlag(BufferUsage.UnorderedAccess))
|
if (usage.HasFlag(BufferUsage.UnorderedAccess))
|
||||||
{
|
{
|
||||||
flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ public struct Mesh : IResourceReleasable
|
|||||||
this.ComputeBounds();
|
this.ComputeBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly void ReleaseCpuResources()
|
public void ReleaseCpuResources()
|
||||||
{
|
{
|
||||||
_vertices.Dispose();
|
_vertices.Dispose();
|
||||||
_indices.Dispose();
|
_indices.Dispose();
|
||||||
@@ -238,7 +238,7 @@ public struct Mesh : IResourceReleasable
|
|||||||
MeshletUtility.Build(config, clodMesh, Unsafe.AsPointer(ref this), MeshletOutputCallback);
|
MeshletUtility.Build(config, clodMesh, Unsafe.AsPointer(ref this), MeshletOutputCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static unsafe int MeshletOutputCallback(void* context, ClodGroup group, ReadOnlyUnsafeCollection<ClodCluster>clusters)
|
private static unsafe int MeshletOutputCallback(void* context, ClodGroup group, ReadOnlyUnsafeCollection<ClodCluster> clusters)
|
||||||
{
|
{
|
||||||
var mesh = (Mesh*)context;
|
var mesh = (Mesh*)context;
|
||||||
ref var data = ref mesh->_meshletData;
|
ref var data = ref mesh->_meshletData;
|
||||||
@@ -277,13 +277,13 @@ public struct Mesh : IResourceReleasable
|
|||||||
data.meshletVertices.Add(cluster.uniqueVertices[j]);
|
data.meshletVertices.Add(cluster.uniqueVertices[j]);
|
||||||
}
|
}
|
||||||
// Add local triangles (packed into uints)
|
// Add local triangles (packed into uints)
|
||||||
nuint triangleCount = cluster.localIndexCount / 3;
|
var triangleCount = cluster.localIndexCount / 3;
|
||||||
for (nuint j = 0; j < triangleCount; j++)
|
for (nuint j = 0; j < triangleCount; j++)
|
||||||
{
|
{
|
||||||
uint i0 = cluster.localIndices[j * 3 + 0];
|
uint i0 = cluster.localIndices[j * 3 + 0];
|
||||||
uint i1 = cluster.localIndices[j * 3 + 1];
|
uint i1 = cluster.localIndices[j * 3 + 1];
|
||||||
uint i2 = cluster.localIndices[j * 3 + 2];
|
uint i2 = cluster.localIndices[j * 3 + 2];
|
||||||
uint packedTriangle = i0 | (i1 << 8) | (i2 << 16);
|
var packedTriangle = i0 | (i1 << 8) | (i2 << 16);
|
||||||
data.meshletTriangles.Add(packedTriangle);
|
data.meshletTriangles.Add(packedTriangle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,7 +291,7 @@ public struct Mesh : IResourceReleasable
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly void ReleaseResource(IResourceDatabase database)
|
public void ReleaseResource(IResourceDatabase database)
|
||||||
{
|
{
|
||||||
ReleaseCpuResources();
|
ReleaseCpuResources();
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public struct RenderList : IDisposable
|
|||||||
{
|
{
|
||||||
while (_listIndex < _length)
|
while (_listIndex < _length)
|
||||||
{
|
{
|
||||||
if (_itemIndex < _pList[_listIndex].Count)
|
if (_itemIndex < _pList[_listIndex].Count - 1)
|
||||||
{
|
{
|
||||||
_itemIndex++;
|
_itemIndex++;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public readonly unsafe ref struct RenderingContext
|
|||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref readonly var meshData = ref r.Value;
|
ref var meshData = ref r.Value;
|
||||||
var vertexHandle = meshData.VertexBuffer.AsResource();
|
var vertexHandle = meshData.VertexBuffer.AsResource();
|
||||||
var indexHandle = meshData.IndexBuffer.AsResource();
|
var indexHandle = meshData.IndexBuffer.AsResource();
|
||||||
|
|
||||||
@@ -105,9 +105,12 @@ public readonly unsafe ref struct RenderingContext
|
|||||||
|
|
||||||
if (staticMesh)
|
if (staticMesh)
|
||||||
{
|
{
|
||||||
|
meshData.CookMeshlets();
|
||||||
meshData.ReleaseCpuResources();
|
meshData.ReleaseCpuResources();
|
||||||
TransitionBarrier(vertexHandle, false, BarrierLayout.Undefined, BarrierAccess.ShaderResource, BarrierSync.VertexShading);
|
TransitionBarrier(vertexHandle, false, BarrierLayout.Undefined, BarrierAccess.ShaderResource, BarrierSync.VertexShading);
|
||||||
TransitionBarrier(indexHandle, false, BarrierLayout.Undefined, BarrierAccess.IndexBuffer, BarrierSync.IndexInput);
|
TransitionBarrier(indexHandle, false, BarrierLayout.Undefined, BarrierAccess.IndexBuffer, BarrierSync.IndexInput);
|
||||||
|
|
||||||
|
UploadMeshlets(mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
@@ -205,17 +208,7 @@ public readonly unsafe ref struct RenderingContext
|
|||||||
|
|
||||||
_directCmd.UploadBuffer(meshRef.MeshLetBuffer, meshletData.meshlets.AsSpan());
|
_directCmd.UploadBuffer(meshRef.MeshLetBuffer, meshletData.meshlets.AsSpan());
|
||||||
_directCmd.UploadBuffer(meshRef.MeshletVerticesBuffer, meshletData.meshletVertices.AsSpan());
|
_directCmd.UploadBuffer(meshRef.MeshletVerticesBuffer, meshletData.meshletVertices.AsSpan());
|
||||||
// Padding for triangle data if needed
|
|
||||||
if (trianglesSize > meshletData.meshletTriangles.Count)
|
|
||||||
{
|
|
||||||
var paddedData = new uint[trianglesSize];
|
|
||||||
meshletData.meshletTriangles.AsSpan().CopyTo(paddedData);
|
|
||||||
_directCmd.UploadBuffer(meshRef.MeshletTrianglesBuffer, paddedData.AsSpan());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_directCmd.UploadBuffer(meshRef.MeshletTrianglesBuffer, meshletData.meshletTriangles.AsSpan());
|
_directCmd.UploadBuffer(meshRef.MeshletTrianglesBuffer, meshletData.meshletTriangles.AsSpan());
|
||||||
}
|
|
||||||
|
|
||||||
TransitionBarrier(meshRef.MeshLetBuffer.AsResource(), false, BarrierLayout.Undefined, BarrierAccess.ShaderResource, BarrierSync.NonPixelShading | BarrierSync.PixelShading);
|
TransitionBarrier(meshRef.MeshLetBuffer.AsResource(), false, BarrierLayout.Undefined, BarrierAccess.ShaderResource, BarrierSync.NonPixelShading | BarrierSync.PixelShading);
|
||||||
TransitionBarrier(meshRef.MeshletVerticesBuffer.AsResource(), false, BarrierLayout.Undefined, BarrierAccess.ShaderResource, BarrierSync.NonPixelShading | BarrierSync.PixelShading);
|
TransitionBarrier(meshRef.MeshletVerticesBuffer.AsResource(), false, BarrierLayout.Undefined, BarrierAccess.ShaderResource, BarrierSync.NonPixelShading | BarrierSync.PixelShading);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Misaki.HighPerformance.Analyzer" Version="1.0.0">
|
<PackageReference Include="Misaki.HighPerformance.Analyzer" Version="1.1.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Ghost.Core;
|
#if false
|
||||||
|
// Obsolete
|
||||||
using Ghost.Core.Graphics;
|
using Ghost.Core.Graphics;
|
||||||
using Ghost.DSL.ShaderCompiler;
|
using Ghost.DSL.ShaderCompiler;
|
||||||
using Ghost.Graphics.Core;
|
using Ghost.Graphics.Core;
|
||||||
@@ -335,3 +336,4 @@ internal class MeshRenderPass : IRenderPass
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ public interface IRasterRenderContext : IRenderGraphContext
|
|||||||
{
|
{
|
||||||
int ActiveMeshIndexCount { get; }
|
int ActiveMeshIndexCount { get; }
|
||||||
|
|
||||||
|
void SetGlobalData(uint globalIndex, uint viewIndex);
|
||||||
|
void SetInstanceIndex(uint instanceIndex);
|
||||||
|
|
||||||
void SetActiveMaterial(Handle<Material> material);
|
void SetActiveMaterial(Handle<Material> material);
|
||||||
void SetActiveMaterial(ref readonly Material material);
|
void SetActiveMaterial(ref readonly Material material);
|
||||||
void SetActiveMesh(Handle<Mesh> mesh);
|
void SetActiveMesh(Handle<Mesh> mesh);
|
||||||
@@ -58,6 +61,10 @@ internal sealed class RenderGraphContext : IRasterRenderContext, IComputeRenderC
|
|||||||
private Handle<GraphicsBuffer> _activePerMeshData;
|
private Handle<GraphicsBuffer> _activePerMeshData;
|
||||||
private int _activeMeshIndexCount;
|
private int _activeMeshIndexCount;
|
||||||
|
|
||||||
|
private uint _activeGlobalIndex;
|
||||||
|
private uint _activeViewIndex;
|
||||||
|
private uint _activeInstanceIndex;
|
||||||
|
|
||||||
public ResourceManager ResourceManager => _resourceManager;
|
public ResourceManager ResourceManager => _resourceManager;
|
||||||
public IResourceDatabase ResourceDatabase => _resourceDatabase;
|
public IResourceDatabase ResourceDatabase => _resourceDatabase;
|
||||||
|
|
||||||
@@ -221,12 +228,26 @@ internal sealed class RenderGraphContext : IRasterRenderContext, IComputeRenderC
|
|||||||
_activeMeshIndexCount = mesh.IndexCount;
|
_activeMeshIndexCount = mesh.IndexCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetGlobalData(uint globalIndex, uint viewIndex)
|
||||||
|
{
|
||||||
|
_activeGlobalIndex = globalIndex;
|
||||||
|
_activeViewIndex = viewIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetInstanceIndex(uint instanceIndex)
|
||||||
|
{
|
||||||
|
_activeInstanceIndex = instanceIndex;
|
||||||
|
}
|
||||||
|
|
||||||
public unsafe void DispatchMesh(uint3 threadGroupCount)
|
public unsafe void DispatchMesh(uint3 threadGroupCount)
|
||||||
{
|
{
|
||||||
// TODO: Global and view constants
|
// TODO: Global, view, and instance constants
|
||||||
var data = new PushConstantsData
|
var data = new PushConstantsData
|
||||||
{
|
{
|
||||||
|
globalIndex = _activeGlobalIndex,
|
||||||
|
viewIndex = _activeViewIndex,
|
||||||
objectIndex = _resourceDatabase.GetBindlessIndex(_activePerMeshData.AsResource()),
|
objectIndex = _resourceDatabase.GetBindlessIndex(_activePerMeshData.AsResource()),
|
||||||
|
instanceIndex = _activeInstanceIndex,
|
||||||
materialIndex = _resourceDatabase.GetBindlessIndex(_activePerMaterialData.AsResource()),
|
materialIndex = _resourceDatabase.GetBindlessIndex(_activePerMaterialData.AsResource()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,18 +8,6 @@ struct PixelInput
|
|||||||
float4 uv : TEXCOORD0;
|
float4 uv : TEXCOORD0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Meshlet
|
|
||||||
{
|
|
||||||
float4 boundingSphere;
|
|
||||||
float3 boundingBoxMin;
|
|
||||||
float3 boundingBoxMax;
|
|
||||||
uint vertexOffset;
|
|
||||||
uint triangleOffset;
|
|
||||||
uint groupIndex;
|
|
||||||
float parentError;
|
|
||||||
uint packedCounts; // byte vertexCount, byte triangleCount, byte localMaterialIndex, byte lodLevel
|
|
||||||
};
|
|
||||||
|
|
||||||
[numthreads(128, 1, 1)] // 128 threads to cover max 64 vertices and 124 triangles
|
[numthreads(128, 1, 1)] // 128 threads to cover max 64 vertices and 124 triangles
|
||||||
[outputtopology("triangle")]
|
[outputtopology("triangle")]
|
||||||
void MSMain(
|
void MSMain(
|
||||||
@@ -50,7 +38,9 @@ void MSMain(
|
|||||||
|
|
||||||
// Basic MVP transform not needed if already in world space, but usually we need localToWorld and ViewProj
|
// Basic MVP transform not needed if already in world space, but usually we need localToWorld and ViewProj
|
||||||
PerViewData perViewData = LoadData<PerViewData>(g_PushConstantData.perViewBuffer, 0);
|
PerViewData perViewData = LoadData<PerViewData>(g_PushConstantData.perViewBuffer, 0);
|
||||||
float4 worldPos = mul(perObjectData.localToWorld, float4(v.position.xyz, 1.0f));
|
PerInstanceData perInstanceData = LoadData<PerInstanceData>(g_PushConstantData.perInstanceBuffer, 0);
|
||||||
|
|
||||||
|
float4 worldPos = mul(perInstanceData.localToWorld, float4(v.position.xyz, 1.0f));
|
||||||
outVerts[groupThreadID.x].position = mul(perViewData.viewMatrix, worldPos);
|
outVerts[groupThreadID.x].position = mul(perViewData.viewMatrix, worldPos);
|
||||||
outVerts[groupThreadID.x].position = mul(perViewData.projectionMatrix, outVerts[groupThreadID.x].position);
|
outVerts[groupThreadID.x].position = mul(perViewData.projectionMatrix, outVerts[groupThreadID.x].position);
|
||||||
|
|
||||||
@@ -76,13 +66,13 @@ void MSMain(
|
|||||||
|
|
||||||
float4 PSMain(PixelInput input) : SV_TARGET
|
float4 PSMain(PixelInput input) : SV_TARGET
|
||||||
{
|
{
|
||||||
PerMaterialData perMaterialData = LoadData<PerMaterialData>(g_PushConstantData.perMaterialBuffer, 0);
|
// PerMaterialData perMaterialData = LoadData<PerMaterialData>(g_PushConstantData.perMaterialBuffer, 0);
|
||||||
|
//
|
||||||
float4 color1 = SAMPLE_TEXTURE2D(perMaterialData.texture1, perMaterialData.tex_sampler, input.uv.xy);
|
// float4 color1 = SAMPLE_TEXTURE2D(perMaterialData.texture1, perMaterialData.tex_sampler, input.uv.xy);
|
||||||
float4 color2 = SAMPLE_TEXTURE2D(perMaterialData.texture2, perMaterialData.tex_sampler, input.uv.xy);
|
// float4 color2 = SAMPLE_TEXTURE2D(perMaterialData.texture2, perMaterialData.tex_sampler, input.uv.xy);
|
||||||
float4 color3 = SAMPLE_TEXTURE2D(perMaterialData.texture3, perMaterialData.tex_sampler, input.uv.xy);
|
// float4 color3 = SAMPLE_TEXTURE2D(perMaterialData.texture3, perMaterialData.tex_sampler, input.uv.xy);
|
||||||
float4 color4 = SAMPLE_TEXTURE2D(perMaterialData.texture4, perMaterialData.tex_sampler, input.uv.xy);
|
// float4 color4 = SAMPLE_TEXTURE2D(perMaterialData.texture4, perMaterialData.tex_sampler, input.uv.xy);
|
||||||
|
//
|
||||||
float4 blendedColor = (color1 + color2 + color3 + color4) * 0.25f;
|
// float4 blendedColor = (color1 + color2 + color3 + color4) * 0.25f;
|
||||||
return perMaterialData.color * blendedColor + input.color;
|
// return perMaterialData.color * blendedColor + input.color;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -422,6 +422,7 @@ public class RenderSystem : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_renderPipeline.Dispose();
|
_renderPipeline.Dispose();
|
||||||
|
_resourceManager.Dispose();
|
||||||
_graphicsEngine.Dispose();
|
_graphicsEngine.Dispose();
|
||||||
_shutdownEvent.Dispose();
|
_shutdownEvent.Dispose();
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,18 @@ struct Vertex
|
|||||||
float4 color;
|
float4 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Meshlet
|
||||||
|
{
|
||||||
|
float4 boundingSphere;
|
||||||
|
float3 boundingBoxMin;
|
||||||
|
float3 boundingBoxMax;
|
||||||
|
uint vertexOffset;
|
||||||
|
uint triangleOffset;
|
||||||
|
uint groupIndex;
|
||||||
|
float parentError;
|
||||||
|
uint packedCounts; // byte vertexCount, byte triangleCount, byte localMaterialIndex, byte lodLevel
|
||||||
|
};
|
||||||
|
|
||||||
// Resource descriptor heap definitions
|
// Resource descriptor heap definitions
|
||||||
|
|
||||||
#define GLOBAL_TEXTURE2D_HEAP ResourceDescriptorHeap
|
#define GLOBAL_TEXTURE2D_HEAP ResourceDescriptorHeap
|
||||||
|
|||||||
@@ -5,11 +5,20 @@
|
|||||||
|
|
||||||
struct PushConstantData
|
struct PushConstantData
|
||||||
{
|
{
|
||||||
BYTE_ADDRESS_BUFFER globalBuffer;
|
uint globalIndex;
|
||||||
BYTE_ADDRESS_BUFFER perViewBuffer;
|
uint viewIndex;
|
||||||
BYTE_ADDRESS_BUFFER perObjectBuffer;
|
uint objectIndex;
|
||||||
BYTE_ADDRESS_BUFFER perInstanceBuffer;
|
uint instanceIndex;
|
||||||
BYTE_ADDRESS_BUFFER perMaterialBuffer;
|
uint materialIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GlobalFrameData
|
||||||
|
{
|
||||||
|
uint viewBufferIndex;
|
||||||
|
uint instanceBufferIndex;
|
||||||
|
uint viewBufferCount;
|
||||||
|
uint instanceBufferCount;
|
||||||
|
uint userBufferIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PerViewData
|
struct PerViewData
|
||||||
@@ -23,6 +32,11 @@ struct PerViewData
|
|||||||
float4 screenSize; // xy: size, zw: 1/size
|
float4 screenSize; // xy: size, zw: 1/size
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PerInstanceData
|
||||||
|
{
|
||||||
|
float4x4 localToWorld;
|
||||||
|
};
|
||||||
|
|
||||||
struct PerObjectData
|
struct PerObjectData
|
||||||
{
|
{
|
||||||
float3 worldBoundsMin;
|
float3 worldBoundsMin;
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ shader "MyShader/Standard"
|
|||||||
{
|
{
|
||||||
properties
|
properties
|
||||||
{
|
{
|
||||||
float4 color = { 1, 1, 1, 1 };
|
//float4 color = { 1, 1, 1, 1 };
|
||||||
tex2d texture1 = { black };
|
//tex2d texture1 = { black };
|
||||||
tex2d texture2 = { white };
|
//tex2d texture2 = { white };
|
||||||
tex2d texture3 = { grey };
|
//tex2d texture3 = { grey };
|
||||||
tex2d texture4 = { normal };
|
//tex2d texture4 = { normal };
|
||||||
sampler tex_sampler;
|
//sampler tex_sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
pass "Forward"
|
pass "Forward"
|
||||||
@@ -21,7 +21,96 @@ shader "MyShader/Standard"
|
|||||||
color_mask = all;
|
color_mask = all;
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh "F:/csharp/GhostEngine/src/Runtime//Ghost.Graphics/RenderPipeline/ShaderCode.hlsl" : "MSMain";
|
includes
|
||||||
pixel "F:/csharp/GhostEngine/src/Runtime//Ghost.Graphics/RenderPipeline/ShaderCode.hlsl" : "PSMain";
|
{
|
||||||
|
"F:/csharp/GhostEngine/src/Runtime/Ghost.Graphics/Shaders/Includes/Properties.hlsl";
|
||||||
|
}
|
||||||
|
|
||||||
|
hlsl
|
||||||
|
{
|
||||||
|
struct PixelInput
|
||||||
|
{
|
||||||
|
float4 position : SV_POSITION;
|
||||||
|
float4 color : COLOR;
|
||||||
|
float4 uv : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
[numthreads(128, 1, 1)] // 128 threads to cover max 64 vertices and 124 triangles
|
||||||
|
[outputtopology("triangle")]
|
||||||
|
void MSMain(
|
||||||
|
uint3 groupThreadID : SV_GroupThreadID,
|
||||||
|
uint3 groupID : SV_GroupID,
|
||||||
|
out vertices PixelInput outVerts[64],
|
||||||
|
out indices uint3 outTris[124])
|
||||||
|
{
|
||||||
|
PerObjectData perObjectData = LoadData<PerObjectData>(g_PushConstantData.objectIndex, 0);
|
||||||
|
|
||||||
|
ByteAddressBuffer meshletBuffer = GET_BUFFER(perObjectData.meshletBuffer);
|
||||||
|
Meshlet m = meshletBuffer.Load<Meshlet>(groupID.x * sizeof(Meshlet));
|
||||||
|
|
||||||
|
uint vertexCount = m.packedCounts & 0xFF;
|
||||||
|
uint triangleCount = (m.packedCounts >> 8) & 0xFF;
|
||||||
|
|
||||||
|
SetMeshOutputCounts(vertexCount, triangleCount);
|
||||||
|
|
||||||
|
ByteAddressBuffer meshletVerticesBuffer = GET_BUFFER(perObjectData.meshletVerticesBuffer);
|
||||||
|
ByteAddressBuffer meshletTrianglesBuffer = GET_BUFFER(perObjectData.meshletTrianglesBuffer);
|
||||||
|
|
||||||
|
// Write vertex output
|
||||||
|
if (groupThreadID.x < vertexCount)
|
||||||
|
{
|
||||||
|
uint vertexIndex = meshletVerticesBuffer.Load((m.vertexOffset + groupThreadID.x) * 4);
|
||||||
|
ByteAddressBuffer vertices = GET_BUFFER(perObjectData.vertexBuffer);
|
||||||
|
Vertex v = vertices.Load<Vertex>(vertexIndex * sizeof(Vertex));
|
||||||
|
|
||||||
|
GlobalFrameData globalFrameData = LoadData<GlobalFrameData>(g_PushConstantData.globalIndex, 0);
|
||||||
|
PerViewData perViewData = LoadData<PerViewData>(g_PushConstantData.viewIndex, 0);
|
||||||
|
PerInstanceData perInstanceData = LoadData<PerInstanceData>(globalFrameData.instanceBufferIndex, g_PushConstantData.instanceIndex);
|
||||||
|
|
||||||
|
float4 worldPos = mul(perInstanceData.localToWorld, float4(v.position.xyz, 1.0f));
|
||||||
|
float4 viewPos = mul(perViewData.viewMatrix, worldPos);
|
||||||
|
|
||||||
|
outVerts[groupThreadID.x].position = mul(perViewData.projectionMatrix, viewPos);
|
||||||
|
|
||||||
|
outVerts[groupThreadID.x].color = v.color;
|
||||||
|
outVerts[groupThreadID.x].uv = v.uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write triangle output (1 thread processes 1 triangle)
|
||||||
|
if (groupThreadID.x < triangleCount)
|
||||||
|
{
|
||||||
|
uint triangleIndex = groupThreadID.x;
|
||||||
|
|
||||||
|
// Load the packed 32-bit integer containing the 3 local indices
|
||||||
|
uint packedIndices = meshletTrianglesBuffer.Load((m.triangleOffset + triangleIndex) * 4);
|
||||||
|
|
||||||
|
uint i0 = packedIndices & 0xFF;
|
||||||
|
uint i1 = (packedIndices >> 8) & 0xFF;
|
||||||
|
uint i2 = (packedIndices >> 16) & 0xFF;
|
||||||
|
|
||||||
|
outTris[triangleIndex] = uint3(i0, i1, i2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 PSMain(PixelInput input) : SV_TARGET
|
||||||
|
{
|
||||||
|
// PerMaterialData perMaterialData = LoadData<PerMaterialData>(g_PushConstantData.materialIndex, 0);
|
||||||
|
//
|
||||||
|
// float4 color1 = SAMPLE_TEXTURE2D(perMaterialData.texture1, perMaterialData.tex_sampler, input.uv.xy);
|
||||||
|
// float4 color2 = SAMPLE_TEXTURE2D(perMaterialData.texture2, perMaterialData.tex_sampler, input.uv.xy);
|
||||||
|
// float4 color3 = SAMPLE_TEXTURE2D(perMaterialData.texture3, perMaterialData.tex_sampler, input.uv.xy);
|
||||||
|
// float4 color4 = SAMPLE_TEXTURE2D(perMaterialData.texture4, perMaterialData.tex_sampler, input.uv.xy);
|
||||||
|
//
|
||||||
|
// float4 blendedColor = (color1 + color2 + color3 + color4) * 0.25f;
|
||||||
|
// return perMaterialData.color * blendedColor + input.color;
|
||||||
|
|
||||||
|
// TODO: Randome color on meshlet.
|
||||||
|
return float4(1, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh "hlsl_block" : "MSMain";
|
||||||
|
pixel "hlsl_block" : "PSMain";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
<ProjectReference Include="..\..\Runtime\Ghost.Engine\Ghost.Engine.csproj" />
|
<ProjectReference Include="..\..\Runtime\Ghost.Engine\Ghost.Engine.csproj" />
|
||||||
<ProjectReference Include="..\..\Test\Ghost.Test.Core\Ghost.Test.Core.csproj" />
|
<ProjectReference Include="..\..\Test\Ghost.Test.Core\Ghost.Test.Core.csproj" />
|
||||||
<ProjectReference Include="..\..\Runtime\Ghost.Graphics\Ghost.Graphics.csproj" />
|
<ProjectReference Include="..\..\Runtime\Ghost.Graphics\Ghost.Graphics.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Editor\Ghost.DSL\Ghost.DSL.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
|
using Ghost.Core.Graphics;
|
||||||
|
using Ghost.DSL.ShaderCompiler;
|
||||||
using Ghost.Graphics.Core;
|
using Ghost.Graphics.Core;
|
||||||
using Ghost.Graphics.RenderGraphModule;
|
using Ghost.Graphics.RenderGraphModule;
|
||||||
using Ghost.Graphics.RenderPipeline;
|
using Ghost.Graphics.RenderPipeline;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.Mathematics;
|
using Misaki.HighPerformance.Mathematics;
|
||||||
|
using Misaki.HighPerformance.Utilities;
|
||||||
|
|
||||||
namespace Ghost.Graphics.Test.RenderPasses;
|
namespace Ghost.Graphics.Test.RenderPasses;
|
||||||
|
|
||||||
@@ -21,10 +24,15 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
|||||||
{
|
{
|
||||||
public Identifier<RGTexture> backbuffer;
|
public Identifier<RGTexture> backbuffer;
|
||||||
public RenderList renderList;
|
public RenderList renderList;
|
||||||
|
public Handle<Material> material;
|
||||||
|
public uint globalIndex;
|
||||||
|
public uint viewIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly RenderGraph _renderGraph;
|
private readonly RenderGraph _renderGraph;
|
||||||
private readonly RenderSystem _renderSystem;
|
private readonly RenderSystem _renderSystem;
|
||||||
|
private Identifier<Shader> _meshletShader;
|
||||||
|
private Handle<Material> _meshletMaterial;
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
@@ -41,6 +49,25 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
|||||||
renderSystem.GraphicsEngine.ResourceDatabase,
|
renderSystem.GraphicsEngine.ResourceDatabase,
|
||||||
renderSystem.GraphicsEngine.PipelineLibrary,
|
renderSystem.GraphicsEngine.PipelineLibrary,
|
||||||
renderSystem.GraphicsEngine.ShaderCompiler);
|
renderSystem.GraphicsEngine.ShaderCompiler);
|
||||||
|
|
||||||
|
var shaderDescriptor = DSLShaderCompiler.CompileShader("F:/csharp/GhostEngine/src/Runtime/Ghost.Graphics/test.gshdr", "C:/Users/Misaki/Downloads/Archive").GetValueOrThrow();
|
||||||
|
_meshletShader = renderSystem.ResourceManager.CreateGraphicsShader(shaderDescriptor);
|
||||||
|
_meshletMaterial = renderSystem.ResourceManager.CreateMaterial(_meshletShader);
|
||||||
|
|
||||||
|
var config = new ShaderCompilationConfig
|
||||||
|
{
|
||||||
|
optimizeLevel = CompilerOptimizeLevel.O3,
|
||||||
|
options = CompilerOption.KeepReflections,
|
||||||
|
tier = CompilerTier.Tier2
|
||||||
|
};
|
||||||
|
|
||||||
|
var pass = shaderDescriptor.passes[0];
|
||||||
|
var emptyKeywords = new LocalKeywordSet();
|
||||||
|
var variantKey = RHIUtility.CreateShaderVariantKey(
|
||||||
|
RHIUtility.CreateShaderPassKey(pass.identifier),
|
||||||
|
in emptyKeywords);
|
||||||
|
|
||||||
|
renderSystem.GraphicsEngine.ShaderCompiler.CompilePass(in pass, in config, variantKey).GetValueOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Render(RenderContext ctx, ReadOnlySpan<RenderRequest> requests)
|
public void Render(RenderContext ctx, ReadOnlySpan<RenderRequest> requests)
|
||||||
@@ -137,7 +164,9 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var backBuffer = _renderGraph.ImportTexture(request.colorTarget, "BackBuffer", clearAtFirstUse: false, discardAtLastUse: false);
|
var backBuffer = _renderGraph.ImportTexture(request.colorTarget, "BackBuffer", clearAtFirstUse: true, discardAtLastUse: false);
|
||||||
|
|
||||||
|
MeshletDebugPass(backBuffer, request.opaqueRenderList, resourceDatabase.GetBindlessIndex(frameBufferResource.AsResource()), resourceDatabase.GetBindlessIndex(viewBufferResource.AsResource()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must enqueue a return for the pooled resources so they are freed next frame.
|
// We must enqueue a return for the pooled resources so they are freed next frame.
|
||||||
@@ -147,16 +176,35 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MeshletDebugPass(Identifier<RGTexture> backbuffer, RenderList renderList)
|
private void MeshletDebugPass(Identifier<RGTexture> backbuffer, RenderList renderList, uint globalIndex, uint viewIndex)
|
||||||
{
|
{
|
||||||
using (var builder = _renderGraph.AddRasterRenderPass<MeshletDebugPassData>("Meshlet Debug Pass", out var passData))
|
using (var builder = _renderGraph.AddRasterRenderPass<MeshletDebugPassData>("Meshlet Debug Pass", out var passData))
|
||||||
{
|
{
|
||||||
passData.renderList = renderList;
|
passData.renderList = renderList;
|
||||||
|
passData.globalIndex = globalIndex;
|
||||||
|
passData.viewIndex = viewIndex;
|
||||||
|
passData.material = _meshletMaterial;
|
||||||
|
|
||||||
builder.SetColorAttachment(backbuffer, 0);
|
builder.SetColorAttachment(backbuffer, 0);
|
||||||
builder.SetRenderFunc<MeshletDebugPassData>(static (data, ctx)=>
|
builder.SetRenderFunc<MeshletDebugPassData>(static (data, ctx)=>
|
||||||
{
|
{
|
||||||
|
ctx.SetGlobalData(data.globalIndex, data.viewIndex);
|
||||||
|
ctx.SetActiveMaterial(data.material);
|
||||||
|
|
||||||
|
var instanceIndex = 0u;
|
||||||
|
foreach (var record in data.renderList)
|
||||||
|
{
|
||||||
|
ctx.SetActiveMesh(record.mesh);
|
||||||
|
ctx.SetInstanceIndex(instanceIndex);
|
||||||
|
|
||||||
|
var meshRefResult = ctx.ResourceManager.GetMeshReference(record.mesh);
|
||||||
|
if (meshRefResult.IsSuccess)
|
||||||
|
{
|
||||||
|
var meshletCount = (uint)meshRefResult.Value.MeshletData.meshlets.Count;
|
||||||
|
ctx.DispatchMesh(new uint3(meshletCount, 1, 1));
|
||||||
|
}
|
||||||
|
instanceIndex++;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,6 +216,9 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_renderSystem.ResourceManager.ReleaseMaterial(_meshletMaterial);
|
||||||
|
_renderSystem.ResourceManager.ReleaseShader(_meshletShader);
|
||||||
|
|
||||||
_renderGraph.Dispose();
|
_renderGraph.Dispose();
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Ghost.Core;
|
|||||||
using Ghost.Graphics.Test.Windows;
|
using Ghost.Graphics.Test.Windows;
|
||||||
|
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
// To learn more about WinUI, the WinUI project structure,
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
@@ -32,22 +33,22 @@ public partial class UnitTestApp : Application
|
|||||||
OperatingSystem.IsMacOS() ? "osx" : "unknown";
|
OperatingSystem.IsMacOS() ? "osx" : "unknown";
|
||||||
var arch = Environment.Is64BitProcess ? "x64" : "x86";
|
var arch = Environment.Is64BitProcess ? "x64" : "x86";
|
||||||
var nativeDllDir = Path.Combine(currentDir, "runtimes", platform + "-" + arch, "native");
|
var nativeDllDir = Path.Combine(currentDir, "runtimes", platform + "-" + arch, "native");
|
||||||
//if (Directory.Exists(nativeDllDir))
|
if (Directory.Exists(nativeDllDir))
|
||||||
//{
|
|
||||||
// foreach (var dll in Directory.EnumerateFiles(nativeDllDir, "*.dll"))
|
|
||||||
// {
|
|
||||||
// NativeLibrary.Load(dll);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
NativeLibrary.SetDllImportResolver(typeof(UnitTestApp).Assembly, (libraryName, assembly, searchPath) =>
|
|
||||||
{
|
{
|
||||||
if (libraryName == "dxcompiler")
|
foreach (var dll in Directory.EnumerateFiles(nativeDllDir, "*.dll"))
|
||||||
{
|
{
|
||||||
NativeLibrary.Load(Path.Combine(nativeDllDir, "dxil.dll"));
|
NativeLibrary.Load(dll);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
//NativeLibrary.SetDllImportResolver(typeof(UnitTestApp).Assembly, (libraryName, assembly, searchPath) =>
|
||||||
|
//{
|
||||||
|
// if (libraryName == "dxcompiler")
|
||||||
|
// {
|
||||||
|
// NativeLibrary.Load(Path.Combine(nativeDllDir, "dxil.dll"));
|
||||||
|
// }
|
||||||
|
|
||||||
return IntPtr.Zero;
|
// return IntPtr.Zero;
|
||||||
});
|
//});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -58,6 +59,15 @@ public partial class UnitTestApp : Application
|
|||||||
{
|
{
|
||||||
LoadDll();
|
LoadDll();
|
||||||
|
|
||||||
|
var opts = new AllocationManagerInitOpts
|
||||||
|
{
|
||||||
|
ArenaCapacity = 1024 * 1024 * 1024, // 1GB
|
||||||
|
StackCapacity = 1024 * 1024 * 32, // 32MB
|
||||||
|
FreeListConcurrencyLevel = Environment.ProcessorCount,
|
||||||
|
};
|
||||||
|
|
||||||
|
AllocationManager.Initialize(opts);
|
||||||
|
|
||||||
_window = new GraphicsTestWindow();
|
_window = new GraphicsTestWindow();
|
||||||
_window.Activate();
|
_window.Activate();
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ public sealed partial class GraphicsTestWindow : Window
|
|||||||
private ISwapChain? _swapChain;
|
private ISwapChain? _swapChain;
|
||||||
private World? _world;
|
private World? _world;
|
||||||
|
|
||||||
|
private Handle<Mesh> _meshHandle;
|
||||||
|
|
||||||
private bool _isFirstActivationHandled;
|
private bool _isFirstActivationHandled;
|
||||||
|
|
||||||
public GraphicsTestWindow()
|
public GraphicsTestWindow()
|
||||||
@@ -64,7 +66,9 @@ public sealed partial class GraphicsTestWindow : Window
|
|||||||
_world.AddService(_renderSystem);
|
_world.AddService(_renderSystem);
|
||||||
|
|
||||||
// Add Systems
|
// Add Systems
|
||||||
_world.SystemManager.GetSystem<DefaultSystemGroup>().AddSystem<RenderExtractionSystem>();
|
var group = _world.SystemManager.GetSystem<DefaultSystemGroup>();
|
||||||
|
group.AddSystem<RenderExtractionSystem>();
|
||||||
|
group.SortSystems();
|
||||||
|
|
||||||
_world.SystemManager.InitializeAll(default);
|
_world.SystemManager.InitializeAll(default);
|
||||||
|
|
||||||
@@ -101,16 +105,8 @@ public sealed partial class GraphicsTestWindow : Window
|
|||||||
using var cmdAllocator = _renderSystem.GraphicsEngine.CreateCommandAllocator(CommandBufferType.Graphics);
|
using var cmdAllocator = _renderSystem.GraphicsEngine.CreateCommandAllocator(CommandBufferType.Graphics);
|
||||||
directCmd.Begin(cmdAllocator);
|
directCmd.Begin(cmdAllocator);
|
||||||
|
|
||||||
var meshHandle = ctx.CreateMesh(vertices, indices, true);
|
_meshHandle = ctx.CreateMesh(vertices, indices, true);
|
||||||
|
ctx.UpdateObjectData(_meshHandle);
|
||||||
var meshRefResult = _renderSystem.ResourceManager.GetMeshReference(meshHandle);
|
|
||||||
if (meshRefResult.IsSuccess)
|
|
||||||
{
|
|
||||||
meshRefResult.Value.CookMeshlets();
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.UploadMeshlets(meshHandle);
|
|
||||||
ctx.UpdateObjectData(meshHandle);
|
|
||||||
|
|
||||||
directCmd.End().ThrowIfFailed();
|
directCmd.End().ThrowIfFailed();
|
||||||
_renderSystem.GraphicsEngine.Device.GraphicsQueue.Submit(directCmd);
|
_renderSystem.GraphicsEngine.Device.GraphicsQueue.Submit(directCmd);
|
||||||
@@ -121,8 +117,8 @@ public sealed partial class GraphicsTestWindow : Window
|
|||||||
var meshEntity = _world.EntityManager.CreateEntity(meshSet);
|
var meshEntity = _world.EntityManager.CreateEntity(meshSet);
|
||||||
_world.EntityManager.SetComponent(meshEntity, new MeshInstance
|
_world.EntityManager.SetComponent(meshEntity, new MeshInstance
|
||||||
{
|
{
|
||||||
mesh = meshHandle,
|
mesh = _meshHandle,
|
||||||
renderingLayerMask = new RenderingLayerMask(uint.MaxValue),
|
renderingLayerMask = RenderingLayerMask.All,
|
||||||
shadowCastingMode = Engine.ShadowCastingMode.On
|
shadowCastingMode = Engine.ShadowCastingMode.On
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -147,6 +143,8 @@ public sealed partial class GraphicsTestWindow : Window
|
|||||||
World.Destroy(_world.ID);
|
World.Destroy(_world.ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_renderSystem?.ResourceManager.ReleaseMesh(_meshHandle);
|
||||||
|
|
||||||
_swapChain?.Dispose();
|
_swapChain?.Dispose();
|
||||||
_renderSystem?.Dispose();
|
_renderSystem?.Dispose();
|
||||||
|
|
||||||
@@ -188,6 +186,8 @@ public sealed partial class GraphicsTestWindow : Window
|
|||||||
var queryID = new QueryBuilder().WithAll<Camera>().Build(_world);
|
var queryID = new QueryBuilder().WithAll<Camera>().Build(_world);
|
||||||
ref var query = ref _world.ComponentManager.GetEntityQueryReference(queryID);
|
ref var query = ref _world.ComponentManager.GetEntityQueryReference(queryID);
|
||||||
|
|
||||||
|
// FIX: A critical bug that resize happens on the render thread, but OnRendering invoke on the UI thread, and there is a chance that our extraction system already send the request to the render thread with old back buffer handle, which is already become invalid after resize.
|
||||||
|
// A proper solution is to use swap chain manager, camera only reference the id of the swap chain, and we will extract the current back buffer handle on the render thread.
|
||||||
foreach (ref var cam in query.GetComponentIterator<Camera>())
|
foreach (ref var cam in query.GetComponentIterator<Camera>())
|
||||||
{
|
{
|
||||||
cam.colorTarget = _swapChain.GetCurrentBackBuffer();
|
cam.colorTarget = _swapChain.GetCurrentBackBuffer();
|
||||||
|
|||||||
Reference in New Issue
Block a user