feat(render): support per-frame render payloads
Refactored the render pipeline system to introduce per-frame IRenderPayload management. IRenderPipelineSettings now requires CreatePipeline and CreatePayload methods. Updated RenderSystem and test pipeline to use the new payload model. Removed legacy GhostRenderPipeline and test code. Added RenderPipelineSystemAttribute for pipeline system registration. Includes minor fixes such as version field type corrections and typo fixes. BREAKING CHANGE: Render pipeline and payload creation APIs have changed; implementers must update to the new interface methods.
This commit is contained in:
@@ -26,6 +26,7 @@ public sealed partial class EngineCore : IDisposable
|
|||||||
{
|
{
|
||||||
FrameBufferCount = 2,
|
FrameBufferCount = 2,
|
||||||
GraphicsAPI = GraphicsAPI.Direct3D12,
|
GraphicsAPI = GraphicsAPI.Direct3D12,
|
||||||
|
InitialRenderPipelineSettings = null! // TODO: We should allow user to specify the initial render pipeline settings.
|
||||||
};
|
};
|
||||||
|
|
||||||
_renderSystem = new RenderSystem(renderingConfig);
|
_renderSystem = new RenderSystem(renderingConfig);
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using Ghost.Entities;
|
||||||
|
using Ghost.Graphics.RenderPipeline;
|
||||||
|
|
||||||
|
namespace Ghost.Engine.Systems;
|
||||||
|
|
||||||
|
public abstract class RenderPipelineSystemAttribute : Attribute
|
||||||
|
{
|
||||||
|
public abstract Type SettingsType { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class RenderPipelineSystemAttribute<T> : RenderPipelineSystemAttribute
|
||||||
|
where T : class, IRenderPipelineSettings
|
||||||
|
{
|
||||||
|
public override Type SettingsType => typeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RenderPipelineSystemRegistry
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<Type, List<Func<ISystem>>> s_renderPipelineSystems = new();
|
||||||
|
|
||||||
|
public static void RegisterRenderPipelineSystem(Type settingsType, Func<ISystem> systemFactory)
|
||||||
|
{
|
||||||
|
if (!s_renderPipelineSystems.TryGetValue(settingsType, out var systems))
|
||||||
|
{
|
||||||
|
systems = new List<Func<ISystem>>();
|
||||||
|
s_renderPipelineSystems[settingsType] = systems;
|
||||||
|
}
|
||||||
|
|
||||||
|
systems.Add(systemFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IEnumerable<Func<ISystem>> GetRenderPipelineSystems(Type settingsType)
|
||||||
|
{
|
||||||
|
if (s_renderPipelineSystems.TryGetValue(settingsType, out var systems))
|
||||||
|
{
|
||||||
|
return systems;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Enumerable.Empty<Func<ISystem>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/Runtime/Ghost.Engine/Systems/RenderSystemGroup.cs
Normal file
7
src/Runtime/Ghost.Engine/Systems/RenderSystemGroup.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
using Ghost.Entities;
|
||||||
|
|
||||||
|
namespace Ghost.Engine.Systems;
|
||||||
|
|
||||||
|
internal class RenderSystemGroup : SystemGroup
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -31,10 +31,10 @@ public abstract class SystemBase : ISystem
|
|||||||
get; init;
|
get; init;
|
||||||
} = null!;
|
} = null!;
|
||||||
|
|
||||||
public int LastSystemVersion
|
public uint LastSystemVersion
|
||||||
{
|
{
|
||||||
get; internal set;
|
get; internal set;
|
||||||
} = -2;
|
} = uint.MaxValue - 1;
|
||||||
|
|
||||||
private bool ShouldUpdate()
|
private bool ShouldUpdate()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,13 +28,13 @@ internal unsafe struct JobEntityBatch<TJob, T0> : IJobParallelFor
|
|||||||
public UnsafeList<int> bitsOffsets0;
|
public UnsafeList<int> bitsOffsets0;
|
||||||
public UnsafeList<int> versionIndices0;
|
public UnsafeList<int> versionIndices0;
|
||||||
|
|
||||||
public int version;
|
public uint version;
|
||||||
|
|
||||||
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
||||||
{
|
{
|
||||||
// 1. Get the specific pChunk for this thread
|
// 1. Get the specific pChunk for this thread
|
||||||
var pChunk = (byte*)chunks[loopIndex];
|
var pChunk = (byte*)chunks[loopIndex];
|
||||||
var pVersions = (int*)chunkVersions[loopIndex];
|
var pVersions = (uint*)chunkVersions[loopIndex];
|
||||||
var count = chunkCount[loopIndex];
|
var count = chunkCount[loopIndex];
|
||||||
|
|
||||||
var off0 = offsets0[loopIndex];
|
var off0 = offsets0[loopIndex];
|
||||||
@@ -93,13 +93,13 @@ internal unsafe struct JobEntityBatch<TJob, T0, T1> : IJobParallelFor
|
|||||||
public UnsafeList<int> bitsOffsets1;
|
public UnsafeList<int> bitsOffsets1;
|
||||||
public UnsafeList<int> versionIndices1;
|
public UnsafeList<int> versionIndices1;
|
||||||
|
|
||||||
public int version;
|
public uint version;
|
||||||
|
|
||||||
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
||||||
{
|
{
|
||||||
// 1. Get the specific pChunk for this thread
|
// 1. Get the specific pChunk for this thread
|
||||||
var pChunk = (byte*)chunks[loopIndex];
|
var pChunk = (byte*)chunks[loopIndex];
|
||||||
var pVersions = (int*)chunkVersions[loopIndex];
|
var pVersions = (uint*)chunkVersions[loopIndex];
|
||||||
var count = chunkCount[loopIndex];
|
var count = chunkCount[loopIndex];
|
||||||
|
|
||||||
var off0 = offsets0[loopIndex];
|
var off0 = offsets0[loopIndex];
|
||||||
@@ -179,13 +179,13 @@ internal unsafe struct JobEntityBatch<TJob, T0, T1, T2> : IJobParallelFor
|
|||||||
public UnsafeList<int> bitsOffsets2;
|
public UnsafeList<int> bitsOffsets2;
|
||||||
public UnsafeList<int> versionIndices2;
|
public UnsafeList<int> versionIndices2;
|
||||||
|
|
||||||
public int version;
|
public uint version;
|
||||||
|
|
||||||
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
||||||
{
|
{
|
||||||
// 1. Get the specific pChunk for this thread
|
// 1. Get the specific pChunk for this thread
|
||||||
var pChunk = (byte*)chunks[loopIndex];
|
var pChunk = (byte*)chunks[loopIndex];
|
||||||
var pVersions = (int*)chunkVersions[loopIndex];
|
var pVersions = (uint*)chunkVersions[loopIndex];
|
||||||
var count = chunkCount[loopIndex];
|
var count = chunkCount[loopIndex];
|
||||||
|
|
||||||
var off0 = offsets0[loopIndex];
|
var off0 = offsets0[loopIndex];
|
||||||
@@ -286,13 +286,13 @@ internal unsafe struct JobEntityBatch<TJob, T0, T1, T2, T3> : IJobParallelFor
|
|||||||
public UnsafeList<int> bitsOffsets3;
|
public UnsafeList<int> bitsOffsets3;
|
||||||
public UnsafeList<int> versionIndices3;
|
public UnsafeList<int> versionIndices3;
|
||||||
|
|
||||||
public int version;
|
public uint version;
|
||||||
|
|
||||||
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
||||||
{
|
{
|
||||||
// 1. Get the specific pChunk for this thread
|
// 1. Get the specific pChunk for this thread
|
||||||
var pChunk = (byte*)chunks[loopIndex];
|
var pChunk = (byte*)chunks[loopIndex];
|
||||||
var pVersions = (int*)chunkVersions[loopIndex];
|
var pVersions = (uint*)chunkVersions[loopIndex];
|
||||||
var count = chunkCount[loopIndex];
|
var count = chunkCount[loopIndex];
|
||||||
|
|
||||||
var off0 = offsets0[loopIndex];
|
var off0 = offsets0[loopIndex];
|
||||||
@@ -414,13 +414,13 @@ internal unsafe struct JobEntityBatch<TJob, T0, T1, T2, T3, T4> : IJobParallelFo
|
|||||||
public UnsafeList<int> bitsOffsets4;
|
public UnsafeList<int> bitsOffsets4;
|
||||||
public UnsafeList<int> versionIndices4;
|
public UnsafeList<int> versionIndices4;
|
||||||
|
|
||||||
public int version;
|
public uint version;
|
||||||
|
|
||||||
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
||||||
{
|
{
|
||||||
// 1. Get the specific pChunk for this thread
|
// 1. Get the specific pChunk for this thread
|
||||||
var pChunk = (byte*)chunks[loopIndex];
|
var pChunk = (byte*)chunks[loopIndex];
|
||||||
var pVersions = (int*)chunkVersions[loopIndex];
|
var pVersions = (uint*)chunkVersions[loopIndex];
|
||||||
var count = chunkCount[loopIndex];
|
var count = chunkCount[loopIndex];
|
||||||
|
|
||||||
var off0 = offsets0[loopIndex];
|
var off0 = offsets0[loopIndex];
|
||||||
@@ -563,13 +563,13 @@ internal unsafe struct JobEntityBatch<TJob, T0, T1, T2, T3, T4, T5> : IJobParall
|
|||||||
public UnsafeList<int> bitsOffsets5;
|
public UnsafeList<int> bitsOffsets5;
|
||||||
public UnsafeList<int> versionIndices5;
|
public UnsafeList<int> versionIndices5;
|
||||||
|
|
||||||
public int version;
|
public uint version;
|
||||||
|
|
||||||
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
||||||
{
|
{
|
||||||
// 1. Get the specific pChunk for this thread
|
// 1. Get the specific pChunk for this thread
|
||||||
var pChunk = (byte*)chunks[loopIndex];
|
var pChunk = (byte*)chunks[loopIndex];
|
||||||
var pVersions = (int*)chunkVersions[loopIndex];
|
var pVersions = (uint*)chunkVersions[loopIndex];
|
||||||
var count = chunkCount[loopIndex];
|
var count = chunkCount[loopIndex];
|
||||||
|
|
||||||
var off0 = offsets0[loopIndex];
|
var off0 = offsets0[loopIndex];
|
||||||
@@ -733,13 +733,13 @@ internal unsafe struct JobEntityBatch<TJob, T0, T1, T2, T3, T4, T5, T6> : IJobPa
|
|||||||
public UnsafeList<int> bitsOffsets6;
|
public UnsafeList<int> bitsOffsets6;
|
||||||
public UnsafeList<int> versionIndices6;
|
public UnsafeList<int> versionIndices6;
|
||||||
|
|
||||||
public int version;
|
public uint version;
|
||||||
|
|
||||||
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
||||||
{
|
{
|
||||||
// 1. Get the specific pChunk for this thread
|
// 1. Get the specific pChunk for this thread
|
||||||
var pChunk = (byte*)chunks[loopIndex];
|
var pChunk = (byte*)chunks[loopIndex];
|
||||||
var pVersions = (int*)chunkVersions[loopIndex];
|
var pVersions = (uint*)chunkVersions[loopIndex];
|
||||||
var count = chunkCount[loopIndex];
|
var count = chunkCount[loopIndex];
|
||||||
|
|
||||||
var off0 = offsets0[loopIndex];
|
var off0 = offsets0[loopIndex];
|
||||||
@@ -924,13 +924,13 @@ internal unsafe struct JobEntityBatch<TJob, T0, T1, T2, T3, T4, T5, T6, T7> : IJ
|
|||||||
public UnsafeList<int> bitsOffsets7;
|
public UnsafeList<int> bitsOffsets7;
|
||||||
public UnsafeList<int> versionIndices7;
|
public UnsafeList<int> versionIndices7;
|
||||||
|
|
||||||
public int version;
|
public uint version;
|
||||||
|
|
||||||
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
||||||
{
|
{
|
||||||
// 1. Get the specific pChunk for this thread
|
// 1. Get the specific pChunk for this thread
|
||||||
var pChunk = (byte*)chunks[loopIndex];
|
var pChunk = (byte*)chunks[loopIndex];
|
||||||
var pVersions = (int*)chunkVersions[loopIndex];
|
var pVersions = (uint*)chunkVersions[loopIndex];
|
||||||
var count = chunkCount[loopIndex];
|
var count = chunkCount[loopIndex];
|
||||||
|
|
||||||
var off0 = offsets0[loopIndex];
|
var off0 = offsets0[loopIndex];
|
||||||
@@ -1167,7 +1167,7 @@ public unsafe partial struct EntityQuery
|
|||||||
var it = _mask.writeAccess.GetIterator();
|
var it = _mask.writeAccess.GetIterator();
|
||||||
while (it.Next(out var id))
|
while (it.Next(out var id))
|
||||||
{
|
{
|
||||||
for (var i = 0; i < 1; i++)
|
for (var i =0; i < 1; i++)
|
||||||
{
|
{
|
||||||
if (id == runner.componentIDs[i])
|
if (id == runner.componentIDs[i])
|
||||||
{
|
{
|
||||||
@@ -1321,7 +1321,7 @@ public unsafe partial struct EntityQuery
|
|||||||
var it = _mask.writeAccess.GetIterator();
|
var it = _mask.writeAccess.GetIterator();
|
||||||
while (it.Next(out var id))
|
while (it.Next(out var id))
|
||||||
{
|
{
|
||||||
for (var i = 0; i < 1; i++)
|
for (var i =0; i < 1; i++)
|
||||||
{
|
{
|
||||||
if (id == runner.componentIDs[i])
|
if (id == runner.componentIDs[i])
|
||||||
{
|
{
|
||||||
@@ -1501,7 +1501,7 @@ public unsafe partial struct EntityQuery
|
|||||||
var it = _mask.writeAccess.GetIterator();
|
var it = _mask.writeAccess.GetIterator();
|
||||||
while (it.Next(out var id))
|
while (it.Next(out var id))
|
||||||
{
|
{
|
||||||
for (var i = 0; i < 1; i++)
|
for (var i =0; i < 1; i++)
|
||||||
{
|
{
|
||||||
if (id == runner.componentIDs[i])
|
if (id == runner.componentIDs[i])
|
||||||
{
|
{
|
||||||
@@ -1707,7 +1707,7 @@ public unsafe partial struct EntityQuery
|
|||||||
var it = _mask.writeAccess.GetIterator();
|
var it = _mask.writeAccess.GetIterator();
|
||||||
while (it.Next(out var id))
|
while (it.Next(out var id))
|
||||||
{
|
{
|
||||||
for (var i = 0; i < 1; i++)
|
for (var i =0; i < 1; i++)
|
||||||
{
|
{
|
||||||
if (id == runner.componentIDs[i])
|
if (id == runner.componentIDs[i])
|
||||||
{
|
{
|
||||||
@@ -1939,7 +1939,7 @@ public unsafe partial struct EntityQuery
|
|||||||
var it = _mask.writeAccess.GetIterator();
|
var it = _mask.writeAccess.GetIterator();
|
||||||
while (it.Next(out var id))
|
while (it.Next(out var id))
|
||||||
{
|
{
|
||||||
for (var i = 0; i < 1; i++)
|
for (var i =0; i < 1; i++)
|
||||||
{
|
{
|
||||||
if (id == runner.componentIDs[i])
|
if (id == runner.componentIDs[i])
|
||||||
{
|
{
|
||||||
@@ -2197,7 +2197,7 @@ public unsafe partial struct EntityQuery
|
|||||||
var it = _mask.writeAccess.GetIterator();
|
var it = _mask.writeAccess.GetIterator();
|
||||||
while (it.Next(out var id))
|
while (it.Next(out var id))
|
||||||
{
|
{
|
||||||
for (var i = 0; i < 1; i++)
|
for (var i =0; i < 1; i++)
|
||||||
{
|
{
|
||||||
if (id == runner.componentIDs[i])
|
if (id == runner.componentIDs[i])
|
||||||
{
|
{
|
||||||
@@ -2481,7 +2481,7 @@ public unsafe partial struct EntityQuery
|
|||||||
var it = _mask.writeAccess.GetIterator();
|
var it = _mask.writeAccess.GetIterator();
|
||||||
while (it.Next(out var id))
|
while (it.Next(out var id))
|
||||||
{
|
{
|
||||||
for (var i = 0; i < 1; i++)
|
for (var i =0; i < 1; i++)
|
||||||
{
|
{
|
||||||
if (id == runner.componentIDs[i])
|
if (id == runner.componentIDs[i])
|
||||||
{
|
{
|
||||||
@@ -2791,7 +2791,7 @@ public unsafe partial struct EntityQuery
|
|||||||
var it = _mask.writeAccess.GetIterator();
|
var it = _mask.writeAccess.GetIterator();
|
||||||
while (it.Next(out var id))
|
while (it.Next(out var id))
|
||||||
{
|
{
|
||||||
for (var i = 0; i < 1; i++)
|
for (var i =0; i < 1; i++)
|
||||||
{
|
{
|
||||||
if (id == runner.componentIDs[i])
|
if (id == runner.componentIDs[i])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,13 +41,13 @@ internal unsafe struct JobEntityBatch<TJob, <#= generics #>> : IJobParallelFor
|
|||||||
public UnsafeList<int> versionIndices<#= j #>;
|
public UnsafeList<int> versionIndices<#= j #>;
|
||||||
|
|
||||||
<# } #>
|
<# } #>
|
||||||
public int version;
|
public uint version;
|
||||||
|
|
||||||
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
|
||||||
{
|
{
|
||||||
// 1. Get the specific pChunk for this thread
|
// 1. Get the specific pChunk for this thread
|
||||||
var pChunk = (byte*)chunks[loopIndex];
|
var pChunk = (byte*)chunks[loopIndex];
|
||||||
var pVersions = (int*)chunkVersions[loopIndex];
|
var pVersions = (uint*)chunkVersions[loopIndex];
|
||||||
var count = chunkCount[loopIndex];
|
var count = chunkCount[loopIndex];
|
||||||
|
|
||||||
<# for (var j = 0; j < i; j++){ #>
|
<# for (var j = 0; j < i; j++){ #>
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
#if flase
|
|
||||||
using Ghost.Core;
|
|
||||||
using Ghost.Graphics.Core;
|
|
||||||
using Ghost.Graphics.RenderGraphModule;
|
|
||||||
using Ghost.Graphics.RHI;
|
|
||||||
using Misaki.HighPerformance.Mathematics;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics.RenderPipeline;
|
|
||||||
|
|
||||||
public partial class GhostRenderPipeline
|
|
||||||
{
|
|
||||||
private class MeshRenderPassData
|
|
||||||
{
|
|
||||||
public RenderList renderList;
|
|
||||||
public Identifier<RGTexture> renderTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class BlitPassData
|
|
||||||
{
|
|
||||||
public Identifier<RGTexture> source;
|
|
||||||
public Identifier<RGTexture> destination;
|
|
||||||
|
|
||||||
public Handle<Material> blitMaterial;
|
|
||||||
public Identifier<Sampler> sampler;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
private struct ShaderProperties_MyShader_Standard
|
|
||||||
{
|
|
||||||
public float4 color;
|
|
||||||
public uint texture1;
|
|
||||||
public uint texture2;
|
|
||||||
public uint texture3;
|
|
||||||
public uint texture4;
|
|
||||||
public uint tex_sampler;
|
|
||||||
|
|
||||||
private readonly uint _padding1;
|
|
||||||
private readonly uint _padding2;
|
|
||||||
private readonly uint _padding3;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
private struct ShaderProperties_Hidden_Blit
|
|
||||||
{
|
|
||||||
public uint mainTex;
|
|
||||||
public uint sampler_mainTex;
|
|
||||||
private readonly uint _padding1;
|
|
||||||
private readonly uint _padding2;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RenderTest(RenderGraph graph, Identifier<RGTexture> backbuffer)
|
|
||||||
{
|
|
||||||
Identifier<RGTexture> renderTarget;
|
|
||||||
using (var builder = graph.AddRasterRenderPass<MeshRenderPassData>("Mesh Render Pass", out var passData))
|
|
||||||
{
|
|
||||||
passData.mesh = _mesh;
|
|
||||||
passData.material = _material;
|
|
||||||
|
|
||||||
passData.renderTarget = builder.CreateTexture(RGTextureDesc.Relative(1.0f, TextureFormat.R8G8B8A8_UNorm), "Render Target");
|
|
||||||
builder.SetColorAttachment(passData.renderTarget, 0);
|
|
||||||
|
|
||||||
renderTarget = passData.renderTarget;
|
|
||||||
|
|
||||||
builder.SetRenderFunc<MeshRenderPassData>(static (data, ctx) =>
|
|
||||||
{
|
|
||||||
ctx.SetActiveMaterial(data.material);
|
|
||||||
ctx.SetActiveMesh(data.mesh);
|
|
||||||
|
|
||||||
var threadGroupCountX = ((uint)ctx.ActiveMeshIndexCount + 2u) / 3u;
|
|
||||||
ctx.DispatchMesh(new uint3(threadGroupCountX, 1u, 1u));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var builder = graph.AddUnsafeRenderPass<BlitPassData>("Blit Pass", out var passData))
|
|
||||||
{
|
|
||||||
passData.source = renderTarget;
|
|
||||||
passData.destination = backbuffer;
|
|
||||||
passData.blitMaterial = _blitMaterial;
|
|
||||||
passData.sampler = _sampler;
|
|
||||||
|
|
||||||
builder.UseTexture(passData.source, AccessFlags.Read);
|
|
||||||
builder.UseTexture(passData.destination, AccessFlags.WriteAll);
|
|
||||||
|
|
||||||
builder.SetRenderFunc<BlitPassData>(static (data, ctx) =>
|
|
||||||
{
|
|
||||||
var r = ctx.ResourceManager.GetMaterialReference(data.blitMaterial);
|
|
||||||
if (r.IsFailure)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref var matRef = ref r.Value;
|
|
||||||
var blitProps = new ShaderProperties_Hidden_Blit
|
|
||||||
{
|
|
||||||
mainTex = ctx.ResourceDatabase.GetBindlessIndex(ctx.GetActualResource(data.source.AsResource())),
|
|
||||||
sampler_mainTex = (uint)data.sampler.Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
matRef.SetPropertyCache(in blitProps).ThrowIfFailed();
|
|
||||||
matRef.UploadData(ctx.CommandBuffer, ctx.ResourceDatabase);
|
|
||||||
|
|
||||||
ctx.CommandBuffer.SetRenderTargets([ctx.GetActualTexture(data.destination)], Handle<Texture>.Invalid);
|
|
||||||
|
|
||||||
ctx.SetActiveMaterial(data.blitMaterial);
|
|
||||||
ctx.SetActiveMesh(Handle<Mesh>.Invalid); // Generate a full-screen triangle dynamically in mesh shader.
|
|
||||||
ctx.DispatchMesh(new uint3(1, 1, 1));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
using Ghost.Graphics.Core;
|
|
||||||
using Ghost.Graphics.RenderGraphModule;
|
|
||||||
using Ghost.Graphics.RHI;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics.RenderPipeline;
|
|
||||||
|
|
||||||
public sealed class GhostRenderPipelineSettings : IRenderPipelineSettings
|
|
||||||
{
|
|
||||||
IRenderPipeline IRenderPipelineSettings.CreatePipeline(RenderSystem renderSystem)
|
|
||||||
{
|
|
||||||
return new GhostRenderPipeline(renderSystem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal unsafe partial class GhostRenderPipeline : IRenderPipeline
|
|
||||||
{
|
|
||||||
private readonly RenderGraph _renderGraph;
|
|
||||||
|
|
||||||
private bool _disposed;
|
|
||||||
|
|
||||||
~GhostRenderPipeline()
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Conditional("DEBUG")]
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
protected void ThrowIfDisposed()
|
|
||||||
{
|
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal GhostRenderPipeline(RenderSystem renderSystem)
|
|
||||||
{
|
|
||||||
_renderGraph = new RenderGraph(renderSystem.ResourceManager,
|
|
||||||
renderSystem.GraphicsEngine.ResourceAllocator,
|
|
||||||
renderSystem.GraphicsEngine.ResourceDatabase,
|
|
||||||
renderSystem.GraphicsEngine.PipelineLibrary,
|
|
||||||
renderSystem.GraphicsEngine.ShaderCompiler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Render(RenderContext ctx, ReadOnlySpan<RenderRequest> requests)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < requests.Length; i++)
|
|
||||||
{
|
|
||||||
ref readonly var request = ref requests[i];
|
|
||||||
|
|
||||||
if (request.renderFunc != null)
|
|
||||||
{
|
|
||||||
request.renderFunc(in ctx, in request);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Set up the rendering pipeline using render graph based on the request data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_renderGraph.Dispose();
|
|
||||||
|
|
||||||
_disposed = true;
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,11 +2,15 @@ using Ghost.Graphics.Core;
|
|||||||
|
|
||||||
namespace Ghost.Graphics.RenderPipeline;
|
namespace Ghost.Graphics.RenderPipeline;
|
||||||
|
|
||||||
public interface IRenderPayload : IDisposable;
|
public interface IRenderPayload : IDisposable
|
||||||
|
{
|
||||||
|
void Reset();
|
||||||
|
}
|
||||||
|
|
||||||
public interface IRenderPipelineSettings
|
public interface IRenderPipelineSettings
|
||||||
{
|
{
|
||||||
void CreatePipeline(RenderSystem renderSystem, out IRenderPipeline renderPipeline, out IRenderPayload renderPayload);
|
IRenderPipeline CreatePipeline(RenderSystem renderSystem);
|
||||||
|
IRenderPayload CreatePayload(RenderSystem renderSystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IRenderPipeline : IDisposable
|
public interface IRenderPipeline : IDisposable
|
||||||
|
|||||||
@@ -3,12 +3,9 @@ using Ghost.Graphics.Core;
|
|||||||
using Ghost.Graphics.D3D12;
|
using Ghost.Graphics.D3D12;
|
||||||
using Ghost.Graphics.RenderPipeline;
|
using Ghost.Graphics.RenderPipeline;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
|
||||||
using Misaki.HighPerformance.Mathematics;
|
using Misaki.HighPerformance.Mathematics;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics;
|
namespace Ghost.Graphics;
|
||||||
|
|
||||||
@@ -17,21 +14,21 @@ internal enum GraphicsAPI
|
|||||||
Direct3D12
|
Direct3D12
|
||||||
}
|
}
|
||||||
|
|
||||||
internal struct RenderSystemDesc
|
internal readonly struct RenderSystemDesc
|
||||||
{
|
{
|
||||||
public GraphicsAPI GraphicsAPI
|
public GraphicsAPI GraphicsAPI
|
||||||
{
|
{
|
||||||
get; set;
|
get; init;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint FrameBufferCount
|
public uint FrameBufferCount
|
||||||
{
|
{
|
||||||
get; set;
|
get; init;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IRenderPipelineSettings? InitialRenderPipelineSettings
|
public required IRenderPipelineSettings InitialRenderPipelineSettings
|
||||||
{
|
{
|
||||||
get; set;
|
get; init;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,11 +60,17 @@ public class RenderSystem : IDisposable
|
|||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IRenderPayload RenderPayload
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
public readonly void Dispose()
|
public readonly void Dispose()
|
||||||
{
|
{
|
||||||
CpuReadyEvent.Dispose();
|
CpuReadyEvent.Dispose();
|
||||||
GpuReadyEvent.Dispose();
|
GpuReadyEvent.Dispose();
|
||||||
CommandAllocator.Dispose();
|
CommandAllocator.Dispose();
|
||||||
|
RenderPayload.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +88,6 @@ public class RenderSystem : IDisposable
|
|||||||
|
|
||||||
private IRenderPipelineSettings _renderPipelineSettings;
|
private IRenderPipelineSettings _renderPipelineSettings;
|
||||||
private IRenderPipeline _renderPipeline;
|
private IRenderPipeline _renderPipeline;
|
||||||
private IRenderPayload _renderPayload;
|
|
||||||
|
|
||||||
private ulong _cpuFenceValue;
|
private ulong _cpuFenceValue;
|
||||||
private ulong _submittedFenceValue;
|
private ulong _submittedFenceValue;
|
||||||
@@ -104,7 +106,6 @@ public class RenderSystem : IDisposable
|
|||||||
|
|
||||||
public uint MaxFrameLatency => _config.FrameBufferCount;
|
public uint MaxFrameLatency => _config.FrameBufferCount;
|
||||||
|
|
||||||
public IRenderPayload RenderPayload => _renderPayload;
|
|
||||||
public IRenderPipelineSettings RenderPipelineSettings
|
public IRenderPipelineSettings RenderPipelineSettings
|
||||||
{
|
{
|
||||||
get => _renderPipelineSettings;
|
get => _renderPipelineSettings;
|
||||||
@@ -119,10 +120,18 @@ public class RenderSystem : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_renderPipeline?.Dispose();
|
_renderPipeline?.Dispose();
|
||||||
_renderPayload?.Dispose();
|
for (int i = 0; i < _frameResources.Length; i++)
|
||||||
|
{
|
||||||
|
_frameResources[i].RenderPayload?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
_renderPipelineSettings = value;
|
_renderPipelineSettings = value;
|
||||||
_renderPipelineSettings.CreatePipeline(this, out _renderPipeline, out _renderPayload);
|
|
||||||
|
_renderPipeline = _renderPipelineSettings.CreatePipeline(this);
|
||||||
|
for (var i = 0; i < _frameResources.Length; i++)
|
||||||
|
{
|
||||||
|
_frameResources[i].RenderPayload = _renderPipelineSettings.CreatePayload(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,8 +188,13 @@ public class RenderSystem : IDisposable
|
|||||||
_shutdownEvent = new AutoResetEvent(false);
|
_shutdownEvent = new AutoResetEvent(false);
|
||||||
_resizeRequest = new ConcurrentDictionary<ISwapChain, uint2>();
|
_resizeRequest = new ConcurrentDictionary<ISwapChain, uint2>();
|
||||||
|
|
||||||
_renderPipelineSettings = _config.InitialRenderPipelineSettings ?? new GhostRenderPipelineSettings();
|
_renderPipelineSettings = _config.InitialRenderPipelineSettings;
|
||||||
_renderPipelineSettings.CreatePipeline(this, out _renderPipeline, out _renderPayload);
|
|
||||||
|
_renderPipeline = _renderPipelineSettings.CreatePipeline(this);
|
||||||
|
for (var i = 0; i < _frameResources.Length; i++)
|
||||||
|
{
|
||||||
|
_frameResources[i].RenderPayload = _renderPipelineSettings.CreatePayload(this);
|
||||||
|
}
|
||||||
|
|
||||||
_isRunning = false;
|
_isRunning = false;
|
||||||
_disposed = false;
|
_disposed = false;
|
||||||
@@ -207,12 +221,13 @@ public class RenderSystem : IDisposable
|
|||||||
var waitHandles = new WaitHandle[] { null!, _shutdownEvent };
|
var waitHandles = new WaitHandle[] { null!, _shutdownEvent };
|
||||||
|
|
||||||
while (_isRunning)
|
while (_isRunning)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var frameIndex = (int)(_submittedFenceValue % _config.FrameBufferCount);
|
var frameIndex = (int)(_submittedFenceValue % _config.FrameBufferCount);
|
||||||
ref var frameResource = ref _frameResources[frameIndex];
|
ref var frameResource = ref _frameResources[frameIndex];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
// Wait for either CPU ready signal or shutdown signal
|
// Wait for either CPU ready signal or shutdown signal
|
||||||
waitHandles[0] = frameResource.CpuReadyEvent;
|
waitHandles[0] = frameResource.CpuReadyEvent;
|
||||||
var waitResult = WaitHandle.WaitAny(waitHandles);
|
var waitResult = WaitHandle.WaitAny(waitHandles);
|
||||||
@@ -268,7 +283,7 @@ public class RenderSystem : IDisposable
|
|||||||
|
|
||||||
var ctx = new RenderContext(_graphicsEngine, _resourceManager, cmd);
|
var ctx = new RenderContext(_graphicsEngine, _resourceManager, cmd);
|
||||||
|
|
||||||
_renderPipeline.Render(ctx, frameIndex, _renderPayload);
|
_renderPipeline.Render(ctx, frameIndex, frameResource.RenderPayload);
|
||||||
_swapChainManager.TransitionToPresent(cmd);
|
_swapChainManager.TransitionToPresent(cmd);
|
||||||
|
|
||||||
// End recording commands and submit
|
// End recording commands and submit
|
||||||
@@ -296,6 +311,8 @@ public class RenderSystem : IDisposable
|
|||||||
// End the frame and retire resources based on the freshest observed GPU progress.
|
// End the frame and retire resources based on the freshest observed GPU progress.
|
||||||
_resourceManager.EndFrame(completedFrame);
|
_resourceManager.EndFrame(completedFrame);
|
||||||
_graphicsEngine.EndFrame(completedFrame);
|
_graphicsEngine.EndFrame(completedFrame);
|
||||||
|
|
||||||
|
frameResource.RenderPayload.Reset();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -391,6 +408,16 @@ public class RenderSystem : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IRenderPayload GetCurrentFramePayload()
|
||||||
|
{
|
||||||
|
Debug.Assert(!_disposed, "Cannot get current frame payload from a disposed RenderSystem.");
|
||||||
|
|
||||||
|
var eventIndex = (int)(_cpuFenceValue % _config.FrameBufferCount);
|
||||||
|
ref var frameResource = ref _frameResources[eventIndex];
|
||||||
|
|
||||||
|
return frameResource.RenderPayload;
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
|
|||||||
@@ -37,11 +37,11 @@ public class ResourceUploadBatch
|
|||||||
|
|
||||||
public void WaitIdle()
|
public void WaitIdle()
|
||||||
{
|
{
|
||||||
_device.GraphicsQueue.WaitIdle();
|
_device.CopyQueue.WaitIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task WaitAsync()
|
public Task WaitAsync()
|
||||||
{
|
{
|
||||||
return _device.GraphicsQueue.WaitAsync();
|
return _device.CopyQueue.WaitAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,11 +104,10 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
|||||||
{
|
{
|
||||||
var testPayload = (TestRenderPayload)payload;
|
var testPayload = (TestRenderPayload)payload;
|
||||||
|
|
||||||
var renderSystem = testPayload.RenderSystem;
|
var resourceManager = _renderSystem.ResourceManager;
|
||||||
var resourceManager = renderSystem.ResourceManager;
|
var resourceDatabase = _renderSystem.GraphicsEngine.ResourceDatabase;
|
||||||
var resourceDatabase = renderSystem.GraphicsEngine.ResourceDatabase;
|
|
||||||
|
|
||||||
var requests = testPayload.FrameRequestData[frameIndex].renderRequests;
|
var requests = testPayload.renderRequests;
|
||||||
|
|
||||||
for (var i = 0; i < requests.Count; i++)
|
for (var i = 0; i < requests.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -126,7 +125,7 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
|||||||
{
|
{
|
||||||
rt = request.colorTarget;
|
rt = request.colorTarget;
|
||||||
}
|
}
|
||||||
else if (renderSystem.SwapChainManager.TryGetSwapChain(request.swapChainIndex, out var swapChain))
|
else if (_renderSystem.SwapChainManager.TryGetSwapChain(request.swapChainIndex, out var swapChain))
|
||||||
{
|
{
|
||||||
rt = swapChain.GetCurrentBackBuffer();
|
rt = swapChain.GetCurrentBackBuffer();
|
||||||
}
|
}
|
||||||
@@ -137,7 +136,7 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var rtResult = renderSystem.GraphicsEngine.ResourceDatabase.GetResourceDescription(rt.AsResource());
|
var rtResult = _renderSystem.GraphicsEngine.ResourceDatabase.GetResourceDescription(rt.AsResource());
|
||||||
if (rtResult.IsFailure)
|
if (rtResult.IsFailure)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -312,7 +311,7 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
|||||||
{
|
{
|
||||||
if (request.swapChainIndex >= 0)
|
if (request.swapChainIndex >= 0)
|
||||||
{
|
{
|
||||||
renderSystem.SwapChainManager.ReleaseSwapChain(request.swapChainIndex);
|
_renderSystem.SwapChainManager.ReleaseSwapChain(request.swapChainIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,48 +7,38 @@ namespace Ghost.Graphics.Test.RenderPipeline;
|
|||||||
|
|
||||||
internal sealed class TestRenderPayload : IRenderPayload
|
internal sealed class TestRenderPayload : IRenderPayload
|
||||||
{
|
{
|
||||||
public class FrameData
|
|
||||||
{
|
|
||||||
public UnsafeList<RenderRequest> renderRequests;
|
public UnsafeList<RenderRequest> renderRequests;
|
||||||
|
|
||||||
|
public TestRenderPayload()
|
||||||
|
{
|
||||||
|
renderRequests = new UnsafeList<RenderRequest>(2, Allocator.Persistent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly RenderSystem _renderSystem;
|
public void Reset()
|
||||||
private readonly FrameData[] _frameData;
|
|
||||||
|
|
||||||
public RenderSystem RenderSystem => _renderSystem;
|
|
||||||
public ReadOnlySpan<FrameData> FrameRequestData => _frameData;
|
|
||||||
|
|
||||||
public TestRenderPayload(RenderSystem renderSystem)
|
|
||||||
{
|
{
|
||||||
_renderSystem = renderSystem;
|
for (int i = 0; i < renderRequests.Count; i++)
|
||||||
_frameData = new FrameData[renderSystem.MaxFrameLatency];
|
|
||||||
|
|
||||||
for (int i = 0; i < _frameData.Length; i++)
|
|
||||||
{
|
{
|
||||||
_frameData[i].renderRequests = new UnsafeList<RenderRequest>(2, Allocator.Persistent);
|
renderRequests[i].Dispose();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddRenderRequest(RenderRequest request)
|
renderRequests.Clear();
|
||||||
{
|
|
||||||
var index = (int)(_renderSystem.CPUFenceValue % (uint)_frameData.Length);
|
|
||||||
_frameData[index].renderRequests.Add(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _frameData.Length; i++)
|
renderRequests.Dispose();
|
||||||
{
|
|
||||||
_frameData[i].renderRequests.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class TestRenderPipelineSettings : IRenderPipelineSettings
|
internal sealed class TestRenderPipelineSettings : IRenderPipelineSettings
|
||||||
{
|
{
|
||||||
public void CreatePipeline(RenderSystem renderSystem, out IRenderPipeline renderPipeline, out IRenderPayload renderPayload)
|
public IRenderPipeline CreatePipeline(RenderSystem renderSystem)
|
||||||
{
|
{
|
||||||
renderPipeline = new TestRenderPipeline(renderSystem);
|
return new TestRenderPipeline(renderSystem);
|
||||||
renderPayload = new TestRenderPayload(renderSystem);
|
}
|
||||||
|
|
||||||
|
public IRenderPayload CreatePayload(RenderSystem renderSystem)
|
||||||
|
{
|
||||||
|
return new TestRenderPayload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Engine;
|
using Ghost.Engine;
|
||||||
using Ghost.Engine.Components;
|
using Ghost.Engine.Components;
|
||||||
|
using Ghost.Engine.Systems;
|
||||||
using Ghost.Entities;
|
using Ghost.Entities;
|
||||||
using Ghost.Graphics.Core;
|
using Ghost.Graphics.Core;
|
||||||
using Ghost.Graphics.Test.RenderPipeline;
|
using Ghost.Graphics.Test.RenderPipeline;
|
||||||
@@ -9,6 +10,7 @@ using Misaki.HighPerformance.Mathematics;
|
|||||||
|
|
||||||
namespace Ghost.Graphics.Test.Systems;
|
namespace Ghost.Graphics.Test.Systems;
|
||||||
|
|
||||||
|
[RenderPipelineSystem<TestRenderPipelineSettings>]
|
||||||
public class RenderExtractionSystem : ISystem
|
public class RenderExtractionSystem : ISystem
|
||||||
{
|
{
|
||||||
private RenderSystem _renderSystem = null!;
|
private RenderSystem _renderSystem = null!;
|
||||||
@@ -135,7 +137,7 @@ public class RenderExtractionSystem : ISystem
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
((TestRenderPayload)_renderSystem.RenderPayload).AddRenderRequest(request);
|
((TestRenderPayload)_renderSystem.GetCurrentFramePayload()).renderRequests.Add(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Engine.Components;
|
using Ghost.Engine.Components;
|
||||||
using Ghost.Engine.Systems;
|
|
||||||
using Ghost.Engine.Utilities;
|
using Ghost.Engine.Utilities;
|
||||||
using Ghost.Entities;
|
using Ghost.Entities;
|
||||||
using Ghost.Graphics.Core;
|
using Ghost.Graphics.Core;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
|
using Ghost.Graphics.Test.Systems;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Media;
|
using Microsoft.UI.Xaml.Media;
|
||||||
@@ -53,7 +53,7 @@ public sealed partial class GraphicsTestWindow : Window
|
|||||||
{
|
{
|
||||||
FrameBufferCount = 2,
|
FrameBufferCount = 2,
|
||||||
GraphicsAPI = GraphicsAPI.Direct3D12,
|
GraphicsAPI = GraphicsAPI.Direct3D12,
|
||||||
InitialRenderPipelineSettings = new RenderPasses.TestRenderPipelineSettings()
|
InitialRenderPipelineSettings = new RenderPipeline.TestRenderPipelineSettings()
|
||||||
});
|
});
|
||||||
|
|
||||||
_swapChain = _renderSystem.SwapChainManager.EnsureSwapChain(0, new SwapChainDesc
|
_swapChain = _renderSystem.SwapChainManager.EnsureSwapChain(0, new SwapChainDesc
|
||||||
@@ -159,6 +159,9 @@ public sealed partial class GraphicsTestWindow : Window
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
System.Diagnostics.Debugger.Break();
|
||||||
|
#endif
|
||||||
Environment.FailFast("Failed to close the window properly.", ex);
|
Environment.FailFast("Failed to close the window properly.", ex);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ internal class MeshoptBenchmark : ITest
|
|||||||
};
|
};
|
||||||
var error = new ufbx_error();
|
var error = new ufbx_error();
|
||||||
|
|
||||||
using var pool = new MemoryPool<VirtualStack, VirtualStack.CreationOpts>(new VirtualStack.CreationOpts
|
using var pool = new MemoryPool<VirtualStack, VirtualStack.CreationOptions>(new VirtualStack.CreationOptions
|
||||||
{
|
{
|
||||||
reserveCapacity = 256 * 1024 * 1024 // 256 MB should be enough for most models, adjust as needed. Note that this use virtual memory and does not actually consume physical memory until allocations are made.
|
reserveCapacity = 256 * 1024 * 1024 // 256 MB should be enough for most models, adjust as needed. Note that this use virtual memory and does not actually consume physical memory until allocations are made.
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user