Refactor render graph error handling and resource APIs
- RenderGraph.Compile/Execute now return Error for better failure detection; error handling is propagated throughout compiler and executor. - Renamed ScheduleReleaseResource to ReleaseResource for clarity; updated all usages. - ResourceManager now calls ReleaseResource directly on Mesh, Material, and Shader types. - Camera exposes Actual/Virtual size properties and Render returns Error. - RenderingContext now uses IResourceManager for mesh/resource ops. - Replaced custom BinaryWriter with BufferWriter in RenderGraphHasher. - Improved variable naming, interface signatures, and code formatting. - Added Error extension for IsSuccess/IsFailure. - Minor FMOD/native interop and test code cleanups. - No breaking API changes except for new Error return values on some methods.
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Core.Graphics;
|
using Ghost.Core.Graphics;
|
||||||
using Ghost.DSL.ShaderParser;
|
using Ghost.DSL.ShaderParser;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Ghost.DSL.ShaderCompiler;
|
namespace Ghost.DSL.ShaderCompiler;
|
||||||
@@ -107,7 +106,7 @@ internal static class DSLShaderCompiler
|
|||||||
if (semantics.passes != null)
|
if (semantics.passes != null)
|
||||||
{
|
{
|
||||||
descriptor.passes = new PassDescriptor[semantics.passes.Count];
|
descriptor.passes = new PassDescriptor[semantics.passes.Count];
|
||||||
for (int i = 0; i < semantics.passes.Count; i++)
|
for (var i = 0; i < semantics.passes.Count; i++)
|
||||||
{
|
{
|
||||||
var pass = semantics.passes[i];
|
var pass = semantics.passes[i];
|
||||||
var localPipeline = MeragePipeline(pass.localPipeline, PipelineState.Default);
|
var localPipeline = MeragePipeline(pass.localPipeline, PipelineState.Default);
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Editor.Core.Contracts;
|
using Ghost.Editor.Core.Contracts;
|
||||||
using Ghost.Graphics.Core;
|
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.Image;
|
using Misaki.HighPerformance.Image;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Configuration;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using TerraFX.Interop.Windows;
|
|
||||||
using static Ghost.Editor.Core.AssetHandler.TextureAssetSettings;
|
using static Ghost.Editor.Core.AssetHandler.TextureAssetSettings;
|
||||||
|
|
||||||
namespace Ghost.Editor.Core.AssetHandler;
|
namespace Ghost.Editor.Core.AssetHandler;
|
||||||
@@ -228,7 +225,7 @@ internal class TextureAssetHandler : IImportableAssetHandler
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ref byte address = ref MemoryMarshal.GetReference(tempArray);
|
ref var address = ref MemoryMarshal.GetReference(tempArray);
|
||||||
Unsafe.WriteUnaligned(ref address, settings.Basic);
|
Unsafe.WriteUnaligned(ref address, settings.Basic);
|
||||||
Unsafe.WriteUnaligned(ref Unsafe.Add(ref address, Unsafe.SizeOf<BasicSettings>()), settings.Advanced);
|
Unsafe.WriteUnaligned(ref Unsafe.Add(ref address, Unsafe.SizeOf<BasicSettings>()), settings.Advanced);
|
||||||
Unsafe.WriteUnaligned(ref Unsafe.Add(ref address, Unsafe.SizeOf<BasicSettings>() + Unsafe.SizeOf<AdvancedSettings>()), settings.Sampler);
|
Unsafe.WriteUnaligned(ref Unsafe.Add(ref address, Unsafe.SizeOf<BasicSettings>() + Unsafe.SizeOf<AdvancedSettings>()), settings.Sampler);
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ namespace Ghost.Editor.Core.Contracts;
|
|||||||
|
|
||||||
public interface IInspectable
|
public interface IInspectable
|
||||||
{
|
{
|
||||||
public IconSource? CreateIcon();
|
IconSource? CreateIcon();
|
||||||
|
|
||||||
public UIElement? CreateHeader();
|
UIElement? CreateHeader();
|
||||||
|
|
||||||
public UIElement? CreateInspector();
|
UIElement? CreateInspector();
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,6 @@ namespace Ghost.Editor.Core.Contracts;
|
|||||||
|
|
||||||
public interface INavigationAware
|
public interface INavigationAware
|
||||||
{
|
{
|
||||||
public void OnNavigatedTo(object? parameter);
|
void OnNavigatedTo(object? parameter);
|
||||||
public void OnNavigatedFrom();
|
void OnNavigatedFrom();
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,6 @@ namespace Ghost.Editor.Core.Contracts;
|
|||||||
|
|
||||||
public interface INotificationService
|
public interface INotificationService
|
||||||
{
|
{
|
||||||
public void ShowNotification(string? message, MessageType type, int duration = 5, string? title = null);
|
void ShowNotification(string? message, MessageType type, int duration = 5, string? title = null);
|
||||||
public void ShowNotification(Notification notification);
|
void ShowNotification(Notification notification);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ namespace Ghost.Editor.Core.Contracts;
|
|||||||
|
|
||||||
public interface IProgressService
|
public interface IProgressService
|
||||||
{
|
{
|
||||||
public void ShowProgress(string message, double progress = 0.0);
|
void ShowProgress(string message, double progress = 0.0);
|
||||||
public void ShowIndeterminateProgress(string message);
|
void ShowIndeterminateProgress(string message);
|
||||||
public void SetProgress(double progress);
|
void SetProgress(double progress);
|
||||||
public void HideProgress();
|
void HideProgress();
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using Ghost.Editor.Core.Utilities;
|
using Ghost.Editor.Core.Utilities;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
|
|
||||||
namespace Ghost.Editor.Core.Controls;
|
namespace Ghost.Editor.Core.Controls;
|
||||||
@@ -93,7 +92,7 @@ public sealed partial class ContextFlyout : MenuFlyout
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentGroup = nodes[0].EffectiveGroup;
|
var currentGroup = nodes[0].EffectiveGroup;
|
||||||
|
|
||||||
foreach (var node in nodes)
|
foreach (var node in nodes)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
using Ghost.Editor.Core;
|
|
||||||
using Ghost.Editor.Core.Contracts;
|
|
||||||
using Ghost.Editor.Core.Utilities;
|
using Ghost.Editor.Core.Utilities;
|
||||||
using Ghost.Editor.Models;
|
using Ghost.Editor.Models;
|
||||||
using Ghost.Engine;
|
using Ghost.Engine;
|
||||||
using Microsoft.UI.Xaml;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Ghost.Editor;
|
namespace Ghost.Editor;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Editor.Core;
|
using Ghost.Editor.Core;
|
||||||
using Ghost.Editor.Core.AssetHandle;
|
|
||||||
using Ghost.Editor.Core.Contracts;
|
using Ghost.Editor.Core.Contracts;
|
||||||
using Ghost.Editor.Core.Services;
|
using Ghost.Editor.Core.Services;
|
||||||
using Ghost.Editor.View.Pages.EngineEditor;
|
using Ghost.Editor.View.Pages.EngineEditor;
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
using Ghost.Engine.Utilities;
|
|
||||||
using Microsoft.UI.Xaml.Data;
|
using Microsoft.UI.Xaml.Data;
|
||||||
using Misaki.HighPerformance.Mathematics;
|
using Misaki.HighPerformance.Mathematics;
|
||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace Ghost.Editor.Utilities.Converters;
|
namespace Ghost.Editor.Utilities.Converters;
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,4 @@
|
|||||||
using Microsoft.UI.Xaml;
|
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
|
||||||
using Microsoft.UI.Xaml.Data;
|
|
||||||
using Microsoft.UI.Xaml.Input;
|
|
||||||
using Microsoft.UI.Xaml.Media;
|
|
||||||
using Microsoft.UI.Xaml.Navigation;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
|
|
||||||
// To learn more about WinUI, the WinUI project structure,
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using Ghost.Editor.Core;
|
|||||||
using Ghost.Editor.Core.Contracts;
|
using Ghost.Editor.Core.Contracts;
|
||||||
using Ghost.Editor.Core.Services;
|
using Ghost.Editor.Core.Services;
|
||||||
using Ghost.Editor.ViewModels.Windows;
|
using Ghost.Editor.ViewModels.Windows;
|
||||||
using System.Diagnostics;
|
|
||||||
using Windows.ApplicationModel;
|
using Windows.ApplicationModel;
|
||||||
using WinUIEx;
|
using WinUIEx;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Ghost.Editor.Core;
|
using Ghost.Editor.Core;
|
||||||
using Ghost.Editor.Core.AssetHandle;
|
|
||||||
using Ghost.Editor.Core.Contracts;
|
using Ghost.Editor.Core.Contracts;
|
||||||
using Ghost.Editor.Core.Utilities;
|
using Ghost.Editor.Core.Utilities;
|
||||||
using Ghost.Editor.Models;
|
using Ghost.Editor.Models;
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Ghost.Editor.Core.Contracts;
|
using Ghost.Editor.Core.Contracts;
|
||||||
using Ghost.Editor.Core.SceneGraph;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
|
|
||||||
namespace Ghost.Editor.ViewModels.Pages.EngineEditor;
|
namespace Ghost.Editor.ViewModels.Pages.EngineEditor;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Ghost.Editor.Core;
|
using Ghost.Editor.Core;
|
||||||
using Ghost.Editor.Core.AssetHandle;
|
|
||||||
using Ghost.Editor.Core.Contracts;
|
|
||||||
using Ghost.Editor.Models;
|
using Ghost.Editor.Models;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ public readonly struct Handle<T> : IEquatable<Handle<T>>
|
|||||||
public readonly bool IsValid => this != Invalid;
|
public readonly bool IsValid => this != Invalid;
|
||||||
public readonly bool IsInvalid => this == Invalid;
|
public readonly bool IsInvalid => this == Invalid;
|
||||||
|
|
||||||
public readonly override int GetHashCode()
|
public override readonly int GetHashCode()
|
||||||
{
|
{
|
||||||
return ID + (Generation << 16);
|
return ID + (Generation << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly override bool Equals(object? obj)
|
public override readonly bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
return obj is Handle<T> id && Equals(id);
|
return obj is Handle<T> id && Equals(id);
|
||||||
}
|
}
|
||||||
@@ -76,12 +76,12 @@ public readonly struct Identifier<T> : IEquatable<Identifier<T>>
|
|||||||
public readonly bool IsValid => this != Invalid;
|
public readonly bool IsValid => this != Invalid;
|
||||||
public readonly bool IsInvalid => this == Invalid;
|
public readonly bool IsInvalid => this == Invalid;
|
||||||
|
|
||||||
public readonly override int GetHashCode()
|
public override readonly int GetHashCode()
|
||||||
{
|
{
|
||||||
return Value;
|
return Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly override bool Equals(object? obj)
|
public override readonly bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
return obj is Identifier<T> id && Equals(id);
|
return obj is Identifier<T> id && Equals(id);
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ public readonly struct Key64<T> : IEquatable<Key64<T>>
|
|||||||
public bool IsValid => this != Invalid;
|
public bool IsValid => this != Invalid;
|
||||||
public bool IsInvalid => this == Invalid;
|
public bool IsInvalid => this == Invalid;
|
||||||
|
|
||||||
public readonly override int GetHashCode()
|
public override readonly int GetHashCode()
|
||||||
{
|
{
|
||||||
return Value.GetHashCode();
|
return Value.GetHashCode();
|
||||||
}
|
}
|
||||||
@@ -167,7 +167,7 @@ public readonly struct Key64<T> : IEquatable<Key64<T>>
|
|||||||
return Value.CompareTo(other.Value);
|
return Value.CompareTo(other.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly override bool Equals(object? obj)
|
public override readonly bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
return obj is Key64<T> id && Equals(id);
|
return obj is Key64<T> id && Equals(id);
|
||||||
}
|
}
|
||||||
@@ -205,7 +205,7 @@ public readonly struct Key128<T> : IEquatable<Key128<T>>
|
|||||||
public bool IsValid => this != Invalid;
|
public bool IsValid => this != Invalid;
|
||||||
public bool IsInvalid => this == Invalid;
|
public bool IsInvalid => this == Invalid;
|
||||||
|
|
||||||
public readonly override int GetHashCode()
|
public override readonly int GetHashCode()
|
||||||
{
|
{
|
||||||
return Value.GetHashCode();
|
return Value.GetHashCode();
|
||||||
}
|
}
|
||||||
@@ -220,7 +220,7 @@ public readonly struct Key128<T> : IEquatable<Key128<T>>
|
|||||||
return Value.CompareTo(other.Value);
|
return Value.CompareTo(other.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly override bool Equals(object? obj)
|
public override readonly bool Equals(object? obj)
|
||||||
{
|
{
|
||||||
return obj is Key128<T> id && Equals(id);
|
return obj is Key128<T> id && Equals(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public readonly struct Result<T>
|
|||||||
private readonly bool _isSuccess;
|
private readonly bool _isSuccess;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the value. Undefined if the result is a failure.
|
/// Gets the value. Undefined behavior if the result is a failure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public T Value
|
public T Value
|
||||||
{
|
{
|
||||||
@@ -141,7 +141,7 @@ public readonly struct Result<T, E>
|
|||||||
private readonly E _error;
|
private readonly E _error;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the value. Undefined if the result is a failure.
|
/// Gets the value. Undefined behavior if the result is a failure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public T Value
|
public T Value
|
||||||
{
|
{
|
||||||
@@ -197,7 +197,7 @@ public readonly ref struct RefResult<T, E>
|
|||||||
private readonly E _error;
|
private readonly E _error;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a reference to the value. Undefined if the result is a failure.
|
/// Gets a reference to the value. Undefined behavior if the result is a failure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ref T Value
|
public ref T Value
|
||||||
{
|
{
|
||||||
@@ -249,6 +249,12 @@ public readonly ref struct RefResult<T, E>
|
|||||||
|
|
||||||
public static class ResultExtensions
|
public static class ResultExtensions
|
||||||
{
|
{
|
||||||
|
extension(Error error)
|
||||||
|
{
|
||||||
|
public bool IsSuccess => error == Error.None;
|
||||||
|
public bool IsFailure => error != Error.None;
|
||||||
|
}
|
||||||
|
|
||||||
public static void ThrowIfFailed(this Error result, [CallerArgumentExpression(nameof(result))] string? op = null)
|
public static void ThrowIfFailed(this Error result, [CallerArgumentExpression(nameof(result))] string? op = null)
|
||||||
{
|
{
|
||||||
if (result != Error.None)
|
if (result != Error.None)
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Ghost.Core.Utilities;
|
|
||||||
|
|
||||||
public ref struct BinaryWriter
|
|
||||||
{
|
|
||||||
private readonly Span<byte> _buffer;
|
|
||||||
private int _position;
|
|
||||||
|
|
||||||
public int Position
|
|
||||||
{
|
|
||||||
readonly get => _position;
|
|
||||||
set => _position = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BinaryWriter(Span<byte> buffer)
|
|
||||||
{
|
|
||||||
_buffer = buffer;
|
|
||||||
_position = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe void Write<T>(scoped ref readonly T value)
|
|
||||||
where T : unmanaged
|
|
||||||
{
|
|
||||||
Unsafe.WriteUnaligned(ref _buffer[_position], value);
|
|
||||||
_position += sizeof(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WriteBytes(ReadOnlySpan<byte> data)
|
|
||||||
{
|
|
||||||
data.CopyTo(_buffer.Slice(_position, data.Length));
|
|
||||||
_position += data.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Span<byte> GetSpan(int length)
|
|
||||||
{
|
|
||||||
var span = _buffer.Slice(_position, length);
|
|
||||||
_position += length;
|
|
||||||
return span;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
53
src/Runtime/Ghost.Core/Utilities/BufferWriter.cs
Normal file
53
src/Runtime/Ghost.Core/Utilities/BufferWriter.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Ghost.Core.Utilities;
|
||||||
|
|
||||||
|
public struct BufferWriter : IDisposable
|
||||||
|
{
|
||||||
|
private UnsafeList<byte> _buffer;
|
||||||
|
private int _position;
|
||||||
|
|
||||||
|
public int Position
|
||||||
|
{
|
||||||
|
readonly get => _position;
|
||||||
|
set => _position = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferWriter(int initialCapacity, AllocationHandle allocationHandle)
|
||||||
|
{
|
||||||
|
_buffer = new UnsafeList<byte>(initialCapacity, allocationHandle);
|
||||||
|
_position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void Write<T>(T value)
|
||||||
|
where T : unmanaged
|
||||||
|
{
|
||||||
|
Unsafe.WriteUnaligned(ref _buffer[_position], value);
|
||||||
|
_position += sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteBytes(ReadOnlySpan<byte> data)
|
||||||
|
{
|
||||||
|
data.CopyTo(_buffer.AsSpan().Slice(_position, data.Length));
|
||||||
|
_position += data.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Span<byte> ReserveSpan(int length)
|
||||||
|
{
|
||||||
|
var span = _buffer.AsSpan().Slice(_position, length);
|
||||||
|
_position += length;
|
||||||
|
return span;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly Span<byte> AsSpan()
|
||||||
|
{
|
||||||
|
return _buffer.AsSpan();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_buffer.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Ghost.Core.Utilities;
|
namespace Ghost.Core.Utilities;
|
||||||
|
|
||||||
internal class EnumUtility
|
internal class EnumUtility
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ public static class Hash
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static ulong Hash64(ulong a, ulong b, ulong c)
|
public static ulong Hash64(ulong a, ulong b, ulong c)
|
||||||
{
|
{
|
||||||
ulong h1 = a * _PRIME1;
|
var h1 = a * _PRIME1;
|
||||||
ulong h2 = b * _PRIME2;
|
var h2 = b * _PRIME2;
|
||||||
ulong h3 = c * _PRIME3;
|
var h3 = c * _PRIME3;
|
||||||
|
|
||||||
ulong h = h1 ^ h2 ^ h3;
|
var h = h1 ^ h2 ^ h3;
|
||||||
|
|
||||||
h = (h ^ (h >> 33)) * _PRIME4;
|
h = (h ^ (h >> 33)) * _PRIME4;
|
||||||
return h ^ (h >> 29);
|
return h ^ (h >> 29);
|
||||||
@@ -31,12 +31,12 @@ public static class Hash
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static ulong Hash64(ulong a, ulong b, ulong c, ulong d)
|
public static ulong Hash64(ulong a, ulong b, ulong c, ulong d)
|
||||||
{
|
{
|
||||||
ulong h1 = a * _PRIME1;
|
var h1 = a * _PRIME1;
|
||||||
ulong h2 = b * _PRIME2;
|
var h2 = b * _PRIME2;
|
||||||
ulong h3 = c * _PRIME3;
|
var h3 = c * _PRIME3;
|
||||||
ulong h4 = d * _PRIME4;
|
var h4 = d * _PRIME4;
|
||||||
|
|
||||||
ulong h = h1 ^ h2 ^ h3 ^ h4;
|
var h = h1 ^ h2 ^ h3 ^ h4;
|
||||||
|
|
||||||
h = (h ^ (h >> 33)) * _PRIME1;
|
h = (h ^ (h >> 33)) * _PRIME1;
|
||||||
return h ^ (h >> 29);
|
return h ^ (h >> 29);
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using Misaki.HighPerformance.LowLevel;
|
using Misaki.HighPerformance.LowLevel;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ internal class EngineData
|
|||||||
{
|
{
|
||||||
public const string ENGINE_NAME = "Ghost Engine";
|
public const string ENGINE_NAME = "Ghost Engine";
|
||||||
|
|
||||||
public readonly static Version EngineVersion = new(0, 1, 0);
|
public static readonly Version EngineVersion = new(0, 1, 0);
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace Ghost.Entities;
|
namespace Ghost.Entities;
|
||||||
|
|
||||||
internal unsafe sealed class ChunkDebugView
|
internal sealed unsafe class ChunkDebugView
|
||||||
{
|
{
|
||||||
[DebuggerDisplay("{Name,nq}: {Data}")]
|
[DebuggerDisplay("{Name,nq}: {Data}")]
|
||||||
internal class ComponentArrayView
|
internal class ComponentArrayView
|
||||||
@@ -541,27 +541,27 @@ internal unsafe struct Archetype : IDisposable
|
|||||||
|
|
||||||
ref var chunk = ref _chunks[chunkIndex];
|
ref var chunk = ref _chunks[chunkIndex];
|
||||||
|
|
||||||
int oldCount = chunk._count;
|
var oldCount = chunk._count;
|
||||||
int removeCount = sortedIndicesToRemove.Length;
|
var removeCount = sortedIndicesToRemove.Length;
|
||||||
int newCount = oldCount - removeCount; // The boundary between "Keep" and "Drop"
|
var newCount = oldCount - removeCount; // The boundary between "Keep" and "Drop"
|
||||||
|
|
||||||
var chunkBase = chunk.GetUnsafePtr();
|
var chunkBase = chunk.GetUnsafePtr();
|
||||||
var world = World.GetWorldUncheck(_worldID); // Typo fixed from 'wrold'
|
var world = World.GetWorldUncheck(_worldID); // Typo fixed from 'wrold'
|
||||||
|
|
||||||
// Pointers for the swap logic
|
// Pointers for the swap logic
|
||||||
// 1. 'holePtr' tracks which index in the sorted list we are processing
|
// 1. 'holePtr' tracks which index in the sorted list we are processing
|
||||||
int holePtr = 0;
|
var holePtr = 0;
|
||||||
|
|
||||||
// 2. 'candidateIndex' starts at the end of the OLD array and moves backward
|
// 2. 'candidateIndex' starts at the end of the OLD array and moves backward
|
||||||
int candidateIndex = oldCount - 1;
|
var candidateIndex = oldCount - 1;
|
||||||
|
|
||||||
// 3. 'removalTailPtr' tracks removals at the end of the array to skip them
|
// 3. 'removalTailPtr' tracks removals at the end of the array to skip them
|
||||||
int removalTailPtr = sortedIndicesToRemove.Length - 1;
|
var removalTailPtr = sortedIndicesToRemove.Length - 1;
|
||||||
|
|
||||||
// Iterate through the holes that are strictly INSIDE the new valid range
|
// Iterate through the holes that are strictly INSIDE the new valid range
|
||||||
while (holePtr < removeCount)
|
while (holePtr < removeCount)
|
||||||
{
|
{
|
||||||
int holeIndex = sortedIndicesToRemove[holePtr];
|
var holeIndex = sortedIndicesToRemove[holePtr];
|
||||||
|
|
||||||
// If the current hole is beyond the new count, it's in the "Drop Zone".
|
// If the current hole is beyond the new count, it's in the "Drop Zone".
|
||||||
// Since the list is sorted, all subsequent holes are also in the drop zone.
|
// Since the list is sorted, all subsequent holes are also in the drop zone.
|
||||||
@@ -574,7 +574,7 @@ internal unsafe struct Archetype : IDisposable
|
|||||||
while (candidateIndex >= newCount)
|
while (candidateIndex >= newCount)
|
||||||
{
|
{
|
||||||
// Check if the current candidate is actually marked for removal
|
// Check if the current candidate is actually marked for removal
|
||||||
bool isCandidateRemoved = false;
|
var isCandidateRemoved = false;
|
||||||
|
|
||||||
// Because sortedIndices is sorted, we check the end of the list
|
// Because sortedIndices is sorted, we check the end of the list
|
||||||
// to see if the candidateIndex matches a removal request.
|
// to see if the candidateIndex matches a removal request.
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ public class ComponentManager : IDisposable
|
|||||||
_archetypes.Add(new Archetype(arcID, _world.ID, componentTypeIDs));
|
_archetypes.Add(new Archetype(arcID, _world.ID, componentTypeIDs));
|
||||||
_archetypeLookup.Add(signatureHash, arcID);
|
_archetypeLookup.Add(signatureHash, arcID);
|
||||||
|
|
||||||
for (int i = 0; i < _entityQueries.Count; i++)
|
for (var i = 0; i < _entityQueries.Count; i++)
|
||||||
{
|
{
|
||||||
ref var query = ref _entityQueries[i];
|
ref var query = ref _entityQueries[i];
|
||||||
query.AddArchetypeIfMatch(in _archetypes[arcID.Value]);
|
query.AddArchetypeIfMatch(in _archetypes[arcID.Value]);
|
||||||
|
|||||||
@@ -455,7 +455,7 @@ public unsafe partial struct EntityQuery : IDisposable
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var i = 0; i < _matchingArchetypes.Count; i++)
|
for (var i = 0; i < _matchingArchetypes.Count; i++)
|
||||||
{
|
{
|
||||||
var archetypeID = _matchingArchetypes[i];
|
var archetypeID = _matchingArchetypes[i];
|
||||||
ref var archetype = ref world.ComponentManager.GetArchetypeReference(archetypeID);
|
ref var archetype = ref world.ComponentManager.GetArchetypeReference(archetypeID);
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ public abstract class SystemGroup : ISystem
|
|||||||
foreach (var sys in systems)
|
foreach (var sys in systems)
|
||||||
{
|
{
|
||||||
var type = sys.GetType();
|
var type = sys.GetType();
|
||||||
if (!dependencies.TryGetValue(type, out HashSet<Type>? value))
|
if (!dependencies.TryGetValue(type, out var value))
|
||||||
{
|
{
|
||||||
value = [];
|
value = [];
|
||||||
dependencies[type] = value;
|
dependencies[type] = value;
|
||||||
@@ -234,7 +234,7 @@ public abstract class SystemGroup : ISystem
|
|||||||
// We loop until we have sorted everyone
|
// We loop until we have sorted everyone
|
||||||
while (sortedList.Count < systems.Count)
|
while (sortedList.Count < systems.Count)
|
||||||
{
|
{
|
||||||
bool addedAny = false;
|
var addedAny = false;
|
||||||
|
|
||||||
foreach (var sys in systems)
|
foreach (var sys in systems)
|
||||||
{
|
{
|
||||||
@@ -242,7 +242,7 @@ public abstract class SystemGroup : ISystem
|
|||||||
if (visited.Contains(type)) continue;
|
if (visited.Contains(type)) continue;
|
||||||
|
|
||||||
// Check if all dependencies for this system are already visited/sorted
|
// Check if all dependencies for this system are already visited/sorted
|
||||||
bool canRun = true;
|
var canRun = true;
|
||||||
if (dependencies.TryGetValue(type, out var deps))
|
if (dependencies.TryGetValue(type, out var deps))
|
||||||
{
|
{
|
||||||
foreach (var dep in deps)
|
foreach (var dep in deps)
|
||||||
|
|||||||
@@ -24,7 +24,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 == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -111,7 +111,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 < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -202,7 +202,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 < 3; i++)
|
for (var i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -297,7 +297,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 < 4; i++)
|
for (var i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -396,7 +396,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 < 5; i++)
|
for (var i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -499,7 +499,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 < 6; i++)
|
for (var i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -606,7 +606,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 < 7; i++)
|
for (var i = 0; i < 7; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -717,7 +717,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 < 8; i++)
|
for (var i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -808,7 +808,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 == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -896,7 +896,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 < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -988,7 +988,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 < 3; i++)
|
for (var i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -1084,7 +1084,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 < 4; i++)
|
for (var i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -1184,7 +1184,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 < 5; i++)
|
for (var i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -1288,7 +1288,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 < 6; i++)
|
for (var i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -1396,7 +1396,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 < 7; i++)
|
for (var i = 0; i < 7; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
@@ -1508,7 +1508,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 < 8; i++)
|
for (var i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (id == compTypeIDs[i])
|
if (id == compTypeIDs[i])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1168,7 +1168,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])
|
||||||
{
|
{
|
||||||
@@ -1324,7 +1324,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])
|
||||||
{
|
{
|
||||||
@@ -1507,7 +1507,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])
|
||||||
{
|
{
|
||||||
@@ -1717,7 +1717,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])
|
||||||
{
|
{
|
||||||
@@ -1954,7 +1954,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])
|
||||||
{
|
{
|
||||||
@@ -2218,7 +2218,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])
|
||||||
{
|
{
|
||||||
@@ -2509,7 +2509,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])
|
||||||
{
|
{
|
||||||
@@ -2827,7 +2827,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])
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Ghost.Core.Utilities;
|
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.LowLevel;
|
using Misaki.HighPerformance.LowLevel;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Core.Utilities;
|
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.LowLevel;
|
using Misaki.HighPerformance.LowLevel;
|
||||||
@@ -869,8 +868,11 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
IncrementCommandCount();
|
IncrementCommandCount();
|
||||||
|
|
||||||
var resource = _resourceDatabase.GetResource(argumentBuffer.AsResource());
|
var resource = _resourceDatabase.GetResource(argumentBuffer.AsResource());
|
||||||
var countResource = _resourceDatabase.GetResource(countBuffer.AsResource());
|
var countResource = _resourceDatabase.GetResource(countBuffer.AsResource());
|
||||||
|
|
||||||
|
// TODO
|
||||||
_commandList.Get()->ExecuteIndirect(null, 0,
|
_commandList.Get()->ExecuteIndirect(null, 0,
|
||||||
resource, argumentOffset, countResource, countBufferOffset);
|
resource, argumentOffset, countResource, countBufferOffset);
|
||||||
|
|
||||||
@@ -947,7 +949,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
d3d12Subresources);
|
d3d12Subresources);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyBuffer(Handle<GraphicsBuffer> dest, Handle<GraphicsBuffer> src, ulong destOffset = 0, ulong srcOffset = 0, ulong numBytes = 0)
|
public void CopyBuffer(Handle<GraphicsBuffer> dst, Handle<GraphicsBuffer> src, ulong dstOffset = 0, ulong srcOffset = 0, ulong numBytes = 0)
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
ThrowIfNotRecording();
|
ThrowIfNotRecording();
|
||||||
@@ -957,11 +959,16 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (dst == src)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IncrementCommandCount();
|
IncrementCommandCount();
|
||||||
|
|
||||||
var pDestResource = _resourceDatabase.GetResource(dest.AsResource());
|
var pDstResource = _resourceDatabase.GetResource(dst.AsResource());
|
||||||
var pSrcResource = _resourceDatabase.GetResource(src.AsResource());
|
var pSrcResource = _resourceDatabase.GetResource(src.AsResource());
|
||||||
if (pSrcResource == null || pDestResource == null)
|
if (pSrcResource == null || pDstResource == null)
|
||||||
{
|
{
|
||||||
RecordError(nameof(CopyBuffer), Error.InvalidArgument);
|
RecordError(nameof(CopyBuffer), Error.InvalidArgument);
|
||||||
return;
|
return;
|
||||||
@@ -969,14 +976,45 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
|
|
||||||
if (numBytes == 0)
|
if (numBytes == 0)
|
||||||
{
|
{
|
||||||
_commandList.Get()->CopyResource(pDestResource, pSrcResource);
|
_commandList.Get()->CopyResource(pDstResource, pSrcResource);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_commandList.Get()->CopyBufferRegion(pDestResource, destOffset, pSrcResource, srcOffset, numBytes);
|
_commandList.Get()->CopyBufferRegion(pDstResource, dstOffset, pSrcResource, srcOffset, numBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CopyTexture(Handle<Texture> dst, Handle<Texture> src)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
|
||||||
|
ThrowIfDisposed();
|
||||||
|
ThrowIfNotRecording();
|
||||||
|
#if !DEBUG
|
||||||
|
if (_lastError.Status != Error.None)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (dst == src)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IncrementCommandCount();
|
||||||
|
|
||||||
|
var pDstResource = _resourceDatabase.GetResource(dst.AsResource());
|
||||||
|
var pSrcResource = _resourceDatabase.GetResource(src.AsResource());
|
||||||
|
if (pSrcResource == null || pDstResource == null)
|
||||||
|
{
|
||||||
|
RecordError(nameof(CopyTexture), Error.InvalidArgument);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
_commandList.Get()->CopyTextureRegion(null, 0, 0, 0, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Ghost.Core.Utilities;
|
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.LowLevel;
|
using Misaki.HighPerformance.LowLevel;
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
using Ghost.Core.Utilities;
|
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Misaki.HighPerformance.LowLevel;
|
using Misaki.HighPerformance.LowLevel;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
using TerraFX.Interop.Windows;
|
|
||||||
|
|
||||||
using static TerraFX.Aliases.DXGI_Alias;
|
using static TerraFX.Aliases.DXGI_Alias;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Core.Graphics;
|
|
||||||
using Ghost.Core.Utilities;
|
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.LowLevel;
|
using Misaki.HighPerformance.LowLevel;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
@@ -504,6 +501,11 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
|||||||
private Handle<GPUResource> TrackAllocation(D3D12MA_Allocation* allocation, ResourceBarrierData barrierData, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string name, bool isTemp)
|
private Handle<GPUResource> TrackAllocation(D3D12MA_Allocation* allocation, ResourceBarrierData barrierData, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string name, bool isTemp)
|
||||||
{
|
{
|
||||||
var handle = _resourceDatabase.AddAllocation(allocation, barrierData, resourceDescriptor, desc, name);
|
var handle = _resourceDatabase.AddAllocation(allocation, barrierData, resourceDescriptor, desc, name);
|
||||||
|
if (isTemp)
|
||||||
|
{
|
||||||
|
_resourceDatabase.ReleaseResource(handle);
|
||||||
|
}
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -830,7 +832,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
|||||||
offset = 0;
|
offset = 0;
|
||||||
var handle = CreateBuffer(in bufferDesc, "TempUploadBuffer", options);
|
var handle = CreateBuffer(in bufferDesc, "TempUploadBuffer", options);
|
||||||
|
|
||||||
_resourceDatabase.ScheduleReleaseResource(handle.AsResource());
|
_resourceDatabase.ReleaseResource(handle.AsResource());
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.Collections;
|
|
||||||
using Misaki.HighPerformance.LowLevel;
|
using Misaki.HighPerformance.LowLevel;
|
||||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
@@ -279,7 +278,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ScheduleReleaseResource(Handle<GPUResource> handle)
|
public void ReleaseResource(Handle<GPUResource> handle)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
|||||||
|
|
||||||
for (var i = 0; i < _backBuffers.Count; i++)
|
for (var i = 0; i < _backBuffers.Count; i++)
|
||||||
{
|
{
|
||||||
_resourceDatabase.ScheduleReleaseResource(_backBuffers[i].AsResource());
|
_resourceDatabase.ReleaseResource(_backBuffers[i].AsResource());
|
||||||
}
|
}
|
||||||
|
|
||||||
_backBuffers.Dispose();
|
_backBuffers.Dispose();
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ public struct Color128 : IEquatable<Color128>
|
|||||||
return obj is Color128 color && Equals(color);
|
return obj is Color128 color && Equals(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly override int GetHashCode()
|
public override readonly int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashCode.Combine(r, g, b, a);
|
return HashCode.Combine(r, g, b, a);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ public interface ICommandQueue : IDisposable
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type of commands this queue can execute
|
/// Type of commands this queue can execute
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CommandQueueType Type
|
CommandQueueType Type
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
@@ -17,35 +17,35 @@ public interface ICommandQueue : IDisposable
|
|||||||
/// Submits a single command buffer for execution
|
/// Submits a single command buffer for execution
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="commandBuffer">Command buffer to submit</param>
|
/// <param name="commandBuffer">Command buffer to submit</param>
|
||||||
public void Submit(ICommandBuffer commandBuffer);
|
void Submit(ICommandBuffer commandBuffer);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Submits multiple command buffers for execution
|
/// Submits multiple command buffers for execution
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="commandBuffers">Command buffers to submit</param>
|
/// <param name="commandBuffers">Command buffers to submit</param>
|
||||||
public void Submit(params ReadOnlySpan<ICommandBuffer> commandBuffers);
|
void Submit(params ReadOnlySpan<ICommandBuffer> commandBuffers);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signals a fence with the specified Value
|
/// Signals a fence with the specified Value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">Value to signal</param>
|
/// <param name="value">Value to signal</param>
|
||||||
/// <returns>The fence Value that was signaled</returns>
|
/// <returns>The fence Value that was signaled</returns>
|
||||||
public ulong Signal(ulong value);
|
ulong Signal(ulong value);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Waits for the fence to reach the specified Value
|
/// Waits for the fence to reach the specified Value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="value">Value to wait for</param>
|
/// <param name="value">Value to wait for</param>
|
||||||
public void WaitForValue(ulong value);
|
void WaitForValue(ulong value);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the last completed fence Value
|
/// Gets the last completed fence Value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Last completed fence Value</returns>
|
/// <returns>Last completed fence Value</returns>
|
||||||
public ulong GetCompletedValue();
|
ulong GetCompletedValue();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Waits until all submitted commands have finished executing
|
/// Waits until all submitted commands have finished executing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void WaitIdle();
|
void WaitIdle();
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ public interface IRenderDevice : IDisposable
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Graphics command queue for rendering operations
|
/// Graphics command queue for rendering operations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICommandQueue GraphicsQueue
|
ICommandQueue GraphicsQueue
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ public interface IRenderDevice : IDisposable
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compute command queue for compute shader operations
|
/// Compute command queue for compute shader operations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICommandQueue ComputeQueue
|
ICommandQueue ComputeQueue
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
@@ -37,12 +37,12 @@ public interface IRenderDevice : IDisposable
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Copy command queue for data transfer operations
|
/// Copy command queue for data transfer operations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ICommandQueue CopyQueue
|
ICommandQueue CopyQueue
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FeatureSupport FeatureSupport
|
FeatureSupport FeatureSupport
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Core.Graphics;
|
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics.RHI;
|
namespace Ghost.Graphics.RHI;
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ public interface IResourceDatabase : IDisposable
|
|||||||
/// Releases the GPU resource associated with the specified handle, freeing any resources allocated to it.
|
/// Releases the GPU resource associated with the specified handle, freeing any resources allocated to it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">The handle of the resource to be removed.</param>
|
/// <param name="handle">The handle of the resource to be removed.</param>
|
||||||
void ScheduleReleaseResource(Handle<GPUResource> handle);
|
void ReleaseResource(Handle<GPUResource> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Releases the GPU resource associated with the specified handle immediately, freeing any resources allocated to it.
|
/// Releases the GPU resource associated with the specified handle immediately, freeing any resources allocated to it.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public class Camera
|
|||||||
{
|
{
|
||||||
private readonly IRenderer _renderer;
|
private readonly IRenderer _renderer;
|
||||||
|
|
||||||
|
// History buffers.
|
||||||
private Handle<Texture> _colorTexture;
|
private Handle<Texture> _colorTexture;
|
||||||
private Handle<Texture> _depthTexture;
|
private Handle<Texture> _depthTexture;
|
||||||
|
|
||||||
@@ -23,14 +24,17 @@ public class Camera
|
|||||||
/// Gets the actual width of the camera's render target in pixels. If upscaler is used, this is the width before upscaling.
|
/// Gets the actual width of the camera's render target in pixels. If upscaler is used, this is the width before upscaling.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint ActualWidth => _actualWidth;
|
public uint ActualWidth => _actualWidth;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the actual height of the camera's render target in pixels. If upscaler is used, this is the height before upscaling.
|
/// Gets the actual height of the camera's render target in pixels. If upscaler is used, this is the height before upscaling.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint ActualHeight => _actualHeight;
|
public uint ActualHeight => _actualHeight;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the virtual width of the camera's render target in pixels. If upscaler is used, this is the width after upscaling.
|
/// Gets the virtual width of the camera's render target in pixels. If upscaler is used, this is the width after upscaling.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint VirtualWidth => _virtualWidth;
|
public uint VirtualWidth => _virtualWidth;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the virtual height of the camera's render target in pixels. If upscaler is used, this is the height after upscaling.
|
/// Gets the virtual height of the camera's render target in pixels. If upscaler is used, this is the height after upscaling.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -64,8 +68,17 @@ public class Camera
|
|||||||
RenderGraph.Reset();
|
RenderGraph.Reset();
|
||||||
|
|
||||||
var view = new ViewState(_virtualWidth, _virtualHeight, _actualWidth, _actualHeight);
|
var view = new ViewState(_virtualWidth, _virtualHeight, _actualWidth, _actualHeight);
|
||||||
RenderGraph.Compile(in view);
|
var e = RenderGraph.Compile(in view);
|
||||||
RenderGraph.Execute(context.CommandBuffer);
|
if (e != Error.None)
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = RenderGraph.Execute(context.CommandBuffer);
|
||||||
|
if (e != Error.None)
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
return Error.None;
|
return Error.None;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ internal struct CBufferCache : IResourceReleasable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_cpuData.Dispose();
|
_cpuData.Dispose();
|
||||||
database.ScheduleReleaseResource(_gpuResource.AsResource());
|
database.ReleaseResource(_gpuResource.AsResource());
|
||||||
|
|
||||||
_gpuResource = Handle<GraphicsBuffer>.Invalid;
|
_gpuResource = Handle<GraphicsBuffer>.Invalid;
|
||||||
_size = 0;
|
_size = 0;
|
||||||
@@ -144,7 +144,6 @@ public struct Material : IResourceReleasable
|
|||||||
return _cBufferCache.CpuData.AsSpan(0, (int)_cBufferCache.Size);
|
return _cBufferCache.CpuData.AsSpan(0, (int)_cBufferCache.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public unsafe Error SetPropertyCache<T>(scoped ref readonly T data)
|
public unsafe Error SetPropertyCache<T>(scoped ref readonly T data)
|
||||||
where T : unmanaged
|
where T : unmanaged
|
||||||
{
|
{
|
||||||
@@ -166,7 +165,6 @@ public struct Material : IResourceReleasable
|
|||||||
return Error.None;
|
return Error.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public Error SetRawPropertyCache(ReadOnlySpan<byte> data)
|
public Error SetRawPropertyCache(ReadOnlySpan<byte> data)
|
||||||
{
|
{
|
||||||
if (data.Length != _cBufferCache.Size)
|
if (data.Length != _cBufferCache.Size)
|
||||||
@@ -200,7 +198,6 @@ public struct Material : IResourceReleasable
|
|||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public Error SetKeyword(IResourceManager manager, int keywordId, bool enabled)
|
public Error SetKeyword(IResourceManager manager, int keywordId, bool enabled)
|
||||||
{
|
{
|
||||||
var r = manager.GetShaderReference(_shader);
|
var r = manager.GetShaderReference(_shader);
|
||||||
@@ -222,7 +219,6 @@ public struct Material : IResourceReleasable
|
|||||||
return Error.None;
|
return Error.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public readonly bool IsKeywordEnabled(IResourceManager manager, int keywordId)
|
public readonly bool IsKeywordEnabled(IResourceManager manager, int keywordId)
|
||||||
{
|
{
|
||||||
var r = manager.GetShaderReference(_shader);
|
var r = manager.GetShaderReference(_shader);
|
||||||
@@ -276,8 +272,7 @@ public struct Material : IResourceReleasable
|
|||||||
cmd.ResourceBarrier(desc);
|
cmd.ResourceBarrier(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
public void ReleaseResource(IResourceDatabase database)
|
||||||
void IResourceReleasable.ReleaseResource(IResourceDatabase database)
|
|
||||||
{
|
{
|
||||||
_cBufferCache.ReleaseResource(database);
|
_cBufferCache.ReleaseResource(database);
|
||||||
_passPipelineOverride.Dispose();
|
_passPipelineOverride.Dispose();
|
||||||
|
|||||||
@@ -113,13 +113,13 @@ public struct Mesh : IResourceReleasable
|
|||||||
_indices.Dispose();
|
_indices.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly void IResourceReleasable.ReleaseResource(IResourceDatabase database)
|
public readonly void ReleaseResource(IResourceDatabase database)
|
||||||
{
|
{
|
||||||
ReleaseCpuResources();
|
ReleaseCpuResources();
|
||||||
|
|
||||||
database.ScheduleReleaseResource(VertexBuffer.AsResource());
|
database.ReleaseResource(VertexBuffer.AsResource());
|
||||||
database.ScheduleReleaseResource(IndexBuffer.AsResource());
|
database.ReleaseResource(IndexBuffer.AsResource());
|
||||||
database.ScheduleReleaseResource(ObjectDataBuffer.AsResource());
|
database.ReleaseResource(ObjectDataBuffer.AsResource());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,18 +10,21 @@ namespace Ghost.Graphics.Core;
|
|||||||
public readonly unsafe ref struct RenderingContext
|
public readonly unsafe ref struct RenderingContext
|
||||||
{
|
{
|
||||||
private readonly IGraphicsEngine _engine;
|
private readonly IGraphicsEngine _engine;
|
||||||
|
private readonly IResourceManager _resourceManager;
|
||||||
private readonly ICommandBuffer _directCmd;
|
private readonly ICommandBuffer _directCmd;
|
||||||
|
|
||||||
public ICommandBuffer DirectCommandBuffer => _directCmd;
|
public ICommandBuffer DirectCommandBuffer => _directCmd;
|
||||||
|
|
||||||
public IShaderCompiler ShaderCompiler => _engine.ShaderCompiler;
|
public IShaderCompiler ShaderCompiler => _engine.ShaderCompiler;
|
||||||
|
public IResourceManager ResourceManager => _resourceManager;
|
||||||
public IResourceAllocator ResourceAllocator => _engine.ResourceAllocator;
|
public IResourceAllocator ResourceAllocator => _engine.ResourceAllocator;
|
||||||
public IResourceDatabase ResourceDatabase => _engine.ResourceDatabase;
|
public IResourceDatabase ResourceDatabase => _engine.ResourceDatabase;
|
||||||
public IPipelineLibrary PipelineLibrary => _engine.PipelineLibrary;
|
public IPipelineLibrary PipelineLibrary => _engine.PipelineLibrary;
|
||||||
|
|
||||||
internal RenderingContext(IGraphicsEngine engine, ICommandBuffer directCmd)
|
internal RenderingContext(IGraphicsEngine engine, IResourceManager resourceManager, ICommandBuffer directCmd)
|
||||||
{
|
{
|
||||||
_engine = engine;
|
_engine = engine;
|
||||||
|
_resourceManager = resourceManager;
|
||||||
_directCmd = directCmd;
|
_directCmd = directCmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,8 +85,8 @@ public readonly unsafe ref struct RenderingContext
|
|||||||
|
|
||||||
public Handle<Mesh> CreateMesh(UnsafeList<Vertex> vertices, UnsafeList<uint> indices, bool staticMesh)
|
public Handle<Mesh> CreateMesh(UnsafeList<Vertex> vertices, UnsafeList<uint> indices, bool staticMesh)
|
||||||
{
|
{
|
||||||
var mesh = ResourceAllocator.CreateMesh(vertices, indices);
|
var mesh = _resourceManager.CreateMesh(vertices, indices);
|
||||||
var r = ResourceDatabase.GetMeshReference(mesh);
|
var r = _resourceManager.GetMeshReference(mesh);
|
||||||
if (r.IsFailure)
|
if (r.IsFailure)
|
||||||
{
|
{
|
||||||
return mesh;
|
return mesh;
|
||||||
@@ -129,7 +132,7 @@ public readonly unsafe ref struct RenderingContext
|
|||||||
/// <param name="markMeshStatic">Whether to mark the mesh as static. If it's true, the cpu buffer of the mesh will not be avaliable any more</param>
|
/// <param name="markMeshStatic">Whether to mark the mesh as static. If it's true, the cpu buffer of the mesh will not be avaliable any more</param>
|
||||||
public void UploadMesh(Handle<Mesh> mesh, bool markMeshStatic)
|
public void UploadMesh(Handle<Mesh> mesh, bool markMeshStatic)
|
||||||
{
|
{
|
||||||
var r = ResourceDatabase.GetMeshReference(mesh);
|
var r = _resourceManager.GetMeshReference(mesh);
|
||||||
if (r.IsFailure)
|
if (r.IsFailure)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -156,7 +159,7 @@ public readonly unsafe ref struct RenderingContext
|
|||||||
|
|
||||||
public void UpdateObjectData(Handle<Mesh> mesh, float4x4 localToWorld)
|
public void UpdateObjectData(Handle<Mesh> mesh, float4x4 localToWorld)
|
||||||
{
|
{
|
||||||
var r = ResourceDatabase.GetMeshReference(mesh);
|
var r = _resourceManager.GetMeshReference(mesh);
|
||||||
if (r.IsFailure)
|
if (r.IsFailure)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Ghost.Core.Graphics;
|
|||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ghost.Graphics.Core;
|
namespace Ghost.Graphics.Core;
|
||||||
@@ -136,6 +137,7 @@ public partial struct Shader : IResourceReleasable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal readonly int GetLocalKeywordIndex(int globalKeywordID)
|
internal readonly int GetLocalKeywordIndex(int globalKeywordID)
|
||||||
{
|
{
|
||||||
if (_keywordIDToLocal.TryGetValue(globalKeywordID, out var localIndex))
|
if (_keywordIDToLocal.TryGetValue(globalKeywordID, out var localIndex))
|
||||||
@@ -146,6 +148,7 @@ public partial struct Shader : IResourceReleasable
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly int GetPassIndex(Identifier<ShaderPass> passID)
|
public readonly int GetPassIndex(Identifier<ShaderPass> passID)
|
||||||
{
|
{
|
||||||
if (_passIDToLocal.TryGetValue(passID.Value, out var index))
|
if (_passIDToLocal.TryGetValue(passID.Value, out var index))
|
||||||
@@ -156,6 +159,7 @@ public partial struct Shader : IResourceReleasable
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly int GetPassIndex(string passName)
|
public readonly int GetPassIndex(string passName)
|
||||||
{
|
{
|
||||||
if (_passIDToLocal.TryGetValue(GetPassID(passName), out var index))
|
if (_passIDToLocal.TryGetValue(GetPassID(passName), out var index))
|
||||||
@@ -166,11 +170,13 @@ public partial struct Shader : IResourceReleasable
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly ref ShaderPass GetPassReference(int index)
|
public readonly ref ShaderPass GetPassReference(int index)
|
||||||
{
|
{
|
||||||
return ref _shaderPasses[index];
|
return ref _shaderPasses[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly Result<ShaderPass, Error> TryGetPass(Identifier<ShaderPass> passID, out int passIndex)
|
public readonly Result<ShaderPass, Error> TryGetPass(Identifier<ShaderPass> passID, out int passIndex)
|
||||||
{
|
{
|
||||||
if (_passIDToLocal.TryGetValue(passID.Value, out var index))
|
if (_passIDToLocal.TryGetValue(passID.Value, out var index))
|
||||||
@@ -183,7 +189,7 @@ public partial struct Shader : IResourceReleasable
|
|||||||
return _shaderPasses[index];
|
return _shaderPasses[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void IResourceReleasable.ReleaseResource(IResourceDatabase database)
|
public void ReleaseResource(IResourceDatabase database)
|
||||||
{
|
{
|
||||||
_keywordIDToLocal.Dispose();
|
_keywordIDToLocal.Dispose();
|
||||||
_shaderPasses.Dispose();
|
_shaderPasses.Dispose();
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Misaki.HighPerformance.LowLevel;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics;
|
namespace Ghost.Graphics;
|
||||||
|
|
||||||
internal unsafe class GPUResourceLeakException : Exception
|
internal unsafe class GPUResourceLeakException : Exception
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ namespace Ghost.Graphics.RenderGraphModule;
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Main render graph class that manages resource allocation and pass execution.
|
/// Main render graph class that manages resource allocation and pass execution.
|
||||||
/// Delegates complex operations to specialized components for better organization.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class RenderGraph : IDisposable
|
public sealed class RenderGraph : IDisposable
|
||||||
{
|
{
|
||||||
@@ -172,38 +171,38 @@ public sealed class RenderGraph : IDisposable
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compiles the render graph by culling unused passes and determining resource lifetimes.
|
/// Compiles the render graph by culling unused passes and determining resource lifetimes.
|
||||||
/// Delegates to RenderGraphCompiler for the actual compilation work.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Compile(in ViewState viewState)
|
public Error Compile(in ViewState viewState)
|
||||||
{
|
{
|
||||||
if (_compiled)
|
if (_compiled)
|
||||||
{
|
{
|
||||||
return;
|
return Error.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve texture sizes before computing hash
|
|
||||||
_resources.ResolveTextureSizes(in viewState);
|
_resources.ResolveTextureSizes(in viewState);
|
||||||
|
|
||||||
// Compute structural hash for caching
|
|
||||||
var graphHash = RenderGraphHasher.ComputeGraphHash(_passes, _resources);
|
var graphHash = RenderGraphHasher.ComputeGraphHash(_passes, _resources);
|
||||||
|
var error = _compiler.Compile(in viewState, graphHash, _passes, _compiledPasses, _nativePasses, _compiledBarriers);
|
||||||
|
if (error != Error.None)
|
||||||
|
{
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
// Delegate to compiler
|
|
||||||
_compiler.Compile(in viewState, graphHash, _passes, _compiledPasses, _nativePasses, _compiledBarriers);
|
|
||||||
_compiled = true;
|
_compiled = true;
|
||||||
|
return Error.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes all compiled passes using native render passes where possible.
|
/// Executes all compiled passes using native render passes where possible.
|
||||||
/// Delegates to RenderGraphExecutor for the actual execution work.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Execute(ICommandBuffer cmd)
|
public Error Execute(ICommandBuffer cmd)
|
||||||
{
|
{
|
||||||
if (!_compiled)
|
if (!_compiled)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Render graph must be compiled before execution. Call Compile(viewState) first.");
|
return Error.InvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
_executor.Execute(cmd, _compiledPasses, _nativePasses, _compiledBarriers);
|
return _executor.Execute(cmd, _compiledPasses, _nativePasses, _compiledBarriers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics.RenderGraphModule;
|
namespace Ghost.Graphics.RenderGraphModule;
|
||||||
|
|
||||||
|
|||||||
@@ -137,8 +137,8 @@ internal sealed class RenderGraphCompilationCache
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public (int hits, int misses, double hitRate) GetStatistics()
|
public (int hits, int misses, double hitRate) GetStatistics()
|
||||||
{
|
{
|
||||||
int total = CacheHits + CacheMisses;
|
var total = CacheHits + CacheMisses;
|
||||||
double hitRate = total > 0 ? (double)CacheHits / total : 0.0;
|
var hitRate = total > 0 ? (double)CacheHits / total : 0.0;
|
||||||
return (CacheHits, CacheMisses, hitRate);
|
return (CacheHits, CacheMisses, hitRate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ internal sealed class RenderGraphCompiler
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compiles the render graph by culling passes, allocating resources, and preparing barriers.
|
/// Compiles the render graph by culling passes, allocating resources, and preparing barriers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Compile(
|
public Error Compile(
|
||||||
in ViewState viewState,
|
in ViewState viewState,
|
||||||
ulong graphHash,
|
ulong graphHash,
|
||||||
List<RenderGraphPassBase> passes,
|
List<RenderGraphPassBase> passes,
|
||||||
@@ -43,6 +43,8 @@ internal sealed class RenderGraphCompiler
|
|||||||
List<NativeRenderPass> nativePasses,
|
List<NativeRenderPass> nativePasses,
|
||||||
List<CompiledBarrier> compiledBarriers)
|
List<CompiledBarrier> compiledBarriers)
|
||||||
{
|
{
|
||||||
|
Error error;
|
||||||
|
|
||||||
// Try to restore from cache
|
// Try to restore from cache
|
||||||
if (_compilationCache.TryGetCached(graphHash, out var cached))
|
if (_compilationCache.TryGetCached(graphHash, out var cached))
|
||||||
{
|
{
|
||||||
@@ -54,7 +56,11 @@ internal sealed class RenderGraphCompiler
|
|||||||
RestoreFromCache(cached, compiledPasses, passes, nativePasses, compiledBarriers);
|
RestoreFromCache(cached, compiledPasses, passes, nativePasses, compiledBarriers);
|
||||||
|
|
||||||
_aliasingManager.AssignPhysicalResources(_resources, passes.Count);
|
_aliasingManager.AssignPhysicalResources(_resources, passes.Count);
|
||||||
AllocateResources();
|
error = AllocateResources();
|
||||||
|
if (error != Error.None)
|
||||||
|
{
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
cached.viewState = viewState;
|
cached.viewState = viewState;
|
||||||
}
|
}
|
||||||
@@ -64,7 +70,7 @@ internal sealed class RenderGraphCompiler
|
|||||||
RestoreFromCache(cached, compiledPasses, passes, nativePasses, compiledBarriers);
|
RestoreFromCache(cached, compiledPasses, passes, nativePasses, compiledBarriers);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return Error.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fresh compilation needed
|
// Fresh compilation needed
|
||||||
@@ -87,16 +93,19 @@ internal sealed class RenderGraphCompiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
_aliasingManager.AssignPhysicalResources(_resources, passes.Count);
|
_aliasingManager.AssignPhysicalResources(_resources, passes.Count);
|
||||||
AllocateResources();
|
error = AllocateResources();
|
||||||
|
if (error != Error.None)
|
||||||
|
{
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
CompileBarriers(compiledPasses, compiledBarriers);
|
CompileBarriers(compiledPasses, compiledBarriers);
|
||||||
_nativePassBuilder.BuildNativeRenderPasses(compiledPasses, nativePasses, compiledBarriers);
|
_nativePassBuilder.BuildNativeRenderPasses(compiledPasses, nativePasses, compiledBarriers);
|
||||||
StoreInCache(graphHash, viewState, compiledPasses, passes, compiledBarriers);
|
StoreInCache(graphHash, viewState, compiledPasses, passes, compiledBarriers);
|
||||||
|
|
||||||
|
return Error.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Marks passes that write to imported resources as having side effects.
|
|
||||||
/// </summary>
|
|
||||||
private void MarkPassesWithSideEffects(List<RenderGraphPassBase> passes)
|
private void MarkPassesWithSideEffects(List<RenderGraphPassBase> passes)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < passes.Count; i++)
|
for (var i = 0; i < passes.Count; i++)
|
||||||
@@ -121,9 +130,6 @@ internal sealed class RenderGraphCompiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Culls unused passes based on dependency analysis.
|
|
||||||
/// </summary>
|
|
||||||
private void CullPasses(List<RenderGraphPassBase> passes)
|
private void CullPasses(List<RenderGraphPassBase> passes)
|
||||||
{
|
{
|
||||||
// Mark all passes as culled initially
|
// Mark all passes as culled initially
|
||||||
@@ -143,9 +149,6 @@ internal sealed class RenderGraphCompiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Recursively un-culls dependencies of a pass.
|
|
||||||
/// </summary>
|
|
||||||
private void UnculDependencies(RenderGraphPassBase pass, List<RenderGraphPassBase> passes)
|
private void UnculDependencies(RenderGraphPassBase pass, List<RenderGraphPassBase> passes)
|
||||||
{
|
{
|
||||||
// Un-cull producers of read resources
|
// Un-cull producers of read resources
|
||||||
@@ -180,9 +183,6 @@ internal sealed class RenderGraphCompiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Un-culls the producer of a resource.
|
|
||||||
/// </summary>
|
|
||||||
private void UnculProducer(Identifier<RGResource> resource, List<RenderGraphPassBase> passes)
|
private void UnculProducer(Identifier<RGResource> resource, List<RenderGraphPassBase> passes)
|
||||||
{
|
{
|
||||||
var res = _resources.GetResource(resource);
|
var res = _resources.GetResource(resource);
|
||||||
@@ -197,10 +197,7 @@ internal sealed class RenderGraphCompiler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private Error AllocateResources()
|
||||||
/// Allocates GPU resources for the render graph.
|
|
||||||
/// </summary>
|
|
||||||
private void AllocateResources()
|
|
||||||
{
|
{
|
||||||
if (_resourceHeap.IsValid)
|
if (_resourceHeap.IsValid)
|
||||||
{
|
{
|
||||||
@@ -211,15 +208,15 @@ internal sealed class RenderGraphCompiler
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_resourceManager.ResourceDatabase.ScheduleReleaseResource(res.backingResource);
|
_resourceManager.ResourceDatabase.ReleaseResource(res.backingResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
_resourceManager.ResourceDatabase.ScheduleReleaseResource(_resourceHeap);
|
_resourceManager.ResourceDatabase.ReleaseResource(_resourceHeap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_aliasingManager.Heap.size == 0)
|
if (_aliasingManager.Heap.size == 0)
|
||||||
{
|
{
|
||||||
return;
|
return Error.None; // No resources to allocate
|
||||||
}
|
}
|
||||||
|
|
||||||
var allocationDesc = new AllocationDesc
|
var allocationDesc = new AllocationDesc
|
||||||
@@ -231,6 +228,10 @@ internal sealed class RenderGraphCompiler
|
|||||||
};
|
};
|
||||||
|
|
||||||
_resourceHeap = _resourceManager.ResourceAllocator.Allocate(in allocationDesc, "RenderGraphResourceHeap");
|
_resourceHeap = _resourceManager.ResourceAllocator.Allocate(in allocationDesc, "RenderGraphResourceHeap");
|
||||||
|
if (_resourceHeap.IsInvalid)
|
||||||
|
{
|
||||||
|
return Error.InvalidState;
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < _resources.Resources.Count; i++)
|
for (var i = 0; i < _resources.Resources.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -263,22 +264,22 @@ internal sealed class RenderGraphCompiler
|
|||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
_compilationCache.UpdateBackingResource(i, res.backingResource);
|
if (res.backingResource.IsInvalid)
|
||||||
}
|
{
|
||||||
|
return Error.InvalidState;
|
||||||
|
}
|
||||||
|
|
||||||
|
_compilationCache.UpdateBackingResource(i, res.backingResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Error.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compiles all barriers needed for execution.
|
|
||||||
/// Delegates to RenderGraphBarriers for the actual compilation logic.
|
|
||||||
/// </summary>
|
|
||||||
private void CompileBarriers(List<RenderGraphPassBase> compiledPasses, List<CompiledBarrier> compiledBarriers)
|
private void CompileBarriers(List<RenderGraphPassBase> compiledPasses, List<CompiledBarrier> compiledBarriers)
|
||||||
{
|
{
|
||||||
RenderGraphBarriers.CompileBarriers(compiledPasses, compiledBarriers, _resources, _aliasingManager);
|
RenderGraphBarriers.CompileBarriers(compiledPasses, compiledBarriers, _resources, _aliasingManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Restores the render graph state from cached compilation results.
|
|
||||||
/// </summary>
|
|
||||||
private void RestoreFromCache(
|
private void RestoreFromCache(
|
||||||
CachedCompilation cached,
|
CachedCompilation cached,
|
||||||
List<RenderGraphPassBase> compiledPasses,
|
List<RenderGraphPassBase> compiledPasses,
|
||||||
@@ -323,9 +324,6 @@ internal sealed class RenderGraphCompiler
|
|||||||
_nativePassBuilder.BuildNativeRenderPasses(compiledPasses, nativePasses, compiledBarriers);
|
_nativePassBuilder.BuildNativeRenderPasses(compiledPasses, nativePasses, compiledBarriers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stores current compilation results in the cache.
|
|
||||||
/// </summary>
|
|
||||||
private void StoreInCache(
|
private void StoreInCache(
|
||||||
ulong graphHash,
|
ulong graphHash,
|
||||||
in ViewState viewState,
|
in ViewState viewState,
|
||||||
@@ -368,9 +366,6 @@ internal sealed class RenderGraphCompiler
|
|||||||
_compilationCache.Store(graphHash, cacheData);
|
_compilationCache.Store(graphHash, cacheData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Releases allocated GPU resources.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (_resourceHeap.IsValid)
|
if (_resourceHeap.IsValid)
|
||||||
@@ -379,11 +374,11 @@ internal sealed class RenderGraphCompiler
|
|||||||
{
|
{
|
||||||
if (!res.isImported)
|
if (!res.isImported)
|
||||||
{
|
{
|
||||||
_resourceManager.ResourceDatabase.ScheduleReleaseResource(res.backingResource);
|
_resourceManager.ResourceDatabase.ReleaseResource(res.backingResource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_resourceManager.ResourceDatabase.ScheduleReleaseResource(_resourceHeap);
|
_resourceManager.ResourceDatabase.ReleaseResource(_resourceHeap);
|
||||||
_resourceHeap = Handle<GPUResource>.Invalid;
|
_resourceHeap = Handle<GPUResource>.Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ internal sealed class RenderGraphContext : IRasterRenderContext, IComputeRenderC
|
|||||||
|
|
||||||
internal void SetRenderTargetFormats(ReadOnlySpan<TextureFormat> rtvFormats, TextureFormat dsvFormat)
|
internal void SetRenderTargetFormats(ReadOnlySpan<TextureFormat> rtvFormats, TextureFormat dsvFormat)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < RHIUtility.MAX_RENDER_TARGETS; i++)
|
for (var i = 0; i < RHIUtility.MAX_RENDER_TARGETS; i++)
|
||||||
{
|
{
|
||||||
_rtvFormats[i] = i < rtvFormats.Length ? rtvFormats[i] : TextureFormat.Unknown;
|
_rtvFormats[i] = i < rtvFormats.Length ? rtvFormats[i] : TextureFormat.Unknown;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ internal sealed class RenderGraphExecutor
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes all compiled passes using native render passes where possible.
|
/// Executes all compiled passes using native render passes where possible.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe void Execute(
|
public unsafe Error Execute(
|
||||||
ICommandBuffer cmd,
|
ICommandBuffer cmd,
|
||||||
List<RenderGraphPassBase> compiledPasses,
|
List<RenderGraphPassBase> compiledPasses,
|
||||||
List<NativeRenderPass> nativePasses,
|
List<NativeRenderPass> nativePasses,
|
||||||
@@ -53,7 +53,11 @@ internal sealed class RenderGraphExecutor
|
|||||||
for (var i = 0; i < nativePass.mergedPassIndices.Count; i++)
|
for (var i = 0; i < nativePass.mergedPassIndices.Count; i++)
|
||||||
{
|
{
|
||||||
var mergedPassIdx = nativePass.mergedPassIndices[i];
|
var mergedPassIdx = nativePass.mergedPassIndices[i];
|
||||||
ExecuteBarriersForPass(cmd, mergedPassIdx, ref barrierIndex, compiledBarriers);
|
var e = ExecuteBarriersForPass(cmd, mergedPassIdx, ref barrierIndex, compiledBarriers);
|
||||||
|
if (e != Error.None)
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin native render pass
|
// Begin native render pass
|
||||||
@@ -119,19 +123,25 @@ internal sealed class RenderGraphExecutor
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Compute pass or standalone raster pass (not merged) or Unsafe pass
|
// Compute pass or standalone raster pass (not merged) or Unsafe pass
|
||||||
ExecuteBarriersForPass(cmd, logicalPassIndex, ref barrierIndex, compiledBarriers);
|
var e = ExecuteBarriersForPass(cmd, logicalPassIndex, ref barrierIndex, compiledBarriers);
|
||||||
|
if (e != Error.None)
|
||||||
|
{
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
pass.Execute(_context);
|
pass.Execute(_context);
|
||||||
logicalPassIndex++;
|
logicalPassIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Error.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes all barriers for a specific pass.
|
/// Executes all barriers for a specific pass.
|
||||||
/// Uses pre-compiled barriers and queries before state from ResourceManager.
|
/// Uses pre-compiled barriers and queries before state from ResourceManager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private unsafe void ExecuteBarriersForPass(
|
private unsafe Error ExecuteBarriersForPass(
|
||||||
ICommandBuffer cmd,
|
ICommandBuffer cmd,
|
||||||
int passIndex,
|
int passIndex,
|
||||||
ref int barrierIndex,
|
ref int barrierIndex,
|
||||||
@@ -158,7 +168,13 @@ internal sealed class RenderGraphExecutor
|
|||||||
var resourceHandle = resource.backingResource;
|
var resourceHandle = resource.backingResource;
|
||||||
|
|
||||||
// Always query the before state from ResourceManager (single source of truth)
|
// Always query the before state from ResourceManager (single source of truth)
|
||||||
var currentState = _resourceManager.ResourceDatabase.GetResourceBarrierData(resourceHandle).GetValueOrThrow();
|
var currentStateResult = _resourceManager.ResourceDatabase.GetResourceBarrierData(resourceHandle);
|
||||||
|
if (currentStateResult.IsFailure)
|
||||||
|
{
|
||||||
|
return currentStateResult.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentState = currentStateResult.Value;
|
||||||
|
|
||||||
BarrierLayout layoutBefore;
|
BarrierLayout layoutBefore;
|
||||||
BarrierAccess accessBefore;
|
BarrierAccess accessBefore;
|
||||||
@@ -168,7 +184,13 @@ internal sealed class RenderGraphExecutor
|
|||||||
if (compiledBarrier.AliasingPredecessor.IsValid)
|
if (compiledBarrier.AliasingPredecessor.IsValid)
|
||||||
{
|
{
|
||||||
var predHandle = _resources.GetResource(compiledBarrier.AliasingPredecessor).backingResource;
|
var predHandle = _resources.GetResource(compiledBarrier.AliasingPredecessor).backingResource;
|
||||||
var predState = _resourceManager.ResourceDatabase.GetResourceBarrierData(predHandle).GetValueOrThrow();
|
var predStateResult = _resourceManager.ResourceDatabase.GetResourceBarrierData(predHandle);
|
||||||
|
if (predStateResult.IsFailure)
|
||||||
|
{
|
||||||
|
return predStateResult.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
var predState = predStateResult.Value;
|
||||||
|
|
||||||
layoutBefore = BarrierLayout.Undefined;
|
layoutBefore = BarrierLayout.Undefined;
|
||||||
accessBefore = BarrierAccess.NoAccess;
|
accessBefore = BarrierAccess.NoAccess;
|
||||||
@@ -218,5 +240,7 @@ internal sealed class RenderGraphExecutor
|
|||||||
}
|
}
|
||||||
|
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
|
return Error.None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +1,43 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Graphics.Core;
|
using Ghost.Core.Utilities;
|
||||||
using Ghost.Graphics.RHI;
|
|
||||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
|
||||||
using System.IO.Hashing;
|
using System.IO.Hashing;
|
||||||
|
|
||||||
namespace Ghost.Graphics.RenderGraphModule;
|
namespace Ghost.Graphics.RenderGraphModule;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Computes structural hashes of render graphs for compilation caching.
|
|
||||||
/// Hashes are based on graph topology and resource configurations, not runtime values.
|
|
||||||
/// </summary>
|
|
||||||
internal static class RenderGraphHasher
|
internal static class RenderGraphHasher
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes a hash of the entire render graph structure.
|
/// Computes a hash of the entire render graph structure.
|
||||||
/// Used for cache invalidation - same hash means same compilation result.
|
/// Used for cache invalidation - same hash means same compilation result.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static unsafe ulong ComputeGraphHash(List<RenderGraphPassBase> passes, RenderGraphResourceRegistry resources)
|
public static ulong ComputeGraphHash(List<RenderGraphPassBase> passes, RenderGraphResourceRegistry resources)
|
||||||
{
|
{
|
||||||
using var scope = AllocationManager.CreateStackScope();
|
using var scope = AllocationManager.CreateStackScope();
|
||||||
var bufferPool = new UnsafeList<byte>(2048, scope.AllocationHandle);
|
var writer = new BufferWriter(2048, scope.AllocationHandle);
|
||||||
var pData = (byte*)bufferPool.GetUnsafePtr();
|
|
||||||
var offset = 0;
|
|
||||||
|
|
||||||
// Hash pass count
|
// Hash pass count
|
||||||
*(int*)(pData + offset) = passes.Count;
|
writer.Write(passes.Count);
|
||||||
offset += sizeof(int);
|
|
||||||
|
|
||||||
// Hash each pass structure (excluding names)
|
// Hash each pass structure (excluding names)
|
||||||
for (var i = 0; i < passes.Count; i++)
|
for (var i = 0; i < passes.Count; i++)
|
||||||
{
|
{
|
||||||
var pass = passes[i];
|
var pass = passes[i];
|
||||||
|
|
||||||
*(RenderPassType*)(pData + offset) = pass.type;
|
writer.Write(pass.type);
|
||||||
offset += sizeof(RenderPassType);
|
writer.Write(pass.allowCulling);
|
||||||
|
writer.Write(pass.asyncCompute);
|
||||||
*(bool*)(pData + offset) = pass.allowCulling;
|
|
||||||
offset += sizeof(bool);
|
|
||||||
|
|
||||||
*(bool*)(pData + offset) = pass.asyncCompute;
|
|
||||||
offset += sizeof(bool);
|
|
||||||
|
|
||||||
// Hash depth attachment
|
// Hash depth attachment
|
||||||
offset = ComputeTextureHash(pData, offset, pass.depthAccess.id, resources);
|
ComputeTextureHash(ref writer, pass.depthAccess.id, resources);
|
||||||
|
|
||||||
pData[offset] = (byte)pass.depthAccess.accessFlags;
|
writer.Write(pass.depthAccess.accessFlags);
|
||||||
offset += sizeof(AccessFlags);
|
writer.Write(pass.maxColorIndex);
|
||||||
|
|
||||||
*(int*)(pData + offset) = pass.maxColorIndex;
|
|
||||||
offset += sizeof(int);
|
|
||||||
for (var j = 0; j <= pass.maxColorIndex; j++)
|
for (var j = 0; j <= pass.maxColorIndex; j++)
|
||||||
{
|
{
|
||||||
offset = ComputeTextureHash(pData, offset, pass.colorAccess[j].id, resources);
|
ComputeTextureHash(ref writer, pass.colorAccess[j].id, resources);
|
||||||
|
writer.Write(pass.colorAccess[j].accessFlags);
|
||||||
pData[offset] = (byte)pass.colorAccess[j].accessFlags;
|
|
||||||
offset += sizeof(AccessFlags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var j = 0; j < (int)RenderGraphResourceType.Count; j++)
|
for (var j = 0; j < (int)RenderGraphResourceType.Count; j++)
|
||||||
@@ -64,45 +46,35 @@ internal static class RenderGraphHasher
|
|||||||
var writeList = pass.resourceWrites[j];
|
var writeList = pass.resourceWrites[j];
|
||||||
var createList = pass.resourceCreates[j];
|
var createList = pass.resourceCreates[j];
|
||||||
|
|
||||||
*(int*)(pData + offset) = readList.Count;
|
writer.Write(readList.Count);
|
||||||
offset += sizeof(int);
|
|
||||||
for (var k = 0; k < readList.Count; k++)
|
for (var k = 0; k < readList.Count; k++)
|
||||||
{
|
{
|
||||||
*(int*)(pData + offset) = readList[k].Value;
|
writer.Write(readList[k].Value);
|
||||||
offset += sizeof(int);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*(int*)(pData + offset) = writeList.Count;
|
writer.Write(writeList.Count);
|
||||||
offset += sizeof(int);
|
|
||||||
for (var k = 0; k < writeList.Count; k++)
|
for (var k = 0; k < writeList.Count; k++)
|
||||||
{
|
{
|
||||||
*(int*)(pData + offset) = writeList[k].Value;
|
writer.Write(writeList[k].Value);
|
||||||
offset += sizeof(int);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*(int*)(pData + offset) = createList.Count;
|
writer.Write(createList.Count);
|
||||||
offset += sizeof(int);
|
|
||||||
for (var k = 0; k < createList.Count; k++)
|
for (var k = 0; k < createList.Count; k++)
|
||||||
{
|
{
|
||||||
*(int*)(pData + offset) = createList[k].Value;
|
writer.Write(createList[k].Value);
|
||||||
offset += sizeof(int);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*(int*)(pData + offset) = pass.randomAccess.Count;
|
writer.Write(pass.randomAccess.Count);
|
||||||
offset += sizeof(int);
|
|
||||||
for (var k = 0; k < pass.randomAccess.Count; k++)
|
for (var k = 0; k < pass.randomAccess.Count; k++)
|
||||||
{
|
{
|
||||||
*(int*)(pData + offset) = pass.randomAccess[k].Value;
|
writer.Write(pass.randomAccess[k].Value);
|
||||||
offset += sizeof(int);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*(int*)(pData + offset) = pass.GetRenderFuncHashCode();
|
writer.Write(pass.GetRenderFuncHashCode());
|
||||||
offset += sizeof(int);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var span = new Span<byte>(pData, offset);
|
return XxHash64.HashToUInt64(writer.AsSpan());
|
||||||
return XxHash64.HashToUInt64(span);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -110,68 +82,49 @@ internal static class RenderGraphHasher
|
|||||||
/// For imported textures, hashes the backing handle.
|
/// For imported textures, hashes the backing handle.
|
||||||
/// For transient textures, hashes the descriptor (respecting size mode).
|
/// For transient textures, hashes the descriptor (respecting size mode).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static unsafe int ComputeTextureHash(byte* pData, int offset, Identifier<RGTexture> texture, RenderGraphResourceRegistry resources)
|
private static void ComputeTextureHash(ref BufferWriter writer, Identifier<RGTexture> texture, RenderGraphResourceRegistry resources)
|
||||||
{
|
{
|
||||||
if (texture.IsInvalid)
|
if (texture.IsInvalid)
|
||||||
{
|
{
|
||||||
return offset;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var resource = resources.GetResource(texture.AsResource());
|
var resource = resources.GetResource(texture.AsResource());
|
||||||
|
|
||||||
// Hash imported flag
|
// Hash imported flag
|
||||||
*(pData + offset) = resource.isImported ? (byte)1 : (byte)0;
|
writer.Write(resource.isImported);
|
||||||
offset += sizeof(byte);
|
|
||||||
|
|
||||||
// For imported textures, hash the backing resource handle
|
// For imported textures, hash the backing resource handle
|
||||||
if (resource.isImported)
|
if (resource.isImported)
|
||||||
{
|
{
|
||||||
*(int*)(pData + offset) = resource.backingResource.GetHashCode();
|
writer.Write(resource.backingResource.GetHashCode());
|
||||||
offset += sizeof(int);
|
return;
|
||||||
return offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var desc = resource.rgTextureDesc;
|
var desc = resource.rgTextureDesc;
|
||||||
|
|
||||||
// Hash format (structural)
|
writer.Write(desc.format);
|
||||||
*(TextureFormat*)(pData + offset) = desc.format;
|
writer.Write(desc.sizeMode);
|
||||||
offset += sizeof(TextureFormat);
|
|
||||||
|
|
||||||
// Hash size mode (structural)
|
|
||||||
*(RGTextureSizeMode*)(pData + offset) = desc.sizeMode;
|
|
||||||
offset += sizeof(RGTextureSizeMode);
|
|
||||||
|
|
||||||
// Hash size specification based on mode
|
// Hash size specification based on mode
|
||||||
if (desc.sizeMode == RGTextureSizeMode.Absolute)
|
if (desc.sizeMode == RGTextureSizeMode.Absolute)
|
||||||
{
|
{
|
||||||
// Absolute mode: hash actual dimensions
|
// Absolute mode: hash actual dimensions
|
||||||
*(uint*)(pData + offset) = desc.width;
|
writer.Write(desc.width);
|
||||||
offset += sizeof(uint);
|
writer.Write(desc.height);
|
||||||
*(uint*)(pData + offset) = desc.height;
|
|
||||||
offset += sizeof(uint);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Relative mode: hash scale factors (NOT resolved dimensions)
|
// Relative mode: hash scale factors (NOT resolved dimensions)
|
||||||
*(float*)(pData + offset) = desc.scaleX;
|
writer.Write(desc.scaleX);
|
||||||
offset += sizeof(float);
|
writer.Write(desc.scaleY);
|
||||||
*(float*)(pData + offset) = desc.scaleY;
|
|
||||||
offset += sizeof(float);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash other structural properties
|
// Hash other structural properties
|
||||||
*(TextureDimension*)(pData + offset) = desc.dimension;
|
writer.Write(desc.dimension);
|
||||||
offset += sizeof(TextureDimension);
|
writer.Write(desc.mipLevels);
|
||||||
*(uint*)(pData + offset) = desc.mipLevels;
|
writer.Write(desc.usage);
|
||||||
offset += sizeof(uint);
|
writer.Write(desc.clearAtFirstUse);
|
||||||
*(TextureUsage*)(pData + offset) = desc.usage;
|
writer.Write(desc.discardAtLastUse);
|
||||||
offset += sizeof(TextureUsage);
|
|
||||||
|
|
||||||
*(bool*)(pData + offset) = desc.clearAtFirstUse;
|
|
||||||
offset += sizeof(bool);
|
|
||||||
*(bool*)(pData + offset) = desc.discardAtLastUse;
|
|
||||||
offset += sizeof(bool);
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Ghost.Core;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics.RenderGraphModule;
|
namespace Ghost.Graphics.RenderGraphModule;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ internal abstract class RenderGraphPassBase
|
|||||||
|
|
||||||
public RenderGraphPassBase()
|
public RenderGraphPassBase()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (int)RenderGraphResourceType.Count; i++)
|
for (var i = 0; i < (int)RenderGraphResourceType.Count; i++)
|
||||||
{
|
{
|
||||||
resourceReads[i] = new List<Identifier<RGResource>>(8);
|
resourceReads[i] = new List<Identifier<RGResource>>(8);
|
||||||
resourceWrites[i] = new List<Identifier<RGResource>>(4);
|
resourceWrites[i] = new List<Identifier<RGResource>>(4);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Graphics.Core;
|
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.Buffer;
|
using Misaki.HighPerformance.Buffer;
|
||||||
|
|
||||||
@@ -145,8 +144,8 @@ internal sealed class RenderGraphResourceRegistry
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
int count = 0;
|
var count = 0;
|
||||||
for (int i = 0; i < _resources.Count; i++)
|
for (var i = 0; i < _resources.Count; i++)
|
||||||
{
|
{
|
||||||
if (_resources[i].type == RenderGraphResourceType.Texture)
|
if (_resources[i].type == RenderGraphResourceType.Texture)
|
||||||
count++;
|
count++;
|
||||||
@@ -158,8 +157,8 @@ internal sealed class RenderGraphResourceRegistry
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
int count = 0;
|
var count = 0;
|
||||||
for (int i = 0; i < _resources.Count; i++)
|
for (var i = 0; i < _resources.Count; i++)
|
||||||
{
|
{
|
||||||
if (_resources[i].type == RenderGraphResourceType.Buffer)
|
if (_resources[i].type == RenderGraphResourceType.Buffer)
|
||||||
count++;
|
count++;
|
||||||
@@ -245,7 +244,7 @@ internal sealed class RenderGraphResourceRegistry
|
|||||||
public Identifier<RGBuffer> CreateBuffer(ref readonly BufferDesc desc, string name)
|
public Identifier<RGBuffer> CreateBuffer(ref readonly BufferDesc desc, string name)
|
||||||
{
|
{
|
||||||
var resource = _pool.Rent<RenderGraphResource>();
|
var resource = _pool.Rent<RenderGraphResource>();
|
||||||
resource.name= name;
|
resource.name = name;
|
||||||
resource.type = RenderGraphResourceType.Buffer;
|
resource.type = RenderGraphResourceType.Buffer;
|
||||||
resource.index = _resources.Count;
|
resource.index = _resources.Count;
|
||||||
resource.bufferDesc = desc;
|
resource.bufferDesc = desc;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Graphics.Core;
|
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
|||||||
@@ -107,8 +107,8 @@ internal class MeshRenderPass : IRenderPass
|
|||||||
private void CompileBlitShader(ref readonly RenderingContext ctx)
|
private void CompileBlitShader(ref readonly RenderingContext ctx)
|
||||||
{
|
{
|
||||||
var shaderDescriptor = DSLShaderCompiler.CompileShader("F:/csharp/GhostEngine/src/Runtime/Ghost.Graphics/Shaders/Blit.gshdr", "C:/Users/Misaki/Downloads/Archive").GetValueOrThrow();
|
var shaderDescriptor = DSLShaderCompiler.CompileShader("F:/csharp/GhostEngine/src/Runtime/Ghost.Graphics/Shaders/Blit.gshdr", "C:/Users/Misaki/Downloads/Archive").GetValueOrThrow();
|
||||||
_blitShader = ctx.ResourceAllocator.CreateGraphicsShader(shaderDescriptor);
|
_blitShader = ctx.ResourceManager.CreateGraphicsShader(shaderDescriptor);
|
||||||
_blitMaterial = ctx.ResourceAllocator.CreateMaterial(_blitShader);
|
_blitMaterial = ctx.ResourceManager.CreateMaterial(_blitShader);
|
||||||
|
|
||||||
var config = new ShaderCompilationConfig
|
var config = new ShaderCompilationConfig
|
||||||
{
|
{
|
||||||
@@ -132,8 +132,8 @@ internal class MeshRenderPass : IRenderPass
|
|||||||
|
|
||||||
var shaderDescriptor = DSLShaderCompiler.CompileShader("F:/csharp/GhostEngine/src/Runtime/Ghost.Graphics/test.gshdr", "C:/Users/Misaki/Downloads/Archive").GetValueOrThrow();
|
var shaderDescriptor = DSLShaderCompiler.CompileShader("F:/csharp/GhostEngine/src/Runtime/Ghost.Graphics/test.gshdr", "C:/Users/Misaki/Downloads/Archive").GetValueOrThrow();
|
||||||
|
|
||||||
_shader = ctx.ResourceAllocator.CreateGraphicsShader(shaderDescriptor);
|
_shader = ctx.ResourceManager.CreateGraphicsShader(shaderDescriptor);
|
||||||
_material = ctx.ResourceAllocator.CreateMaterial(_shader);
|
_material = ctx.ResourceManager.CreateMaterial(_shader);
|
||||||
|
|
||||||
for (var i = 0; i < shaderDescriptor.passes.Length; i++)
|
for (var i = 0; i < shaderDescriptor.passes.Length; i++)
|
||||||
{
|
{
|
||||||
@@ -320,7 +320,7 @@ internal class MeshRenderPass : IRenderPass
|
|||||||
{
|
{
|
||||||
foreach (var texture in _textures)
|
foreach (var texture in _textures)
|
||||||
{
|
{
|
||||||
resourceManager.ResourceDatabase.ScheduleReleaseResource(texture.AsResource());
|
resourceManager.ResourceDatabase.ReleaseResource(texture.AsResource());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,14 +222,13 @@ internal sealed class ResourceManager : IResourceManager, IDisposable
|
|||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
ref var mesh = ref _meshes.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
|
if (!_meshes.TryGetElementAt(handle.ID, handle.Generation, out var mesh))
|
||||||
if (!exist)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseResource(mesh);
|
|
||||||
_meshes.Remove(handle.ID, handle.Generation);
|
_meshes.Remove(handle.ID, handle.Generation);
|
||||||
|
mesh.ReleaseResource(_resourceDatabase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasMaterial(Handle<Material> handle)
|
public bool HasMaterial(Handle<Material> handle)
|
||||||
@@ -253,14 +252,14 @@ internal sealed class ResourceManager : IResourceManager, IDisposable
|
|||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
ref var material = ref _materials.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
|
var material = _materials.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
|
||||||
if (!exist)
|
if (!exist)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseResource(material);
|
|
||||||
_materials.Remove(handle.ID, handle.Generation);
|
_materials.Remove(handle.ID, handle.Generation);
|
||||||
|
material.ReleaseResource(_resourceDatabase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasShader(Identifier<Shader> id)
|
public bool HasShader(Identifier<Shader> id)
|
||||||
@@ -288,14 +287,8 @@ internal sealed class ResourceManager : IResourceManager, IDisposable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref var shader = ref _shaders[id.Value]!;
|
var shader = _shaders[id.Value];
|
||||||
ReleaseResource(shader);
|
shader.ReleaseResource(_resourceDatabase);
|
||||||
}
|
|
||||||
|
|
||||||
private void ReleaseResource<T>(T resource)
|
|
||||||
where T : IResourceReleasable
|
|
||||||
{
|
|
||||||
resource.ReleaseResource(_resourceDatabase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@@ -307,17 +300,17 @@ internal sealed class ResourceManager : IResourceManager, IDisposable
|
|||||||
|
|
||||||
foreach (var mesh in _meshes)
|
foreach (var mesh in _meshes)
|
||||||
{
|
{
|
||||||
ReleaseResource(mesh);
|
mesh.ReleaseResource(_resourceDatabase);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var material in _materials)
|
foreach (var material in _materials)
|
||||||
{
|
{
|
||||||
ReleaseResource(material);
|
material.ReleaseResource(_resourceDatabase);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var shader in _shaders)
|
foreach (var shader in _shaders)
|
||||||
{
|
{
|
||||||
ReleaseResource(shader);
|
shader.ReleaseResource(_resourceDatabase);
|
||||||
}
|
}
|
||||||
|
|
||||||
_meshes.Dispose();
|
_meshes.Dispose();
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
using BenchmarkDotNet.Running;
|
using BenchmarkDotNet.Running;
|
||||||
using Ghost.Entities.Test;
|
using Ghost.Entities.Test;
|
||||||
using Ghost.Test.Core;
|
|
||||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
|
||||||
|
|
||||||
//AllocationManager.EnableDebugLayer();
|
//AllocationManager.EnableDebugLayer();
|
||||||
//TestRunner.Run<SerializationTest>();
|
//TestRunner.Run<SerializationTest>();
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
using System.Collections.ObjectModel;
|
|
||||||
|
|
||||||
using Ghost.Graphics.Test.Models;
|
using Ghost.Graphics.Test.Models;
|
||||||
using Ghost.Graphics.Test.Services;
|
using Ghost.Graphics.Test.Services;
|
||||||
|
|
||||||
using Microsoft.UI;
|
using Microsoft.UI;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Data;
|
using Microsoft.UI.Xaml.Data;
|
||||||
using Microsoft.UI.Xaml.Media;
|
using Microsoft.UI.Xaml.Media;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
namespace Ghost.Graphics.Test.Controls;
|
namespace Ghost.Graphics.Test.Controls;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Microsoft.UI.Xaml;
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Media;
|
using Microsoft.UI.Xaml.Media;
|
||||||
using Misaki.HighPerformance.Mathematics;
|
using Misaki.HighPerformance.Mathematics;
|
||||||
using static Ghost.Graphics.D3D12.D3D12ResourceDatabase;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics.Test.Windows;
|
namespace Ghost.Graphics.Test.Windows;
|
||||||
|
|
||||||
|
|||||||
@@ -38,18 +38,18 @@ internal sealed unsafe class NvttBindingTest : ITest
|
|||||||
{
|
{
|
||||||
// ---- Test 1: Version ---------------------------------------------------
|
// ---- Test 1: Version ---------------------------------------------------
|
||||||
Console.Write("[Test 1] nvttVersion ... ");
|
Console.Write("[Test 1] nvttVersion ... ");
|
||||||
uint version = NvttGlobal.Version;
|
var version = NvttGlobal.Version;
|
||||||
Assert(version > 0, $"Expected version > 0, got {version}");
|
Assert(version > 0, $"Expected version > 0, got {version}");
|
||||||
Console.WriteLine($"OK (version = {version >> 16}.{(version >> 8) & 0xFF}.{version & 0xFF})");
|
Console.WriteLine($"OK (version = {version >> 16}.{(version >> 8) & 0xFF}.{version & 0xFF})");
|
||||||
|
|
||||||
// ---- Test 2: CUDA support query (must not crash) ----------------------
|
// ---- Test 2: CUDA support query (must not crash) ----------------------
|
||||||
Console.Write("[Test 2] IsCudaSupported ... ");
|
Console.Write("[Test 2] IsCudaSupported ... ");
|
||||||
bool cuda = NvttGlobal.IsCudaSupported;
|
var cuda = NvttGlobal.IsCudaSupported;
|
||||||
Console.WriteLine($"OK (cuda = {cuda})");
|
Console.WriteLine($"OK (cuda = {cuda})");
|
||||||
|
|
||||||
// ---- Test 3: Global message callback ----------------------------------
|
// ---- Test 3: Global message callback ----------------------------------
|
||||||
Console.Write("[Test 3] SetMessageCallback ... ");
|
Console.Write("[Test 3] SetMessageCallback ... ");
|
||||||
int callbackFired = 0;
|
var callbackFired = 0;
|
||||||
using (var token = NvttGlobal.SetMessageCallback((severity, error, msg) =>
|
using (var token = NvttGlobal.SetMessageCallback((severity, error, msg) =>
|
||||||
{
|
{
|
||||||
callbackFired++;
|
callbackFired++;
|
||||||
@@ -66,7 +66,7 @@ internal sealed unsafe class NvttBindingTest : ITest
|
|||||||
$"Image not found: '{_IMAGE_PATH}'. Edit _IMAGE_PATH before running.");
|
$"Image not found: '{_IMAGE_PATH}'. Edit _IMAGE_PATH before running.");
|
||||||
|
|
||||||
using var surface = new NvttSurfaceHandle();
|
using var surface = new NvttSurfaceHandle();
|
||||||
bool loaded = surface.Load(_IMAGE_PATH, out bool hasAlpha);
|
var loaded = surface.Load(_IMAGE_PATH, out var hasAlpha);
|
||||||
Assert(loaded, "nvttSurfaceLoad returned false");
|
Assert(loaded, "nvttSurfaceLoad returned false");
|
||||||
Assert(!surface.IsNull, "Surface is null after load");
|
Assert(!surface.IsNull, "Surface is null after load");
|
||||||
Assert(surface.Width > 0 && surface.Height > 0,
|
Assert(surface.Width > 0 && surface.Height > 0,
|
||||||
@@ -91,8 +91,8 @@ internal sealed unsafe class NvttBindingTest : ITest
|
|||||||
|
|
||||||
// ---- Test 7: CountMipmaps ---------------------------------------------
|
// ---- Test 7: CountMipmaps ---------------------------------------------
|
||||||
Console.Write("[Test 7] CountMipmaps ... ");
|
Console.Write("[Test 7] CountMipmaps ... ");
|
||||||
int mipCount = surface.CountMipmaps();
|
var mipCount = surface.CountMipmaps();
|
||||||
int expectedMax = (int)Math.Log2(Math.Max(surface.Width, surface.Height)) + 1;
|
var expectedMax = (int)Math.Log2(Math.Max(surface.Width, surface.Height)) + 1;
|
||||||
Assert(mipCount > 0 && mipCount <= expectedMax,
|
Assert(mipCount > 0 && mipCount <= expectedMax,
|
||||||
$"Unexpected mip count: {mipCount} (expected 1..{expectedMax})");
|
$"Unexpected mip count: {mipCount} (expected 1..{expectedMax})");
|
||||||
Console.WriteLine($"OK ({mipCount} levels)");
|
Console.WriteLine($"OK ({mipCount} levels)");
|
||||||
@@ -100,7 +100,7 @@ internal sealed unsafe class NvttBindingTest : ITest
|
|||||||
// ---- Test 8: In-memory BC7 compression + mip chain -------------------
|
// ---- Test 8: In-memory BC7 compression + mip chain -------------------
|
||||||
Console.Write("[Test 8] Compress BC7 in-memory ... ");
|
Console.Write("[Test 8] Compress BC7 in-memory ... ");
|
||||||
long totalBytesReceived = 0;
|
long totalBytesReceived = 0;
|
||||||
int imagesBegun = 0;
|
var imagesBegun = 0;
|
||||||
|
|
||||||
using var compOpts = new NvttCompressionOptionsHandle();
|
using var compOpts = new NvttCompressionOptionsHandle();
|
||||||
compOpts.Format = NvttFormat.NVTT_Format_BC7;
|
compOpts.Format = NvttFormat.NVTT_Format_BC7;
|
||||||
@@ -130,12 +130,12 @@ internal sealed unsafe class NvttBindingTest : ITest
|
|||||||
ctx.SetCudaAcceleration(false); // CPU only for the test
|
ctx.SetCudaAcceleration(false); // CPU only for the test
|
||||||
|
|
||||||
using var mip = surface.Clone();
|
using var mip = surface.Clone();
|
||||||
bool headerOk = ctx.OutputHeader(mip, mipCount, compOpts, outOpts);
|
var headerOk = ctx.OutputHeader(mip, mipCount, compOpts, outOpts);
|
||||||
Assert(headerOk, "OutputHeader returned false");
|
Assert(headerOk, "OutputHeader returned false");
|
||||||
|
|
||||||
for (int level = 0; level < mipCount; level++)
|
for (var level = 0; level < mipCount; level++)
|
||||||
{
|
{
|
||||||
bool compressOk = ctx.Compress(mip, face: 0, mipmap: level, compOpts, outOpts);
|
var compressOk = ctx.Compress(mip, face: 0, mipmap: level, compOpts, outOpts);
|
||||||
Assert(compressOk, $"Compress returned false at mip level {level}");
|
Assert(compressOk, $"Compress returned false at mip level {level}");
|
||||||
|
|
||||||
if (level + 1 < mipCount)
|
if (level + 1 < mipCount)
|
||||||
@@ -150,7 +150,7 @@ internal sealed unsafe class NvttBindingTest : ITest
|
|||||||
|
|
||||||
// ---- Test 9: EstimateSize consistency ---------------------------------
|
// ---- Test 9: EstimateSize consistency ---------------------------------
|
||||||
Console.Write("[Test 9] EstimateSize ... ");
|
Console.Write("[Test 9] EstimateSize ... ");
|
||||||
int estimated = ctx.EstimateSize(surface, mipCount, compOpts);
|
var estimated = ctx.EstimateSize(surface, mipCount, compOpts);
|
||||||
// Estimate can differ from actual due to header overhead; just sanity-check it's > 0.
|
// Estimate can differ from actual due to header overhead; just sanity-check it's > 0.
|
||||||
Assert(estimated > 0, $"EstimateSize returned {estimated}");
|
Assert(estimated > 0, $"EstimateSize returned {estimated}");
|
||||||
Console.WriteLine($"OK (estimated = {estimated:N0} bytes, actual = {totalBytesReceived:N0} bytes)");
|
Console.WriteLine($"OK (estimated = {estimated:N0} bytes, actual = {totalBytesReceived:N0} bytes)");
|
||||||
@@ -166,12 +166,12 @@ internal sealed unsafe class NvttBindingTest : ITest
|
|||||||
using var ctxFile = new NvttContextHandle();
|
using var ctxFile = new NvttContextHandle();
|
||||||
using var mipFile = surface.Clone();
|
using var mipFile = surface.Clone();
|
||||||
|
|
||||||
bool fileHeaderOk = ctxFile.OutputHeader(mipFile, mipCount, compOpts, outOptsFile);
|
var fileHeaderOk = ctxFile.OutputHeader(mipFile, mipCount, compOpts, outOptsFile);
|
||||||
Assert(fileHeaderOk, "File OutputHeader returned false");
|
Assert(fileHeaderOk, "File OutputHeader returned false");
|
||||||
|
|
||||||
for (int level = 0; level < mipCount; level++)
|
for (var level = 0; level < mipCount; level++)
|
||||||
{
|
{
|
||||||
bool ok = ctxFile.Compress(mipFile, face: 0, mipmap: level, compOpts, outOptsFile);
|
var ok = ctxFile.Compress(mipFile, face: 0, mipmap: level, compOpts, outOptsFile);
|
||||||
Assert(ok, $"File Compress returned false at level {level}");
|
Assert(ok, $"File Compress returned false at level {level}");
|
||||||
|
|
||||||
if (level + 1 < mipCount)
|
if (level + 1 < mipCount)
|
||||||
@@ -180,7 +180,7 @@ internal sealed unsafe class NvttBindingTest : ITest
|
|||||||
|
|
||||||
Assert(File.Exists(_outputDdsPath),
|
Assert(File.Exists(_outputDdsPath),
|
||||||
$"DDS output file was not created: {_outputDdsPath}");
|
$"DDS output file was not created: {_outputDdsPath}");
|
||||||
long fileSize = new FileInfo(_outputDdsPath).Length;
|
var fileSize = new FileInfo(_outputDdsPath).Length;
|
||||||
Assert(fileSize > 128, $"DDS file suspiciously small: {fileSize} bytes");
|
Assert(fileSize > 128, $"DDS file suspiciously small: {fileSize} bytes");
|
||||||
Console.WriteLine($"OK ({fileSize:N0} bytes → {_outputDdsPath})");
|
Console.WriteLine($"OK ({fileSize:N0} bytes → {_outputDdsPath})");
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Ghost.Test.Core;
|
|
||||||
using Ghost.MicroTest;
|
using Ghost.MicroTest;
|
||||||
|
using Ghost.Test.Core;
|
||||||
|
|
||||||
TestRunner.Run<NvttBindingTest>();
|
TestRunner.Run<NvttBindingTest>();
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Ghost.DSL.ShaderCompiler;
|
|
||||||
using Misaki.HighPerformance.Mathematics;
|
using Misaki.HighPerformance.Mathematics;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ namespace Ghost.Test.Core;
|
|||||||
|
|
||||||
public interface ITest
|
public interface ITest
|
||||||
{
|
{
|
||||||
public void Setup();
|
void Setup();
|
||||||
|
|
||||||
public void Run();
|
void Run();
|
||||||
|
|
||||||
public void Cleanup();
|
void Cleanup();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Ghost.Editor.Core.AssetHandle;
|
|
||||||
using Ghost.Data.Services;
|
|
||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
|
|
||||||
namespace Ghost.UnitTest;
|
namespace Ghost.UnitTest;
|
||||||
@@ -330,7 +328,7 @@ public class AssetDatabaseIntegrationTest
|
|||||||
var tasks = new List<Task>();
|
var tasks = new List<Task>();
|
||||||
var fileNames = new List<string>();
|
var fileNames = new List<string>();
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++)
|
for (var i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
var fileName = $"race{i}.txt";
|
var fileName = $"race{i}.txt";
|
||||||
fileNames.Add(fileName);
|
fileNames.Add(fileName);
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Ghost.Editor.Core.AssetHandle;
|
|
||||||
using Ghost.Editor.Core.AssetHandle.Importers;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace Ghost.UnitTest;
|
namespace Ghost.UnitTest;
|
||||||
|
|||||||
@@ -331,8 +331,8 @@ namespace Ghost.FMOD.Core
|
|||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct PLUGINLIST
|
public struct PLUGINLIST
|
||||||
{
|
{
|
||||||
PLUGINTYPE type;
|
private PLUGINTYPE type;
|
||||||
IntPtr description;
|
private IntPtr description;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@@ -1396,8 +1396,7 @@ namespace Ghost.FMOD.Core
|
|||||||
// System information functions.
|
// System information functions.
|
||||||
public RESULT getVersion(out uint version)
|
public RESULT getVersion(out uint version)
|
||||||
{
|
{
|
||||||
uint buildnumber;
|
return getVersion(out version, out var buildnumber);
|
||||||
return getVersion(out version, out buildnumber);
|
|
||||||
}
|
}
|
||||||
public RESULT getVersion(out uint version, out uint buildnumber)
|
public RESULT getVersion(out uint version, out uint buildnumber)
|
||||||
{
|
{
|
||||||
@@ -2189,7 +2188,7 @@ namespace Ghost.FMOD.Core
|
|||||||
/*
|
/*
|
||||||
'ChannelControl' API
|
'ChannelControl' API
|
||||||
*/
|
*/
|
||||||
interface IChannelControl
|
internal interface IChannelControl
|
||||||
{
|
{
|
||||||
RESULT getSystemObject(out System system);
|
RESULT getSystemObject(out System system);
|
||||||
|
|
||||||
@@ -3539,8 +3538,7 @@ namespace Ghost.FMOD.Core
|
|||||||
}
|
}
|
||||||
public RESULT getParameterInfo(int index, out DSP_PARAMETER_DESC desc)
|
public RESULT getParameterInfo(int index, out DSP_PARAMETER_DESC desc)
|
||||||
{
|
{
|
||||||
IntPtr descPtr;
|
var result = FMOD5_DSP_GetParameterInfo(this.handle, index, out var descPtr);
|
||||||
var result = FMOD5_DSP_GetParameterInfo(this.handle, index, out descPtr);
|
|
||||||
desc = (DSP_PARAMETER_DESC)Marshal.PtrToStructure<DSP_PARAMETER_DESC>(descPtr);
|
desc = (DSP_PARAMETER_DESC)Marshal.PtrToStructure<DSP_PARAMETER_DESC>(descPtr);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -4060,7 +4058,7 @@ namespace Ghost.FMOD.Core
|
|||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct StringWrapper
|
public struct StringWrapper
|
||||||
{
|
{
|
||||||
IntPtr nativeUtf8Ptr;
|
private IntPtr nativeUtf8Ptr;
|
||||||
|
|
||||||
public StringWrapper(IntPtr ptr)
|
public StringWrapper(IntPtr ptr)
|
||||||
{
|
{
|
||||||
@@ -4117,15 +4115,15 @@ namespace Ghost.FMOD.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class StringHelper
|
internal static class StringHelper
|
||||||
{
|
{
|
||||||
public class ThreadSafeEncoding : IDisposable
|
public class ThreadSafeEncoding : IDisposable
|
||||||
{
|
{
|
||||||
UTF8Encoding encoding = new UTF8Encoding();
|
private UTF8Encoding encoding = new UTF8Encoding();
|
||||||
byte[] encodedBuffer = new byte[128];
|
private byte[] encodedBuffer = new byte[128];
|
||||||
char[] decodedBuffer = new char[128];
|
private char[] decodedBuffer = new char[128];
|
||||||
bool inUse;
|
private bool inUse;
|
||||||
GCHandle gcHandle;
|
private GCHandle gcHandle;
|
||||||
|
|
||||||
public bool InUse()
|
public bool InUse()
|
||||||
{
|
{
|
||||||
@@ -4234,7 +4232,7 @@ namespace Ghost.FMOD.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<ThreadSafeEncoding> encoders = new List<ThreadSafeEncoding>(1);
|
private static List<ThreadSafeEncoding> encoders = new List<ThreadSafeEncoding>(1);
|
||||||
|
|
||||||
public static ThreadSafeEncoding GetFreeHelper()
|
public static ThreadSafeEncoding GetFreeHelper()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -170,13 +170,13 @@ namespace Ghost.FMOD.Studio
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is only need for loading memory and given our C# wrapper LOAD_MEMORY_POINT isn't feasible anyway
|
// This is only need for loading memory and given our C# wrapper LOAD_MEMORY_POINT isn't feasible anyway
|
||||||
enum LOAD_MEMORY_MODE : int
|
internal enum LOAD_MEMORY_MODE : int
|
||||||
{
|
{
|
||||||
LOAD_MEMORY,
|
LOAD_MEMORY,
|
||||||
LOAD_MEMORY_POINT,
|
LOAD_MEMORY_POINT,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LOAD_MEMORY_ALIGNMENT : int
|
internal enum LOAD_MEMORY_ALIGNMENT : int
|
||||||
{
|
{
|
||||||
VALUE = 32
|
VALUE = 32
|
||||||
}
|
}
|
||||||
@@ -235,7 +235,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
};
|
};
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
struct Union_IntBoolFloatString
|
internal struct Union_IntBoolFloatString
|
||||||
{
|
{
|
||||||
[FieldOffset(0)]
|
[FieldOffset(0)]
|
||||||
public int intvalue;
|
public int intvalue;
|
||||||
@@ -529,8 +529,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
using (var encoder = StringHelper.GetFreeHelper())
|
using (var encoder = StringHelper.GetFreeHelper())
|
||||||
{
|
{
|
||||||
var stringMem = Marshal.AllocHGlobal(256);
|
var stringMem = Marshal.AllocHGlobal(256);
|
||||||
var retrieved = 0;
|
var result = FMOD_Studio_System_GetParameterLabelByID(this.handle, id, labelindex, stringMem, 256, out var retrieved);
|
||||||
var result = FMOD_Studio_System_GetParameterLabelByID(this.handle, id, labelindex, stringMem, 256, out retrieved);
|
|
||||||
|
|
||||||
if (result == RESULT.ERR_TRUNCATED)
|
if (result == RESULT.ERR_TRUNCATED)
|
||||||
{
|
{
|
||||||
@@ -550,8 +549,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
}
|
}
|
||||||
public RESULT getParameterByID(PARAMETER_ID id, out float value)
|
public RESULT getParameterByID(PARAMETER_ID id, out float value)
|
||||||
{
|
{
|
||||||
float finalValue;
|
return getParameterByID(id, out value, out var finalValue);
|
||||||
return getParameterByID(id, out value, out finalValue);
|
|
||||||
}
|
}
|
||||||
public RESULT getParameterByID(PARAMETER_ID id, out float value, out float finalvalue)
|
public RESULT getParameterByID(PARAMETER_ID id, out float value, out float finalvalue)
|
||||||
{
|
{
|
||||||
@@ -574,8 +572,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
}
|
}
|
||||||
public RESULT getParameterByName(string name, out float value)
|
public RESULT getParameterByName(string name, out float value)
|
||||||
{
|
{
|
||||||
float finalValue;
|
return getParameterByName(name, out value, out var finalValue);
|
||||||
return getParameterByName(name, out value, out finalValue);
|
|
||||||
}
|
}
|
||||||
public RESULT getParameterByName(string name, out float value, out float finalvalue)
|
public RESULT getParameterByName(string name, out float value, out float finalvalue)
|
||||||
{
|
{
|
||||||
@@ -612,8 +609,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
|
|
||||||
using var encoder = StringHelper.GetFreeHelper();
|
using var encoder = StringHelper.GetFreeHelper();
|
||||||
var stringMem = Marshal.AllocHGlobal(256);
|
var stringMem = Marshal.AllocHGlobal(256);
|
||||||
var retrieved = 0;
|
var result = FMOD_Studio_System_LookupPath(this.handle, ref id, stringMem, 256, out var retrieved);
|
||||||
var result = FMOD_Studio_System_LookupPath(this.handle, ref id, stringMem, 256, out retrieved);
|
|
||||||
|
|
||||||
if (result == RESULT.ERR_TRUNCATED)
|
if (result == RESULT.ERR_TRUNCATED)
|
||||||
{
|
{
|
||||||
@@ -1014,8 +1010,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
|
|
||||||
using var encoder = StringHelper.GetFreeHelper();
|
using var encoder = StringHelper.GetFreeHelper();
|
||||||
var stringMem = Marshal.AllocHGlobal(256);
|
var stringMem = Marshal.AllocHGlobal(256);
|
||||||
var retrieved = 0;
|
var result = FMOD_Studio_EventDescription_GetParameterLabelByIndex(this.handle, index, labelindex, stringMem, 256, out var retrieved);
|
||||||
var result = FMOD_Studio_EventDescription_GetParameterLabelByIndex(this.handle, index, labelindex, stringMem, 256, out retrieved);
|
|
||||||
|
|
||||||
if (result == RESULT.ERR_TRUNCATED)
|
if (result == RESULT.ERR_TRUNCATED)
|
||||||
{
|
{
|
||||||
@@ -1038,9 +1033,8 @@ namespace Ghost.FMOD.Studio
|
|||||||
|
|
||||||
using var encoder = StringHelper.GetFreeHelper();
|
using var encoder = StringHelper.GetFreeHelper();
|
||||||
var stringMem = Marshal.AllocHGlobal(256);
|
var stringMem = Marshal.AllocHGlobal(256);
|
||||||
var retrieved = 0;
|
|
||||||
var nameBytes = encoder.byteFromStringUTF8(name);
|
var nameBytes = encoder.byteFromStringUTF8(name);
|
||||||
var result = FMOD_Studio_EventDescription_GetParameterLabelByName(this.handle, nameBytes, labelindex, stringMem, 256, out retrieved);
|
var result = FMOD_Studio_EventDescription_GetParameterLabelByName(this.handle, nameBytes, labelindex, stringMem, 256, out var retrieved);
|
||||||
|
|
||||||
if (result == RESULT.ERR_TRUNCATED)
|
if (result == RESULT.ERR_TRUNCATED)
|
||||||
{
|
{
|
||||||
@@ -1063,8 +1057,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
|
|
||||||
using var encoder = StringHelper.GetFreeHelper();
|
using var encoder = StringHelper.GetFreeHelper();
|
||||||
var stringMem = Marshal.AllocHGlobal(256);
|
var stringMem = Marshal.AllocHGlobal(256);
|
||||||
var retrieved = 0;
|
var result = FMOD_Studio_EventDescription_GetParameterLabelByID(this.handle, id, labelindex, stringMem, 256, out var retrieved);
|
||||||
var result = FMOD_Studio_EventDescription_GetParameterLabelByID(this.handle, id, labelindex, stringMem, 256, out retrieved);
|
|
||||||
|
|
||||||
if (result == RESULT.ERR_TRUNCATED)
|
if (result == RESULT.ERR_TRUNCATED)
|
||||||
{
|
{
|
||||||
@@ -1413,8 +1406,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
}
|
}
|
||||||
public RESULT getParameterByID(PARAMETER_ID id, out float value)
|
public RESULT getParameterByID(PARAMETER_ID id, out float value)
|
||||||
{
|
{
|
||||||
float finalvalue;
|
return getParameterByID(id, out value, out var finalvalue);
|
||||||
return getParameterByID(id, out value, out finalvalue);
|
|
||||||
}
|
}
|
||||||
public RESULT getParameterByID(PARAMETER_ID id, out float value, out float finalvalue)
|
public RESULT getParameterByID(PARAMETER_ID id, out float value, out float finalvalue)
|
||||||
{
|
{
|
||||||
@@ -1437,8 +1429,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
}
|
}
|
||||||
public RESULT getParameterByName(string name, out float value)
|
public RESULT getParameterByName(string name, out float value)
|
||||||
{
|
{
|
||||||
float finalValue;
|
return getParameterByName(name, out value, out var finalValue);
|
||||||
return getParameterByName(name, out value, out finalValue);
|
|
||||||
}
|
}
|
||||||
public RESULT getParameterByName(string name, out float value, out float finalvalue)
|
public RESULT getParameterByName(string name, out float value, out float finalvalue)
|
||||||
{
|
{
|
||||||
@@ -1608,8 +1599,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
|
|
||||||
using var encoder = StringHelper.GetFreeHelper();
|
using var encoder = StringHelper.GetFreeHelper();
|
||||||
var stringMem = Marshal.AllocHGlobal(256);
|
var stringMem = Marshal.AllocHGlobal(256);
|
||||||
var retrieved = 0;
|
var result = FMOD_Studio_Bus_GetPath(this.handle, stringMem, 256, out var retrieved);
|
||||||
var result = FMOD_Studio_Bus_GetPath(this.handle, stringMem, 256, out retrieved);
|
|
||||||
|
|
||||||
if (result == RESULT.ERR_TRUNCATED)
|
if (result == RESULT.ERR_TRUNCATED)
|
||||||
{
|
{
|
||||||
@@ -1628,8 +1618,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
}
|
}
|
||||||
public RESULT getVolume(out float volume)
|
public RESULT getVolume(out float volume)
|
||||||
{
|
{
|
||||||
float finalVolume;
|
return getVolume(out volume, out var finalVolume);
|
||||||
return getVolume(out volume, out finalVolume);
|
|
||||||
}
|
}
|
||||||
public RESULT getVolume(out float volume, out float finalvolume)
|
public RESULT getVolume(out float volume, out float finalvolume)
|
||||||
{
|
{
|
||||||
@@ -1762,8 +1751,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
|
|
||||||
using var encoder = StringHelper.GetFreeHelper();
|
using var encoder = StringHelper.GetFreeHelper();
|
||||||
var stringMem = Marshal.AllocHGlobal(256);
|
var stringMem = Marshal.AllocHGlobal(256);
|
||||||
var retrieved = 0;
|
var result = FMOD_Studio_VCA_GetPath(this.handle, stringMem, 256, out var retrieved);
|
||||||
var result = FMOD_Studio_VCA_GetPath(this.handle, stringMem, 256, out retrieved);
|
|
||||||
|
|
||||||
if (result == RESULT.ERR_TRUNCATED)
|
if (result == RESULT.ERR_TRUNCATED)
|
||||||
{
|
{
|
||||||
@@ -1781,8 +1769,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
}
|
}
|
||||||
public RESULT getVolume(out float volume)
|
public RESULT getVolume(out float volume)
|
||||||
{
|
{
|
||||||
float finalVolume;
|
return getVolume(out volume, out var finalVolume);
|
||||||
return getVolume(out volume, out finalVolume);
|
|
||||||
}
|
}
|
||||||
public RESULT getVolume(out float volume, out float finalvolume)
|
public RESULT getVolume(out float volume, out float finalvolume)
|
||||||
{
|
{
|
||||||
@@ -1845,8 +1832,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
|
|
||||||
using var encoder = StringHelper.GetFreeHelper();
|
using var encoder = StringHelper.GetFreeHelper();
|
||||||
var stringMem = Marshal.AllocHGlobal(256);
|
var stringMem = Marshal.AllocHGlobal(256);
|
||||||
var retrieved = 0;
|
var result = FMOD_Studio_Bank_GetPath(this.handle, stringMem, 256, out var retrieved);
|
||||||
var result = FMOD_Studio_Bank_GetPath(this.handle, stringMem, 256, out retrieved);
|
|
||||||
|
|
||||||
if (result == RESULT.ERR_TRUNCATED)
|
if (result == RESULT.ERR_TRUNCATED)
|
||||||
{
|
{
|
||||||
@@ -1895,8 +1881,7 @@ namespace Ghost.FMOD.Studio
|
|||||||
|
|
||||||
using var encoder = StringHelper.GetFreeHelper();
|
using var encoder = StringHelper.GetFreeHelper();
|
||||||
var stringMem = Marshal.AllocHGlobal(256);
|
var stringMem = Marshal.AllocHGlobal(256);
|
||||||
var retrieved = 0;
|
var result = FMOD_Studio_Bank_GetStringInfo(this.handle, index, out id, stringMem, 256, out var retrieved);
|
||||||
var result = FMOD_Studio_Bank_GetStringInfo(this.handle, index, out id, stringMem, 256, out retrieved);
|
|
||||||
|
|
||||||
if (result == RESULT.ERR_TRUNCATED)
|
if (result == RESULT.ERR_TRUNCATED)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Ghost.Zeux.MeshOptimizer;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Ghost.Zeux.MeshOptimizer;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Ghost.MeshOptimizer
|
namespace Ghost.MeshOptimizer
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Ghost.Zeux.MeshOptimizer;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Ghost.MeshOptimizer
|
namespace Ghost.MeshOptimizer
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Ghost.Zeux.MeshOptimizer;
|
|
||||||
|
|
||||||
namespace Ghost.MeshOptimizer
|
namespace Ghost.MeshOptimizer
|
||||||
{
|
{
|
||||||
public partial struct meshopt_Meshlet
|
public partial struct meshopt_Meshlet
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Ghost.Zeux.MeshOptimizer;
|
|
||||||
|
|
||||||
namespace Ghost.MeshOptimizer
|
namespace Ghost.MeshOptimizer
|
||||||
{
|
{
|
||||||
public partial struct meshopt_OverdrawStatistics
|
public partial struct meshopt_OverdrawStatistics
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Ghost.Zeux.MeshOptimizer;
|
|
||||||
|
|
||||||
namespace Ghost.MeshOptimizer
|
namespace Ghost.MeshOptimizer
|
||||||
{
|
{
|
||||||
public unsafe partial struct meshopt_Stream
|
public unsafe partial struct meshopt_Stream
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Ghost.Zeux.MeshOptimizer;
|
|
||||||
|
|
||||||
namespace Ghost.MeshOptimizer
|
namespace Ghost.MeshOptimizer
|
||||||
{
|
{
|
||||||
public partial struct meshopt_VertexCacheStatistics
|
public partial struct meshopt_VertexCacheStatistics
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Ghost.Zeux.MeshOptimizer;
|
|
||||||
|
|
||||||
namespace Ghost.MeshOptimizer
|
namespace Ghost.MeshOptimizer
|
||||||
{
|
{
|
||||||
public partial struct meshopt_VertexFetchStatistics
|
public partial struct meshopt_VertexFetchStatistics
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Ghost.Nvtt.Native
|
namespace Ghost.Nvtt.Native
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Ghost.Nvtt.Native
|
namespace Ghost.Nvtt.Native
|
||||||
|
|||||||
@@ -173,13 +173,13 @@ public sealed unsafe class NvttOutputOptionsHandle : IDisposable
|
|||||||
|
|
||||||
_outputDataDelegate = (data, size, lastChunk) =>
|
_outputDataDelegate = (data, size, lastChunk) =>
|
||||||
{
|
{
|
||||||
bool ok = outputData?.Invoke((nint)data, size) ?? true;
|
var ok = outputData?.Invoke((nint)data, size) ?? true;
|
||||||
return ok ? Ghost.Nvtt.Native.NvttBoolean.NVTT_True
|
return ok ? Ghost.Nvtt.Native.NvttBoolean.NVTT_True
|
||||||
: Ghost.Nvtt.Native.NvttBoolean.NVTT_False;
|
: Ghost.Nvtt.Native.NvttBoolean.NVTT_False;
|
||||||
};
|
};
|
||||||
|
|
||||||
nint beginPtr = Marshal.GetFunctionPointerForDelegate(_beginImageDelegate);
|
var beginPtr = Marshal.GetFunctionPointerForDelegate(_beginImageDelegate);
|
||||||
nint outputPtr = Marshal.GetFunctionPointerForDelegate(_outputDataDelegate);
|
var outputPtr = Marshal.GetFunctionPointerForDelegate(_outputDataDelegate);
|
||||||
|
|
||||||
Api.nvttSetOutputOptionsOutputHandler(
|
Api.nvttSetOutputOptionsOutputHandler(
|
||||||
_ptr,
|
_ptr,
|
||||||
@@ -193,7 +193,7 @@ public sealed unsafe class NvttOutputOptionsHandle : IDisposable
|
|||||||
var handler = _errorHandler;
|
var handler = _errorHandler;
|
||||||
_errorDelegate = error => handler?.Invoke(error);
|
_errorDelegate = error => handler?.Invoke(error);
|
||||||
|
|
||||||
nint errorPtr = Marshal.GetFunctionPointerForDelegate(_errorDelegate);
|
var errorPtr = Marshal.GetFunctionPointerForDelegate(_errorDelegate);
|
||||||
Api.nvttSetOutputOptionsErrorHandler(
|
Api.nvttSetOutputOptionsErrorHandler(
|
||||||
_ptr,
|
_ptr,
|
||||||
(delegate* unmanaged[Cdecl]<Ghost.Nvtt.Native.NvttError, void>)errorPtr);
|
(delegate* unmanaged[Cdecl]<Ghost.Nvtt.Native.NvttError, void>)errorPtr);
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
using Ghost.Nvtt.Native;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ghost.Nvtt;
|
namespace Ghost.Nvtt;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -150,8 +147,8 @@ public sealed unsafe class NvttSurfaceHandle : IDisposable
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
float* p = Api.nvttSurfaceData(_ptr);
|
var p = Api.nvttSurfaceData(_ptr);
|
||||||
int count = Width * Height * Depth * 4;
|
var count = Width * Height * Depth * 4;
|
||||||
return p == null ? Span<float>.Empty : new Span<float>(p, count);
|
return p == null ? Span<float>.Empty : new Span<float>(p, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,8 +160,8 @@ public sealed unsafe class NvttSurfaceHandle : IDisposable
|
|||||||
public Span<float> Channel(int index)
|
public Span<float> Channel(int index)
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
float* p = Api.nvttSurfaceChannel(_ptr, index);
|
var p = Api.nvttSurfaceChannel(_ptr, index);
|
||||||
int count = Width * Height * Depth;
|
var count = Width * Height * Depth;
|
||||||
return p == null ? Span<float>.Empty : new Span<float>(p, count);
|
return p == null ? Span<float>.Empty : new Span<float>(p, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +202,7 @@ public sealed unsafe class NvttSurfaceHandle : IDisposable
|
|||||||
fixed (byte* p = utf8)
|
fixed (byte* p = utf8)
|
||||||
{
|
{
|
||||||
Ghost.Nvtt.Native.NvttBoolean nvAlpha;
|
Ghost.Nvtt.Native.NvttBoolean nvAlpha;
|
||||||
bool ok = NvttInterop.ToBool(
|
var ok = NvttInterop.ToBool(
|
||||||
Api.nvttSurfaceLoad(_ptr, (sbyte*)p, &nvAlpha,
|
Api.nvttSurfaceLoad(_ptr, (sbyte*)p, &nvAlpha,
|
||||||
NvttInterop.ToNvtt(expectSigned), tc));
|
NvttInterop.ToNvtt(expectSigned), tc));
|
||||||
hasAlpha = NvttInterop.ToBool(nvAlpha);
|
hasAlpha = NvttInterop.ToBool(nvAlpha);
|
||||||
@@ -221,7 +218,7 @@ public sealed unsafe class NvttSurfaceHandle : IDisposable
|
|||||||
fixed (byte* p = data)
|
fixed (byte* p = data)
|
||||||
{
|
{
|
||||||
Ghost.Nvtt.Native.NvttBoolean nvAlpha;
|
Ghost.Nvtt.Native.NvttBoolean nvAlpha;
|
||||||
bool ok = NvttInterop.ToBool(
|
var ok = NvttInterop.ToBool(
|
||||||
Api.nvttSurfaceLoadFromMemory(_ptr, p, (ulong)data.Length,
|
Api.nvttSurfaceLoadFromMemory(_ptr, p, (ulong)data.Length,
|
||||||
&nvAlpha, NvttInterop.ToNvtt(expectSigned), tc));
|
&nvAlpha, NvttInterop.ToNvtt(expectSigned), tc));
|
||||||
hasAlpha = NvttInterop.ToBool(nvAlpha);
|
hasAlpha = NvttInterop.ToBool(nvAlpha);
|
||||||
@@ -363,7 +360,7 @@ public sealed unsafe class NvttSurfaceHandle : IDisposable
|
|||||||
NvttTimingContext* tc = null)
|
NvttTimingContext* tc = null)
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
float* color = stackalloc float[4] { r, g, b, a };
|
var color = stackalloc float[4] { r, g, b, a };
|
||||||
return NvttInterop.ToBool(
|
return NvttInterop.ToBool(
|
||||||
Api.nvttSurfaceBuildNextMipmapSolidColor(_ptr, color, tc));
|
Api.nvttSurfaceBuildNextMipmapSolidColor(_ptr, color, tc));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public sealed unsafe class NvttTimingContextHandle : IDisposable
|
|||||||
fixed (byte* p = buf)
|
fixed (byte* p = buf)
|
||||||
{
|
{
|
||||||
Api.nvttTimingContextGetRecordSafe(_ptr, index, (sbyte*)p, (nuint)buf.Length, &seconds);
|
Api.nvttTimingContextGetRecordSafe(_ptr, index, (sbyte*)p, (nuint)buf.Length, &seconds);
|
||||||
string desc = NvttInterop.FromUtf8((sbyte*)p) ?? string.Empty;
|
var desc = NvttInterop.FromUtf8((sbyte*)p) ?? string.Empty;
|
||||||
return (desc, seconds);
|
return (desc, seconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user