Refactor and enhance codebase for maintainability
Refactored and reorganized the codebase to improve readability, performance, and maintainability. Introduced new interfaces and structs for better resource management, updated project configuration files, and refactored shader and graphics pipeline management. Improved error handling, code formatting, and removed unused code and namespaces. Updated DLL references and method signatures for consistency and maintainability.
This commit is contained in:
6
Ghost.Core/Contracts/InternalRelease.cs
Normal file
6
Ghost.Core/Contracts/InternalRelease.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Ghost.Core.Contracts;
|
||||||
|
|
||||||
|
internal interface IReleasable
|
||||||
|
{
|
||||||
|
void InternalRelease();
|
||||||
|
}
|
||||||
@@ -7,7 +7,18 @@
|
|||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<IsAotCompatible>True</IsAotCompatible>
|
||||||
|
<DefineConstants>$(DefineConstants);PLATEFORME_WIN64</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<IsAotCompatible>True</IsAotCompatible>
|
||||||
|
<DefineConstants>$(DefineConstants);PLATEFORME_WIN64</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="System.IO.Hashing" Version="9.0.10" />
|
||||||
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.26100.2" />
|
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.26100.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -17,9 +28,5 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Contracts\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
namespace Ghost.Core.Graphics;
|
namespace Ghost.Core.Graphics;
|
||||||
|
|
||||||
public enum KeywordType
|
public enum KeywordType
|
||||||
{
|
{
|
||||||
Static,
|
Static,
|
||||||
@@ -20,6 +21,8 @@ public struct ShaderEntryPoint
|
|||||||
{
|
{
|
||||||
public string entry;
|
public string entry;
|
||||||
public string shader;
|
public string shader;
|
||||||
|
|
||||||
|
public readonly bool IsCreated => !string.IsNullOrEmpty(entry) && !string.IsNullOrEmpty(shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct KeywordsGroup
|
public struct KeywordsGroup
|
||||||
@@ -52,27 +55,11 @@ public interface IPassDescriptor
|
|||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public class FullPassDescriptor : IPassDescriptor
|
public string Name
|
||||||
{
|
{
|
||||||
public string uniqueIdentifier = string.Empty;
|
get;
|
||||||
public ShaderEntryPoint vertexShader;
|
}
|
||||||
public ShaderEntryPoint pixelShader;
|
|
||||||
public List<string>? defines;
|
|
||||||
public List<string>? includes;
|
|
||||||
public List<KeywordsGroup>? keywords;
|
|
||||||
public List<PropertyDescriptor>? properties;
|
|
||||||
public PipelineDescriptor localPipeline;
|
|
||||||
|
|
||||||
public string Identifier => uniqueIdentifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FallbackPassDescriptor : IPassDescriptor
|
|
||||||
{
|
|
||||||
public string fallbackPassIdentifier = string.Empty;
|
|
||||||
|
|
||||||
public string Identifier => fallbackPassIdentifier;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct PropertyDescriptor
|
public struct PropertyDescriptor
|
||||||
@@ -82,6 +69,33 @@ public struct PropertyDescriptor
|
|||||||
public object? defaultValue;
|
public object? defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class FullPassDescriptor : IPassDescriptor
|
||||||
|
{
|
||||||
|
public string uniqueIdentifier = string.Empty;
|
||||||
|
public string name = string.Empty;
|
||||||
|
|
||||||
|
public ShaderEntryPoint taskShader;
|
||||||
|
public ShaderEntryPoint meshShader;
|
||||||
|
public ShaderEntryPoint pixelShader;
|
||||||
|
public List<string>? defines;
|
||||||
|
public List<string>? includes;
|
||||||
|
public List<KeywordsGroup>? keywords;
|
||||||
|
public List<PropertyDescriptor>? properties;
|
||||||
|
public PipelineDescriptor localPipeline;
|
||||||
|
|
||||||
|
public string Identifier => uniqueIdentifier;
|
||||||
|
public string Name => name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FallbackPassDescriptor : IPassDescriptor
|
||||||
|
{
|
||||||
|
public string fallbackPassIdentifier = string.Empty;
|
||||||
|
public string name = string.Empty;
|
||||||
|
|
||||||
|
public string Identifier => fallbackPassIdentifier;
|
||||||
|
public string Name => name;
|
||||||
|
}
|
||||||
|
|
||||||
public class ShaderDescriptor
|
public class ShaderDescriptor
|
||||||
{
|
{
|
||||||
public string name = string.Empty;
|
public string name = string.Empty;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ public readonly struct Handle<T>
|
|||||||
where T : IHandleType
|
where T : IHandleType
|
||||||
{
|
{
|
||||||
public readonly int id;
|
public readonly int id;
|
||||||
|
|
||||||
public readonly int generation;
|
public readonly int generation;
|
||||||
|
|
||||||
public Handle(int id, int generation)
|
public Handle(int id, int generation)
|
||||||
@@ -22,7 +21,7 @@ public readonly struct Handle<T>
|
|||||||
|
|
||||||
public readonly override int GetHashCode()
|
public readonly override int GetHashCode()
|
||||||
{
|
{
|
||||||
return id.GetHashCode();
|
return id + (generation << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly override bool Equals(object? obj)
|
public readonly override bool Equals(object? obj)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public enum LogLevel
|
|||||||
Error
|
Error
|
||||||
}
|
}
|
||||||
|
|
||||||
internal struct LogMessage
|
internal readonly struct LogMessage
|
||||||
{
|
{
|
||||||
public LogLevel Level
|
public LogLevel Level
|
||||||
{
|
{
|
||||||
@@ -58,10 +58,9 @@ internal interface ILogger
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Log(string message, LogLevel level);
|
public void Log(string message, LogLevel level);
|
||||||
|
|
||||||
public void Log(Exception exception);
|
public void Log(Exception exception);
|
||||||
|
|
||||||
public void Assert(bool condition, string message);
|
public void Assert(bool condition, string message);
|
||||||
|
public void Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add file logging.
|
// TODO: Add file logging.
|
||||||
@@ -98,6 +97,14 @@ internal class LoggerImplementation : ILogger
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_logs.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Logger
|
public static class Logger
|
||||||
@@ -149,4 +156,14 @@ public static class Logger
|
|||||||
{
|
{
|
||||||
s_logger.Log(ex);
|
s_logger.Log(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Assert(bool condition, string message)
|
||||||
|
{
|
||||||
|
s_logger.Assert(condition, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Clear()
|
||||||
|
{
|
||||||
|
s_logger.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -17,20 +17,14 @@ public readonly struct Result
|
|||||||
return new Result(true);
|
return new Result(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Result Failure(string? message)
|
public static Result Fail(string? message)
|
||||||
{
|
{
|
||||||
return new Result(false, message);
|
return new Result(false, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ThrowIfFailed()
|
|
||||||
{
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Operation failed: {message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString() => success ? "OK" : $"Error: {message}";
|
public override string ToString() => success ? "OK" : $"Error: {message}";
|
||||||
|
|
||||||
|
public static implicit operator Result(bool success) => success ? Success() : Fail(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly struct Result<T>
|
public readonly struct Result<T>
|
||||||
@@ -52,18 +46,33 @@ public readonly struct Result<T>
|
|||||||
return new Result<T>(true, data);
|
return new Result<T>(true, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Result<T> Failure(string? message)
|
public static Result<T> Fail(string? message)
|
||||||
{
|
{
|
||||||
return new Result<T>(false, default!, message);
|
return new Result<T>(false, default!, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ThrowIfFailed()
|
public override string ToString() => success ? $"OK: {value}" : $"Error: {message}";
|
||||||
|
|
||||||
|
public static implicit operator Result<T>(T? data) => data is not null ? Success(data) : Fail(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ResultExtensions
|
||||||
|
{
|
||||||
|
public static void ThrowIfFailed(this Result result)
|
||||||
{
|
{
|
||||||
if (!success)
|
if (!result.success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Operation failed: {message}");
|
throw new InvalidOperationException($"Operation failed: {result.message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => success ? $"OK: {value}" : $"Error: {message}";
|
public static T GetValueOrThrow<T>(this Result<T> result)
|
||||||
}
|
{
|
||||||
|
if (!result.success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Operation failed: {result.message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Ghost.Core/Utilities/InternalResource.cs
Normal file
12
Ghost.Core/Utilities/InternalResource.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using Ghost.Core.Contracts;
|
||||||
|
|
||||||
|
namespace Ghost.Core.Utilities;
|
||||||
|
|
||||||
|
internal static class InternalResource
|
||||||
|
{
|
||||||
|
public static void Release<T>(ref T? resource)
|
||||||
|
where T : IReleasable
|
||||||
|
{
|
||||||
|
resource?.InternalRelease();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,22 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.Versioning;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
namespace Ghost.Graphics.D3D12.Utilities;
|
namespace Ghost.Core.Utilities;
|
||||||
|
|
||||||
|
#if PLATEFORME_WIN64
|
||||||
|
[SupportedOSPlatform("windows10.0.19041.0")]
|
||||||
internal unsafe static class Win32Utility
|
internal unsafe static class Win32Utility
|
||||||
{
|
{
|
||||||
|
public static Guid* IID_NULL => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID.IID_NULL));
|
||||||
|
|
||||||
|
[Conditional("DEBUG")]
|
||||||
|
public static void Assert(this HRESULT hr)
|
||||||
|
{
|
||||||
|
Debug.Assert(hr.SUCCEEDED);
|
||||||
|
}
|
||||||
|
|
||||||
public static void ThrowIfFailed(this HRESULT hr)
|
public static void ThrowIfFailed(this HRESULT hr)
|
||||||
{
|
{
|
||||||
Windows.ThrowIfFailed(hr);
|
Windows.ThrowIfFailed(hr);
|
||||||
@@ -22,11 +34,11 @@ internal unsafe static class Win32Utility
|
|||||||
return (void**)comPtr.ReleaseAndGetAddressOf();
|
return (void**)comPtr.ReleaseAndGetAddressOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ComPtr<T> Move<T>(this ComPtr<T> comPtr)
|
public static ComPtr<T> Move<T>(ref this ComPtr<T> comPtr)
|
||||||
where T : unmanaged, IUnknown.Interface
|
where T : unmanaged, IUnknown.Interface
|
||||||
{
|
{
|
||||||
ComPtr<T> copy = default;
|
var copy = default(ComPtr<T>);
|
||||||
Unsafe.AsRef(in comPtr).Swap(ref copy);
|
comPtr.Swap(ref copy);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,4 +47,5 @@ internal unsafe static class Win32Utility
|
|||||||
{
|
{
|
||||||
return (flags & Unsafe.As<T, uint>(ref flag)) != 0;
|
return (flags & Unsafe.As<T, uint>(ref flag)) != 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
@@ -75,29 +75,29 @@ internal partial class ProjectService
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(projectDirectory) || !Directory.Exists(projectDirectory))
|
if (string.IsNullOrWhiteSpace(projectDirectory) || !Directory.Exists(projectDirectory))
|
||||||
{
|
{
|
||||||
return Result<ProjectMetadataInfo>.Failure("Project directory is invalid or does not exist.");
|
return Result<ProjectMetadataInfo>.Fail("Project directory is invalid or does not exist.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var projectAssetsPath = Path.Combine(projectDirectory, ASSETS_FOLDER);
|
var projectAssetsPath = Path.Combine(projectDirectory, ASSETS_FOLDER);
|
||||||
var projectConfigPath = Path.Combine(projectDirectory, CONFIG_FOLDER);
|
var projectConfigPath = Path.Combine(projectDirectory, CONFIG_FOLDER);
|
||||||
if (!Directory.Exists(projectAssetsPath) || !Directory.Exists(projectConfigPath))
|
if (!Directory.Exists(projectAssetsPath) || !Directory.Exists(projectConfigPath))
|
||||||
{
|
{
|
||||||
return Result<ProjectMetadataInfo>.Failure("Project folder structure is invalid.");
|
return Result<ProjectMetadataInfo>.Fail("Project folder structure is invalid.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var metadataPath = Directory.GetFiles(projectDirectory, $"*.{ProjectMetadata.PROJECT_EXTENSION}", SearchOption.TopDirectoryOnly).FirstOrDefault();
|
var metadataPath = Directory.GetFiles(projectDirectory, $"*.{ProjectMetadata.PROJECT_EXTENSION}", SearchOption.TopDirectoryOnly).FirstOrDefault();
|
||||||
if (string.IsNullOrWhiteSpace(metadataPath) || !File.Exists(metadataPath))
|
if (string.IsNullOrWhiteSpace(metadataPath) || !File.Exists(metadataPath))
|
||||||
{
|
{
|
||||||
return Result<ProjectMetadataInfo>.Failure("Project metadata file not found.");
|
return Result<ProjectMetadataInfo>.Fail("Project metadata file not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var metadata = await LoadMetadataAsync(metadataPath);
|
var metadata = await LoadMetadataAsync(metadataPath);
|
||||||
if (metadata == null)
|
if (metadata == null)
|
||||||
{
|
{
|
||||||
return Result<ProjectMetadataInfo>.Failure("Project metadata file is corrupted or invalid.");
|
return Result<ProjectMetadataInfo>.Fail("Project metadata file is corrupted or invalid.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result<ProjectMetadataInfo>.Success(new(metadataPath, metadata));
|
return new ProjectMetadataInfo(metadataPath, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async ValueTask SetupRequestFolderAsync(string projectDirectory, string templateDirectory)
|
private static async ValueTask SetupRequestFolderAsync(string projectDirectory, string templateDirectory)
|
||||||
@@ -201,7 +201,7 @@ internal partial class ProjectService
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
return Result<ProjectMetadataInfo>.Failure($"Failed to create project: {e.Message}");
|
return Result<ProjectMetadataInfo>.Fail($"Failed to create project: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ internal partial class ProjectService
|
|||||||
|
|
||||||
if (await HasProjectAsync(result.value.Path))
|
if (await HasProjectAsync(result.value.Path))
|
||||||
{
|
{
|
||||||
return Result<ProjectMetadataInfo>.Failure("Project already exists.");
|
return Result<ProjectMetadataInfo>.Fail("Project already exists.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await AddProjectAsync(result.value.Metadata.Name, result.value.Path);
|
await AddProjectAsync(result.value.Metadata.Name, result.value.Path);
|
||||||
|
|||||||
@@ -36,12 +36,12 @@ public static partial class AssetDatabase
|
|||||||
{
|
{
|
||||||
if (Directory.Exists(assetPath))
|
if (Directory.Exists(assetPath))
|
||||||
{
|
{
|
||||||
return Result<string>.Failure("Folder does not have meta data");
|
return Result<string>.Fail("Folder does not have meta data");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Path.GetExtension(assetPath).Equals(".meta", StringComparison.OrdinalIgnoreCase))
|
if (Path.GetExtension(assetPath).Equals(".meta", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
return Result<string>.Failure("Asset path cannot be a meta file");
|
return Result<string>.Fail("Asset path cannot be a meta file");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result<string>.Success(assetPath + ".meta");
|
return Result<string>.Success(assetPath + ".meta");
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Ghost.Editor.Core.AssetHandle;
|
|||||||
using Ghost.Editor.View.Windows;
|
using Ghost.Editor.View.Windows;
|
||||||
using Ghost.Engine;
|
using Ghost.Engine;
|
||||||
using Ghost.Engine.Services;
|
using Ghost.Engine.Services;
|
||||||
using Ghost.Graphics;
|
|
||||||
using Microsoft.UI.Xaml.Media;
|
using Microsoft.UI.Xaml.Media;
|
||||||
|
|
||||||
namespace Ghost.Editor.Core.AppState;
|
namespace Ghost.Editor.Core.AppState;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ghost.Editor.Controls.Internal;
|
using Ghost.Editor.Controls.Internal;
|
||||||
using Ghost.Graphics;
|
|
||||||
using Ghost.Graphics.Contracts;
|
using Ghost.Graphics.Contracts;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Ghost.Engine.Models;
|
using Ghost.Engine.Models;
|
||||||
using Ghost.Engine.Services;
|
using Ghost.Engine.Services;
|
||||||
using Ghost.Graphics;
|
|
||||||
|
|
||||||
namespace Ghost.Engine;
|
namespace Ghost.Engine;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Entities.Components;
|
|
||||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
namespace Ghost.Entities;
|
namespace Ghost.Entities;
|
||||||
|
|
||||||
public delegate void ForEach<T0>(ref T0 t0Component);
|
public delegate void ForEach<T0>(ref T0 t0Component);
|
||||||
public delegate void ForEach<T0, T1>(ref T0 t0Component,ref T1 t1Component);
|
public delegate void ForEach<T0, T1>(ref T0 t0Component, ref T1 t1Component);
|
||||||
public delegate void ForEach<T0, T1, T2>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component);
|
public delegate void ForEach<T0, T1, T2>(ref T0 t0Component, ref T1 t1Component, ref T2 t2Component);
|
||||||
public delegate void ForEach<T0, T1, T2, T3>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component);
|
public delegate void ForEach<T0, T1, T2, T3>(ref T0 t0Component, ref T1 t1Component, ref T2 t2Component, ref T3 t3Component);
|
||||||
public delegate void ForEach<T0, T1, T2, T3, T4>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component);
|
public delegate void ForEach<T0, T1, T2, T3, T4>(ref T0 t0Component, ref T1 t1Component, ref T2 t2Component, ref T3 t3Component, ref T4 t4Component);
|
||||||
public delegate void ForEach<T0, T1, T2, T3, T4, T5>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component);
|
public delegate void ForEach<T0, T1, T2, T3, T4, T5>(ref T0 t0Component, ref T1 t1Component, ref T2 t2Component, ref T3 t3Component, ref T4 t4Component, ref T5 t5Component);
|
||||||
public delegate void ForEach<T0, T1, T2, T3, T4, T5, T6>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component);
|
public delegate void ForEach<T0, T1, T2, T3, T4, T5, T6>(ref T0 t0Component, ref T1 t1Component, ref T2 t2Component, ref T3 t3Component, ref T4 t4Component, ref T5 t5Component, ref T6 t6Component);
|
||||||
public delegate void ForEach<T0, T1, T2, T3, T4, T5, T6, T7>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component);
|
public delegate void ForEach<T0, T1, T2, T3, T4, T5, T6, T7>(ref T0 t0Component, ref T1 t1Component, ref T2 t2Component, ref T3 t3Component, ref T4 t4Component, ref T5 t5Component, ref T6 t6Component, ref T7 t7Component);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@ public readonly struct QueryItem<T0>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new (ref _pool0.GetRef(_entity));
|
c0 = new(ref _pool0.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,8 +54,8 @@ public readonly struct QueryItem<T0, T1>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new (ref _pool0.GetRef(_entity));
|
c0 = new(ref _pool0.GetRef(_entity));
|
||||||
c1 = new (ref _pool1.GetRef(_entity));
|
c1 = new(ref _pool1.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,9 +86,9 @@ public readonly struct QueryItem<T0, T1, T2>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new (ref _pool0.GetRef(_entity));
|
c0 = new(ref _pool0.GetRef(_entity));
|
||||||
c1 = new (ref _pool1.GetRef(_entity));
|
c1 = new(ref _pool1.GetRef(_entity));
|
||||||
c2 = new (ref _pool2.GetRef(_entity));
|
c2 = new(ref _pool2.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,10 +122,10 @@ public readonly struct QueryItem<T0, T1, T2, T3>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new (ref _pool0.GetRef(_entity));
|
c0 = new(ref _pool0.GetRef(_entity));
|
||||||
c1 = new (ref _pool1.GetRef(_entity));
|
c1 = new(ref _pool1.GetRef(_entity));
|
||||||
c2 = new (ref _pool2.GetRef(_entity));
|
c2 = new(ref _pool2.GetRef(_entity));
|
||||||
c3 = new (ref _pool3.GetRef(_entity));
|
c3 = new(ref _pool3.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,11 +162,11 @@ public readonly struct QueryItem<T0, T1, T2, T3, T4>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new (ref _pool0.GetRef(_entity));
|
c0 = new(ref _pool0.GetRef(_entity));
|
||||||
c1 = new (ref _pool1.GetRef(_entity));
|
c1 = new(ref _pool1.GetRef(_entity));
|
||||||
c2 = new (ref _pool2.GetRef(_entity));
|
c2 = new(ref _pool2.GetRef(_entity));
|
||||||
c3 = new (ref _pool3.GetRef(_entity));
|
c3 = new(ref _pool3.GetRef(_entity));
|
||||||
c4 = new (ref _pool4.GetRef(_entity));
|
c4 = new(ref _pool4.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,12 +206,12 @@ public readonly struct QueryItem<T0, T1, T2, T3, T4, T5>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new (ref _pool0.GetRef(_entity));
|
c0 = new(ref _pool0.GetRef(_entity));
|
||||||
c1 = new (ref _pool1.GetRef(_entity));
|
c1 = new(ref _pool1.GetRef(_entity));
|
||||||
c2 = new (ref _pool2.GetRef(_entity));
|
c2 = new(ref _pool2.GetRef(_entity));
|
||||||
c3 = new (ref _pool3.GetRef(_entity));
|
c3 = new(ref _pool3.GetRef(_entity));
|
||||||
c4 = new (ref _pool4.GetRef(_entity));
|
c4 = new(ref _pool4.GetRef(_entity));
|
||||||
c5 = new (ref _pool5.GetRef(_entity));
|
c5 = new(ref _pool5.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,13 +254,13 @@ public readonly struct QueryItem<T0, T1, T2, T3, T4, T5, T6>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new (ref _pool0.GetRef(_entity));
|
c0 = new(ref _pool0.GetRef(_entity));
|
||||||
c1 = new (ref _pool1.GetRef(_entity));
|
c1 = new(ref _pool1.GetRef(_entity));
|
||||||
c2 = new (ref _pool2.GetRef(_entity));
|
c2 = new(ref _pool2.GetRef(_entity));
|
||||||
c3 = new (ref _pool3.GetRef(_entity));
|
c3 = new(ref _pool3.GetRef(_entity));
|
||||||
c4 = new (ref _pool4.GetRef(_entity));
|
c4 = new(ref _pool4.GetRef(_entity));
|
||||||
c5 = new (ref _pool5.GetRef(_entity));
|
c5 = new(ref _pool5.GetRef(_entity));
|
||||||
c6 = new (ref _pool6.GetRef(_entity));
|
c6 = new(ref _pool6.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,14 +306,14 @@ public readonly struct QueryItem<T0, T1, T2, T3, T4, T5, T6, T7>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new (ref _pool0.GetRef(_entity));
|
c0 = new(ref _pool0.GetRef(_entity));
|
||||||
c1 = new (ref _pool1.GetRef(_entity));
|
c1 = new(ref _pool1.GetRef(_entity));
|
||||||
c2 = new (ref _pool2.GetRef(_entity));
|
c2 = new(ref _pool2.GetRef(_entity));
|
||||||
c3 = new (ref _pool3.GetRef(_entity));
|
c3 = new(ref _pool3.GetRef(_entity));
|
||||||
c4 = new (ref _pool4.GetRef(_entity));
|
c4 = new(ref _pool4.GetRef(_entity));
|
||||||
c5 = new (ref _pool5.GetRef(_entity));
|
c5 = new(ref _pool5.GetRef(_entity));
|
||||||
c6 = new (ref _pool6.GetRef(_entity));
|
c6 = new(ref _pool6.GetRef(_entity));
|
||||||
c7 = new (ref _pool7.GetRef(_entity));
|
c7 = new(ref _pool7.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0> QueryFilter<T0>(ref readonly QueryFilter filter)
|
public QueryEnumerable<T0> QueryFilter<T0>(ref readonly QueryFilter filter)
|
||||||
where T0 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0)))
|
||||||
@@ -50,7 +50,7 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1> QueryFilter<T0, T1>(ref readonly QueryFilter filter)
|
public QueryEnumerable<T0, T1> QueryFilter<T0, T1>(ref readonly QueryFilter filter)
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1)))
|
||||||
@@ -79,7 +79,7 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2> QueryFilter<T0, T1, T2>(ref readonly QueryFilter filter)
|
public QueryEnumerable<T0, T1, T2> QueryFilter<T0, T1, T2>(ref readonly QueryFilter filter)
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2)))
|
||||||
@@ -108,7 +108,7 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2, T3> QueryFilter<T0, T1, T2, T3>(ref readonly QueryFilter filter)
|
public QueryEnumerable<T0, T1, T2, T3> QueryFilter<T0, T1, T2, T3>(ref readonly QueryFilter filter)
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3)))
|
||||||
@@ -137,7 +137,7 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2, T3, T4> QueryFilter<T0, T1, T2, T3, T4>(ref readonly QueryFilter filter)
|
public QueryEnumerable<T0, T1, T2, T3, T4> QueryFilter<T0, T1, T2, T3, T4>(ref readonly QueryFilter filter)
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4)))
|
||||||
@@ -166,7 +166,7 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2, T3, T4, T5> QueryFilter<T0, T1, T2, T3, T4, T5>(ref readonly QueryFilter filter)
|
public QueryEnumerable<T0, T1, T2, T3, T4, T5> QueryFilter<T0, T1, T2, T3, T4, T5>(ref readonly QueryFilter filter)
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5)))
|
||||||
@@ -195,7 +195,7 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2, T3, T4, T5, T6> QueryFilter<T0, T1, T2, T3, T4, T5, T6>(ref readonly QueryFilter filter)
|
public QueryEnumerable<T0, T1, T2, T3, T4, T5, T6> QueryFilter<T0, T1, T2, T3, T4, T5, T6>(ref readonly QueryFilter filter)
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5) && _componentStorage.TryGetPool<T6>(out var pool6)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5) && _componentStorage.TryGetPool<T6>(out var pool6)))
|
||||||
@@ -224,7 +224,7 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2, T3, T4, T5, T6, T7> QueryFilter<T0, T1, T2, T3, T4, T5, T6, T7>(ref readonly QueryFilter filter)
|
public QueryEnumerable<T0, T1, T2, T3, T4, T5, T6, T7> QueryFilter<T0, T1, T2, T3, T4, T5, T6, T7>(ref readonly QueryFilter filter)
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5) && _componentStorage.TryGetPool<T6>(out var pool6) && _componentStorage.TryGetPool<T7>(out var pool7)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5) && _componentStorage.TryGetPool<T6>(out var pool6) && _componentStorage.TryGetPool<T7>(out var pool7)))
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
/* https://fmod.com/docs/2.03/api/plugin-api-dsp.html */
|
/* https://fmod.com/docs/2.03/api/plugin-api-dsp.html */
|
||||||
/* =========================================================================================*/
|
/* =========================================================================================*/
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Text;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ghost.FMOD.Core
|
namespace Ghost.FMOD.Core
|
||||||
@@ -19,11 +17,11 @@ namespace Ghost.FMOD.Core
|
|||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_BUFFER_ARRAY
|
public struct DSP_BUFFER_ARRAY
|
||||||
{
|
{
|
||||||
public int numbuffers;
|
public int numbuffers;
|
||||||
public IntPtr buffernumchannels;
|
public IntPtr buffernumchannels;
|
||||||
public IntPtr bufferchannelmask;
|
public IntPtr bufferchannelmask;
|
||||||
public IntPtr buffers;
|
public IntPtr buffers;
|
||||||
public SPEAKERMODE speakermode;
|
public SPEAKERMODE speakermode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
These properties take advantage of the fact that numbuffers is always zero or one
|
These properties take advantage of the fact that numbuffers is always zero or one
|
||||||
@@ -31,7 +29,7 @@ namespace Ghost.FMOD.Core
|
|||||||
|
|
||||||
public int numchannels
|
public int numchannels
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (buffernumchannels != IntPtr.Zero && numbuffers != 0)
|
if (buffernumchannels != IntPtr.Zero && numbuffers != 0)
|
||||||
return Marshal.ReadInt32(buffernumchannels);
|
return Marshal.ReadInt32(buffernumchannels);
|
||||||
@@ -85,47 +83,47 @@ namespace Ghost.FMOD.Core
|
|||||||
/*
|
/*
|
||||||
DSP callbacks
|
DSP callbacks
|
||||||
*/
|
*/
|
||||||
public delegate RESULT DSP_CREATE_CALLBACK (ref DSP_STATE dsp_state);
|
public delegate RESULT DSP_CREATE_CALLBACK(ref DSP_STATE dsp_state);
|
||||||
public delegate RESULT DSP_RELEASE_CALLBACK (ref DSP_STATE dsp_state);
|
public delegate RESULT DSP_RELEASE_CALLBACK(ref DSP_STATE dsp_state);
|
||||||
public delegate RESULT DSP_RESET_CALLBACK (ref DSP_STATE dsp_state);
|
public delegate RESULT DSP_RESET_CALLBACK(ref DSP_STATE dsp_state);
|
||||||
public delegate RESULT DSP_SETPOSITION_CALLBACK (ref DSP_STATE dsp_state, uint pos);
|
public delegate RESULT DSP_SETPOSITION_CALLBACK(ref DSP_STATE dsp_state, uint pos);
|
||||||
public delegate RESULT DSP_READ_CALLBACK (ref DSP_STATE dsp_state, IntPtr inbuffer, IntPtr outbuffer, uint length, int inchannels, ref int outchannels);
|
public delegate RESULT DSP_READ_CALLBACK(ref DSP_STATE dsp_state, IntPtr inbuffer, IntPtr outbuffer, uint length, int inchannels, ref int outchannels);
|
||||||
public delegate RESULT DSP_SHOULDIPROCESS_CALLBACK (ref DSP_STATE dsp_state, bool inputsidle, uint length, CHANNELMASK inmask, int inchannels, SPEAKERMODE speakermode);
|
public delegate RESULT DSP_SHOULDIPROCESS_CALLBACK(ref DSP_STATE dsp_state, bool inputsidle, uint length, CHANNELMASK inmask, int inchannels, SPEAKERMODE speakermode);
|
||||||
public delegate RESULT DSP_PROCESS_CALLBACK (ref DSP_STATE dsp_state, uint length, ref DSP_BUFFER_ARRAY inbufferarray, ref DSP_BUFFER_ARRAY outbufferarray, bool inputsidle, DSP_PROCESS_OPERATION op);
|
public delegate RESULT DSP_PROCESS_CALLBACK(ref DSP_STATE dsp_state, uint length, ref DSP_BUFFER_ARRAY inbufferarray, ref DSP_BUFFER_ARRAY outbufferarray, bool inputsidle, DSP_PROCESS_OPERATION op);
|
||||||
public delegate RESULT DSP_SETPARAM_FLOAT_CALLBACK (ref DSP_STATE dsp_state, int index, float value);
|
public delegate RESULT DSP_SETPARAM_FLOAT_CALLBACK(ref DSP_STATE dsp_state, int index, float value);
|
||||||
public delegate RESULT DSP_SETPARAM_INT_CALLBACK (ref DSP_STATE dsp_state, int index, int value);
|
public delegate RESULT DSP_SETPARAM_INT_CALLBACK(ref DSP_STATE dsp_state, int index, int value);
|
||||||
public delegate RESULT DSP_SETPARAM_BOOL_CALLBACK (ref DSP_STATE dsp_state, int index, bool value);
|
public delegate RESULT DSP_SETPARAM_BOOL_CALLBACK(ref DSP_STATE dsp_state, int index, bool value);
|
||||||
public delegate RESULT DSP_SETPARAM_DATA_CALLBACK (ref DSP_STATE dsp_state, int index, IntPtr data, uint length);
|
public delegate RESULT DSP_SETPARAM_DATA_CALLBACK(ref DSP_STATE dsp_state, int index, IntPtr data, uint length);
|
||||||
public delegate RESULT DSP_GETPARAM_FLOAT_CALLBACK (ref DSP_STATE dsp_state, int index, ref float value, IntPtr valuestr);
|
public delegate RESULT DSP_GETPARAM_FLOAT_CALLBACK(ref DSP_STATE dsp_state, int index, ref float value, IntPtr valuestr);
|
||||||
public delegate RESULT DSP_GETPARAM_INT_CALLBACK (ref DSP_STATE dsp_state, int index, ref int value, IntPtr valuestr);
|
public delegate RESULT DSP_GETPARAM_INT_CALLBACK(ref DSP_STATE dsp_state, int index, ref int value, IntPtr valuestr);
|
||||||
public delegate RESULT DSP_GETPARAM_BOOL_CALLBACK (ref DSP_STATE dsp_state, int index, ref bool value, IntPtr valuestr);
|
public delegate RESULT DSP_GETPARAM_BOOL_CALLBACK(ref DSP_STATE dsp_state, int index, ref bool value, IntPtr valuestr);
|
||||||
public delegate RESULT DSP_GETPARAM_DATA_CALLBACK (ref DSP_STATE dsp_state, int index, ref IntPtr data, ref uint length, IntPtr valuestr);
|
public delegate RESULT DSP_GETPARAM_DATA_CALLBACK(ref DSP_STATE dsp_state, int index, ref IntPtr data, ref uint length, IntPtr valuestr);
|
||||||
public delegate RESULT DSP_SYSTEM_REGISTER_CALLBACK (ref DSP_STATE dsp_state);
|
public delegate RESULT DSP_SYSTEM_REGISTER_CALLBACK(ref DSP_STATE dsp_state);
|
||||||
public delegate RESULT DSP_SYSTEM_DEREGISTER_CALLBACK (ref DSP_STATE dsp_state);
|
public delegate RESULT DSP_SYSTEM_DEREGISTER_CALLBACK(ref DSP_STATE dsp_state);
|
||||||
public delegate RESULT DSP_SYSTEM_MIX_CALLBACK (ref DSP_STATE dsp_state, int stage);
|
public delegate RESULT DSP_SYSTEM_MIX_CALLBACK(ref DSP_STATE dsp_state, int stage);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
DSP functions
|
DSP functions
|
||||||
*/
|
*/
|
||||||
public delegate IntPtr DSP_ALLOC_FUNC (uint size, MEMORY_TYPE type, IntPtr sourcestr);
|
public delegate IntPtr DSP_ALLOC_FUNC(uint size, MEMORY_TYPE type, IntPtr sourcestr);
|
||||||
public delegate IntPtr DSP_REALLOC_FUNC (IntPtr ptr, uint size, MEMORY_TYPE type, IntPtr sourcestr);
|
public delegate IntPtr DSP_REALLOC_FUNC(IntPtr ptr, uint size, MEMORY_TYPE type, IntPtr sourcestr);
|
||||||
public delegate void DSP_FREE_FUNC (IntPtr ptr, MEMORY_TYPE type, IntPtr sourcestr);
|
public delegate void DSP_FREE_FUNC(IntPtr ptr, MEMORY_TYPE type, IntPtr sourcestr);
|
||||||
public delegate void DSP_LOG_FUNC (DEBUG_FLAGS level, IntPtr file, int line, IntPtr function, IntPtr str);
|
public delegate void DSP_LOG_FUNC(DEBUG_FLAGS level, IntPtr file, int line, IntPtr function, IntPtr str);
|
||||||
public delegate RESULT DSP_GETSAMPLERATE_FUNC (ref DSP_STATE dsp_state, ref int rate);
|
public delegate RESULT DSP_GETSAMPLERATE_FUNC(ref DSP_STATE dsp_state, ref int rate);
|
||||||
public delegate RESULT DSP_GETBLOCKSIZE_FUNC (ref DSP_STATE dsp_state, ref uint blocksize);
|
public delegate RESULT DSP_GETBLOCKSIZE_FUNC(ref DSP_STATE dsp_state, ref uint blocksize);
|
||||||
public delegate RESULT DSP_GETSPEAKERMODE_FUNC (ref DSP_STATE dsp_state, ref int speakermode_mixer, ref int speakermode_output);
|
public delegate RESULT DSP_GETSPEAKERMODE_FUNC(ref DSP_STATE dsp_state, ref int speakermode_mixer, ref int speakermode_output);
|
||||||
public delegate RESULT DSP_GETCLOCK_FUNC (ref DSP_STATE dsp_state, out ulong clock, out uint offset, out uint length);
|
public delegate RESULT DSP_GETCLOCK_FUNC(ref DSP_STATE dsp_state, out ulong clock, out uint offset, out uint length);
|
||||||
public delegate RESULT DSP_GETLISTENERATTRIBUTES_FUNC (ref DSP_STATE dsp_state, ref int numlisteners, IntPtr attributes);
|
public delegate RESULT DSP_GETLISTENERATTRIBUTES_FUNC(ref DSP_STATE dsp_state, ref int numlisteners, IntPtr attributes);
|
||||||
public delegate RESULT DSP_GETUSERDATA_FUNC (ref DSP_STATE dsp_state, out IntPtr userdata);
|
public delegate RESULT DSP_GETUSERDATA_FUNC(ref DSP_STATE dsp_state, out IntPtr userdata);
|
||||||
public delegate RESULT DSP_DFT_FFTREAL_FUNC (ref DSP_STATE dsp_state, int size, IntPtr signal, IntPtr dft, IntPtr window, int signalhop);
|
public delegate RESULT DSP_DFT_FFTREAL_FUNC(ref DSP_STATE dsp_state, int size, IntPtr signal, IntPtr dft, IntPtr window, int signalhop);
|
||||||
public delegate RESULT DSP_DFT_IFFTREAL_FUNC (ref DSP_STATE dsp_state, int size, IntPtr dft, IntPtr signal, IntPtr window, int signalhop);
|
public delegate RESULT DSP_DFT_IFFTREAL_FUNC(ref DSP_STATE dsp_state, int size, IntPtr dft, IntPtr signal, IntPtr window, int signalhop);
|
||||||
public delegate RESULT DSP_PAN_SUMMONOMATRIX_FUNC (ref DSP_STATE dsp_state, int sourceSpeakerMode, float lowFrequencyGain, float overallGain, IntPtr matrix);
|
public delegate RESULT DSP_PAN_SUMMONOMATRIX_FUNC(ref DSP_STATE dsp_state, int sourceSpeakerMode, float lowFrequencyGain, float overallGain, IntPtr matrix);
|
||||||
public delegate RESULT DSP_PAN_SUMSTEREOMATRIX_FUNC (ref DSP_STATE dsp_state, int sourceSpeakerMode, float pan, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);
|
public delegate RESULT DSP_PAN_SUMSTEREOMATRIX_FUNC(ref DSP_STATE dsp_state, int sourceSpeakerMode, float pan, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);
|
||||||
public delegate RESULT DSP_PAN_SUMSURROUNDMATRIX_FUNC (ref DSP_STATE dsp_state, int sourceSpeakerMode, int targetSpeakerMode, float direction, float extent, float rotation, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix, DSP_PAN_SURROUND_FLAGS flags);
|
public delegate RESULT DSP_PAN_SUMSURROUNDMATRIX_FUNC(ref DSP_STATE dsp_state, int sourceSpeakerMode, int targetSpeakerMode, float direction, float extent, float rotation, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix, DSP_PAN_SURROUND_FLAGS flags);
|
||||||
public delegate RESULT DSP_PAN_SUMMONOTOSURROUNDMATRIX_FUNC (ref DSP_STATE dsp_state, int targetSpeakerMode, float direction, float extent, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);
|
public delegate RESULT DSP_PAN_SUMMONOTOSURROUNDMATRIX_FUNC(ref DSP_STATE dsp_state, int targetSpeakerMode, float direction, float extent, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);
|
||||||
public delegate RESULT DSP_PAN_SUMSTEREOTOSURROUNDMATRIX_FUNC (ref DSP_STATE dsp_state, int targetSpeakerMode, float direction, float extent, float rotation, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);
|
public delegate RESULT DSP_PAN_SUMSTEREOTOSURROUNDMATRIX_FUNC(ref DSP_STATE dsp_state, int targetSpeakerMode, float direction, float extent, float rotation, float lowFrequencyGain, float overallGain, int matrixHop, IntPtr matrix);
|
||||||
public delegate RESULT DSP_PAN_GETROLLOFFGAIN_FUNC (ref DSP_STATE dsp_state, DSP_PAN_3D_ROLLOFF_TYPE rolloff, float distance, float mindistance, float maxdistance, out float gain);
|
public delegate RESULT DSP_PAN_GETROLLOFFGAIN_FUNC(ref DSP_STATE dsp_state, DSP_PAN_3D_ROLLOFF_TYPE rolloff, float distance, float mindistance, float maxdistance, out float gain);
|
||||||
|
|
||||||
|
|
||||||
public enum DSP_TYPE : int
|
public enum DSP_TYPE : int
|
||||||
@@ -202,71 +200,71 @@ namespace Ghost.FMOD.Core
|
|||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_PARAMETER_DESC_FLOAT
|
public struct DSP_PARAMETER_DESC_FLOAT
|
||||||
{
|
{
|
||||||
public float min;
|
public float min;
|
||||||
public float max;
|
public float max;
|
||||||
public float defaultval;
|
public float defaultval;
|
||||||
public DSP_PARAMETER_FLOAT_MAPPING mapping;
|
public DSP_PARAMETER_FLOAT_MAPPING mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_PARAMETER_DESC_INT
|
public struct DSP_PARAMETER_DESC_INT
|
||||||
{
|
{
|
||||||
public int min;
|
public int min;
|
||||||
public int max;
|
public int max;
|
||||||
public int defaultval;
|
public int defaultval;
|
||||||
public bool goestoinf;
|
public bool goestoinf;
|
||||||
public IntPtr valuenames;
|
public IntPtr valuenames;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_PARAMETER_DESC_BOOL
|
public struct DSP_PARAMETER_DESC_BOOL
|
||||||
{
|
{
|
||||||
public bool defaultval;
|
public bool defaultval;
|
||||||
public IntPtr valuenames;
|
public IntPtr valuenames;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_PARAMETER_DESC_DATA
|
public struct DSP_PARAMETER_DESC_DATA
|
||||||
{
|
{
|
||||||
public int datatype;
|
public int datatype;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
public struct DSP_PARAMETER_DESC_UNION
|
public struct DSP_PARAMETER_DESC_UNION
|
||||||
{
|
{
|
||||||
[FieldOffset(0)]
|
[FieldOffset(0)]
|
||||||
public DSP_PARAMETER_DESC_FLOAT floatdesc;
|
public DSP_PARAMETER_DESC_FLOAT floatdesc;
|
||||||
[FieldOffset(0)]
|
[FieldOffset(0)]
|
||||||
public DSP_PARAMETER_DESC_INT intdesc;
|
public DSP_PARAMETER_DESC_INT intdesc;
|
||||||
[FieldOffset(0)]
|
[FieldOffset(0)]
|
||||||
public DSP_PARAMETER_DESC_BOOL booldesc;
|
public DSP_PARAMETER_DESC_BOOL booldesc;
|
||||||
[FieldOffset(0)]
|
[FieldOffset(0)]
|
||||||
public DSP_PARAMETER_DESC_DATA datadesc;
|
public DSP_PARAMETER_DESC_DATA datadesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_PARAMETER_DESC
|
public struct DSP_PARAMETER_DESC
|
||||||
{
|
{
|
||||||
public DSP_PARAMETER_TYPE type;
|
public DSP_PARAMETER_TYPE type;
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
||||||
public byte[] name;
|
public byte[] name;
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
|
||||||
public byte[] label;
|
public byte[] label;
|
||||||
public string description;
|
public string description;
|
||||||
|
|
||||||
public DSP_PARAMETER_DESC_UNION desc;
|
public DSP_PARAMETER_DESC_UNION desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DSP_PARAMETER_DATA_TYPE
|
public enum DSP_PARAMETER_DATA_TYPE
|
||||||
{
|
{
|
||||||
DSP_PARAMETER_DATA_TYPE_USER = 0,
|
DSP_PARAMETER_DATA_TYPE_USER = 0,
|
||||||
DSP_PARAMETER_DATA_TYPE_OVERALLGAIN = -1,
|
DSP_PARAMETER_DATA_TYPE_OVERALLGAIN = -1,
|
||||||
DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES = -2,
|
DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES = -2,
|
||||||
DSP_PARAMETER_DATA_TYPE_SIDECHAIN = -3,
|
DSP_PARAMETER_DATA_TYPE_SIDECHAIN = -3,
|
||||||
DSP_PARAMETER_DATA_TYPE_FFT = -4,
|
DSP_PARAMETER_DATA_TYPE_FFT = -4,
|
||||||
DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES_MULTI = -5,
|
DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES_MULTI = -5,
|
||||||
DSP_PARAMETER_DATA_TYPE_ATTENUATION_RANGE = -6,
|
DSP_PARAMETER_DATA_TYPE_ATTENUATION_RANGE = -6,
|
||||||
DSP_PARAMETER_DATA_TYPE_DYNAMIC_RESPONSE = -7
|
DSP_PARAMETER_DATA_TYPE_DYNAMIC_RESPONSE = -7
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
@@ -275,38 +273,38 @@ namespace Ghost.FMOD.Core
|
|||||||
public float linear_gain;
|
public float linear_gain;
|
||||||
public float linear_gain_additive;
|
public float linear_gain_additive;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_PARAMETER_3DATTRIBUTES
|
public struct DSP_PARAMETER_3DATTRIBUTES
|
||||||
{
|
{
|
||||||
public ATTRIBUTES_3D relative;
|
public ATTRIBUTES_3D relative;
|
||||||
public ATTRIBUTES_3D absolute;
|
public ATTRIBUTES_3D absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_PARAMETER_3DATTRIBUTES_MULTI
|
public struct DSP_PARAMETER_3DATTRIBUTES_MULTI
|
||||||
{
|
{
|
||||||
public int numlisteners;
|
public int numlisteners;
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||||
public ATTRIBUTES_3D[] relative;
|
public ATTRIBUTES_3D[] relative;
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||||
public float[] weight;
|
public float[] weight;
|
||||||
public ATTRIBUTES_3D absolute;
|
public ATTRIBUTES_3D absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_PARAMETER_SIDECHAIN
|
public struct DSP_PARAMETER_SIDECHAIN
|
||||||
{
|
{
|
||||||
public int sidechainenable;
|
public int sidechainenable;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_PARAMETER_FFT
|
public struct DSP_PARAMETER_FFT
|
||||||
{
|
{
|
||||||
public int length;
|
public int length;
|
||||||
public int numchannels;
|
public int numchannels;
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType.ByValArray,SizeConst=32)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||||
private IntPtr[] spectrum_internal;
|
private IntPtr[] spectrum_internal;
|
||||||
|
|
||||||
public float[][] spectrum
|
public float[][] spectrum
|
||||||
@@ -314,21 +312,21 @@ namespace Ghost.FMOD.Core
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
var buffer = new float[numchannels][];
|
var buffer = new float[numchannels][];
|
||||||
|
|
||||||
for (int i = 0; i < numchannels; ++i)
|
for (var i = 0; i < numchannels; ++i)
|
||||||
{
|
{
|
||||||
buffer[i] = new float[length];
|
buffer[i] = new float[length];
|
||||||
Marshal.Copy(spectrum_internal[i], buffer[i], 0, length);
|
Marshal.Copy(spectrum_internal[i], buffer[i], 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getSpectrum(ref float[][] buffer)
|
public void getSpectrum(ref float[][] buffer)
|
||||||
{
|
{
|
||||||
int bufferLength = Math.Min(buffer.Length, numchannels);
|
var bufferLength = Math.Min(buffer.Length, numchannels);
|
||||||
for (int i = 0; i < bufferLength; ++i)
|
for (var i = 0; i < bufferLength; ++i)
|
||||||
{
|
{
|
||||||
getSpectrum(i, ref buffer[i]);
|
getSpectrum(i, ref buffer[i]);
|
||||||
}
|
}
|
||||||
@@ -336,7 +334,7 @@ namespace Ghost.FMOD.Core
|
|||||||
|
|
||||||
public void getSpectrum(int channel, ref float[] buffer)
|
public void getSpectrum(int channel, ref float[] buffer)
|
||||||
{
|
{
|
||||||
int bufferLength = Math.Min(buffer.Length, length);
|
var bufferLength = Math.Min(buffer.Length, length);
|
||||||
Marshal.Copy(spectrum_internal[channel], buffer, 0, bufferLength);
|
Marshal.Copy(spectrum_internal[channel], buffer, 0, bufferLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -380,105 +378,114 @@ namespace Ghost.FMOD.Core
|
|||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_DESCRIPTION
|
public struct DSP_DESCRIPTION
|
||||||
{
|
{
|
||||||
public uint pluginsdkversion;
|
public uint pluginsdkversion;
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||||
public byte[] name;
|
public byte[] name;
|
||||||
public uint version;
|
public uint version;
|
||||||
public int numinputbuffers;
|
public int numinputbuffers;
|
||||||
public int numoutputbuffers;
|
public int numoutputbuffers;
|
||||||
public DSP_CREATE_CALLBACK create;
|
public DSP_CREATE_CALLBACK create;
|
||||||
public DSP_RELEASE_CALLBACK release;
|
public DSP_RELEASE_CALLBACK release;
|
||||||
public DSP_RESET_CALLBACK reset;
|
public DSP_RESET_CALLBACK reset;
|
||||||
public DSP_READ_CALLBACK read;
|
public DSP_READ_CALLBACK read;
|
||||||
public DSP_PROCESS_CALLBACK process;
|
public DSP_PROCESS_CALLBACK process;
|
||||||
public DSP_SETPOSITION_CALLBACK setposition;
|
public DSP_SETPOSITION_CALLBACK setposition;
|
||||||
|
|
||||||
public int numparameters;
|
public int numparameters;
|
||||||
public IntPtr paramdesc;
|
public IntPtr paramdesc;
|
||||||
public DSP_SETPARAM_FLOAT_CALLBACK setparameterfloat;
|
public DSP_SETPARAM_FLOAT_CALLBACK setparameterfloat;
|
||||||
public DSP_SETPARAM_INT_CALLBACK setparameterint;
|
public DSP_SETPARAM_INT_CALLBACK setparameterint;
|
||||||
public DSP_SETPARAM_BOOL_CALLBACK setparameterbool;
|
public DSP_SETPARAM_BOOL_CALLBACK setparameterbool;
|
||||||
public DSP_SETPARAM_DATA_CALLBACK setparameterdata;
|
public DSP_SETPARAM_DATA_CALLBACK setparameterdata;
|
||||||
public DSP_GETPARAM_FLOAT_CALLBACK getparameterfloat;
|
public DSP_GETPARAM_FLOAT_CALLBACK getparameterfloat;
|
||||||
public DSP_GETPARAM_INT_CALLBACK getparameterint;
|
public DSP_GETPARAM_INT_CALLBACK getparameterint;
|
||||||
public DSP_GETPARAM_BOOL_CALLBACK getparameterbool;
|
public DSP_GETPARAM_BOOL_CALLBACK getparameterbool;
|
||||||
public DSP_GETPARAM_DATA_CALLBACK getparameterdata;
|
public DSP_GETPARAM_DATA_CALLBACK getparameterdata;
|
||||||
public DSP_SHOULDIPROCESS_CALLBACK shouldiprocess;
|
public DSP_SHOULDIPROCESS_CALLBACK shouldiprocess;
|
||||||
public IntPtr userdata;
|
public IntPtr userdata;
|
||||||
|
|
||||||
public DSP_SYSTEM_REGISTER_CALLBACK sys_register;
|
public DSP_SYSTEM_REGISTER_CALLBACK sys_register;
|
||||||
public DSP_SYSTEM_DEREGISTER_CALLBACK sys_deregister;
|
public DSP_SYSTEM_DEREGISTER_CALLBACK sys_deregister;
|
||||||
public DSP_SYSTEM_MIX_CALLBACK sys_mix;
|
public DSP_SYSTEM_MIX_CALLBACK sys_mix;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_STATE_DFT_FUNCTIONS
|
public struct DSP_STATE_DFT_FUNCTIONS
|
||||||
{
|
{
|
||||||
public DSP_DFT_FFTREAL_FUNC fftreal;
|
public DSP_DFT_FFTREAL_FUNC fftreal;
|
||||||
public DSP_DFT_IFFTREAL_FUNC inversefftreal;
|
public DSP_DFT_IFFTREAL_FUNC inversefftreal;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_STATE_PAN_FUNCTIONS
|
public struct DSP_STATE_PAN_FUNCTIONS
|
||||||
{
|
{
|
||||||
public DSP_PAN_SUMMONOMATRIX_FUNC summonomatrix;
|
public DSP_PAN_SUMMONOMATRIX_FUNC summonomatrix;
|
||||||
public DSP_PAN_SUMSTEREOMATRIX_FUNC sumstereomatrix;
|
public DSP_PAN_SUMSTEREOMATRIX_FUNC sumstereomatrix;
|
||||||
public DSP_PAN_SUMSURROUNDMATRIX_FUNC sumsurroundmatrix;
|
public DSP_PAN_SUMSURROUNDMATRIX_FUNC sumsurroundmatrix;
|
||||||
public DSP_PAN_SUMMONOTOSURROUNDMATRIX_FUNC summonotosurroundmatrix;
|
public DSP_PAN_SUMMONOTOSURROUNDMATRIX_FUNC summonotosurroundmatrix;
|
||||||
public DSP_PAN_SUMSTEREOTOSURROUNDMATRIX_FUNC sumstereotosurroundmatrix;
|
public DSP_PAN_SUMSTEREOTOSURROUNDMATRIX_FUNC sumstereotosurroundmatrix;
|
||||||
public DSP_PAN_GETROLLOFFGAIN_FUNC getrolloffgain;
|
public DSP_PAN_GETROLLOFFGAIN_FUNC getrolloffgain;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_STATE_FUNCTIONS
|
public struct DSP_STATE_FUNCTIONS
|
||||||
{
|
{
|
||||||
public DSP_ALLOC_FUNC alloc;
|
public DSP_ALLOC_FUNC alloc;
|
||||||
public DSP_REALLOC_FUNC realloc;
|
public DSP_REALLOC_FUNC realloc;
|
||||||
public DSP_FREE_FUNC free;
|
public DSP_FREE_FUNC free;
|
||||||
public DSP_GETSAMPLERATE_FUNC getsamplerate;
|
public DSP_GETSAMPLERATE_FUNC getsamplerate;
|
||||||
public DSP_GETBLOCKSIZE_FUNC getblocksize;
|
public DSP_GETBLOCKSIZE_FUNC getblocksize;
|
||||||
public IntPtr dft_internal;
|
public IntPtr dft_internal;
|
||||||
public IntPtr pan_internal;
|
public IntPtr pan_internal;
|
||||||
public DSP_GETSPEAKERMODE_FUNC getspeakermode;
|
public DSP_GETSPEAKERMODE_FUNC getspeakermode;
|
||||||
public DSP_GETCLOCK_FUNC getclock;
|
public DSP_GETCLOCK_FUNC getclock;
|
||||||
public DSP_GETLISTENERATTRIBUTES_FUNC getlistenerattributes;
|
public DSP_GETLISTENERATTRIBUTES_FUNC getlistenerattributes;
|
||||||
public DSP_LOG_FUNC log;
|
public DSP_LOG_FUNC log;
|
||||||
public DSP_GETUSERDATA_FUNC getuserdata;
|
public DSP_GETUSERDATA_FUNC getuserdata;
|
||||||
public DSP_STATE_DFT_FUNCTIONS dft
|
public DSP_STATE_DFT_FUNCTIONS dft
|
||||||
{
|
{
|
||||||
get { return Marshal.PtrToStructure<DSP_STATE_DFT_FUNCTIONS>(dft_internal); }
|
get
|
||||||
|
{
|
||||||
|
return Marshal.PtrToStructure<DSP_STATE_DFT_FUNCTIONS>(dft_internal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public DSP_STATE_PAN_FUNCTIONS pan
|
public DSP_STATE_PAN_FUNCTIONS pan
|
||||||
{
|
{
|
||||||
get { return Marshal.PtrToStructure<DSP_STATE_PAN_FUNCTIONS>(pan_internal); }
|
get
|
||||||
|
{
|
||||||
|
return Marshal.PtrToStructure<DSP_STATE_PAN_FUNCTIONS>(pan_internal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_STATE
|
public struct DSP_STATE
|
||||||
{
|
{
|
||||||
public IntPtr instance;
|
public IntPtr instance;
|
||||||
public IntPtr plugindata;
|
public IntPtr plugindata;
|
||||||
public uint channelmask;
|
public uint channelmask;
|
||||||
public int source_speakermode;
|
public int source_speakermode;
|
||||||
public IntPtr sidechaindata;
|
public IntPtr sidechaindata;
|
||||||
public int sidechainchannels;
|
public int sidechainchannels;
|
||||||
private IntPtr functions_internal;
|
private IntPtr functions_internal;
|
||||||
public int systemobject;
|
public int systemobject;
|
||||||
|
|
||||||
public DSP_STATE_FUNCTIONS functions
|
public DSP_STATE_FUNCTIONS functions
|
||||||
{
|
{
|
||||||
get { return Marshal.PtrToStructure<DSP_STATE_FUNCTIONS>(functions_internal); }
|
get
|
||||||
|
{
|
||||||
|
return Marshal.PtrToStructure<DSP_STATE_FUNCTIONS>(functions_internal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct DSP_METERING_INFO
|
public struct DSP_METERING_INFO
|
||||||
{
|
{
|
||||||
public int numsamples;
|
public int numsamples;
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||||
public float[] peaklevel;
|
public float[] peaklevel;
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||||
public float[] rmslevel;
|
public float[] rmslevel;
|
||||||
public short numchannels;
|
public short numchannels;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,89 +17,172 @@ namespace Ghost.FMOD.Core
|
|||||||
{
|
{
|
||||||
switch (errcode)
|
switch (errcode)
|
||||||
{
|
{
|
||||||
case RESULT.OK: return "No errors.";
|
case RESULT.OK:
|
||||||
case RESULT.ERR_BADCOMMAND: return "Tried to call a function on a data type that does not allow this type of functionality (ie calling Sound::lock on a streaming sound).";
|
return "No errors.";
|
||||||
case RESULT.ERR_CHANNEL_ALLOC: return "Error trying to allocate a channel.";
|
case RESULT.ERR_BADCOMMAND:
|
||||||
case RESULT.ERR_CHANNEL_STOLEN: return "The specified channel has been reused to play another sound.";
|
return "Tried to call a function on a data type that does not allow this type of functionality (ie calling Sound::lock on a streaming sound).";
|
||||||
case RESULT.ERR_DMA: return "DMA Failure. See debug output for more information.";
|
case RESULT.ERR_CHANNEL_ALLOC:
|
||||||
case RESULT.ERR_DSP_CONNECTION: return "DSP connection error. Connection possibly caused a cyclic dependency or connected dsps with incompatible buffer counts.";
|
return "Error trying to allocate a channel.";
|
||||||
case RESULT.ERR_DSP_DONTPROCESS: return "DSP return code from a DSP process query callback. Tells mixer not to call the process callback and therefore not consume CPU. Use this to optimize the DSP graph.";
|
case RESULT.ERR_CHANNEL_STOLEN:
|
||||||
case RESULT.ERR_DSP_FORMAT: return "DSP Format error. A DSP unit may have attempted to connect to this network with the wrong format, or a matrix may have been set with the wrong size if the target unit has a specified channel map.";
|
return "The specified channel has been reused to play another sound.";
|
||||||
case RESULT.ERR_DSP_INUSE: return "DSP is already in the mixer's DSP network. It must be removed before being reinserted or released.";
|
case RESULT.ERR_DMA:
|
||||||
case RESULT.ERR_DSP_NOTFOUND: return "DSP connection error. Couldn't find the DSP unit specified.";
|
return "DMA Failure. See debug output for more information.";
|
||||||
case RESULT.ERR_DSP_RESERVED: return "DSP operation error. Cannot perform operation on this DSP as it is reserved by the system.";
|
case RESULT.ERR_DSP_CONNECTION:
|
||||||
case RESULT.ERR_DSP_SILENCE: return "DSP return code from a DSP process query callback. Tells mixer silence would be produced from read, so go idle and not consume CPU. Use this to optimize the DSP graph.";
|
return "DSP connection error. Connection possibly caused a cyclic dependency or connected dsps with incompatible buffer counts.";
|
||||||
case RESULT.ERR_DSP_TYPE: return "DSP operation cannot be performed on a DSP of this type.";
|
case RESULT.ERR_DSP_DONTPROCESS:
|
||||||
case RESULT.ERR_FILE_BAD: return "Error loading file.";
|
return "DSP return code from a DSP process query callback. Tells mixer not to call the process callback and therefore not consume CPU. Use this to optimize the DSP graph.";
|
||||||
case RESULT.ERR_FILE_COULDNOTSEEK: return "Couldn't perform seek operation. This is a limitation of the medium (ie netstreams) or the file format.";
|
case RESULT.ERR_DSP_FORMAT:
|
||||||
case RESULT.ERR_FILE_DISKEJECTED: return "Media was ejected while reading.";
|
return "DSP Format error. A DSP unit may have attempted to connect to this network with the wrong format, or a matrix may have been set with the wrong size if the target unit has a specified channel map.";
|
||||||
case RESULT.ERR_FILE_EOF: return "End of file unexpectedly reached while trying to read essential data (truncated?).";
|
case RESULT.ERR_DSP_INUSE:
|
||||||
case RESULT.ERR_FILE_ENDOFDATA: return "End of current chunk reached while trying to read data.";
|
return "DSP is already in the mixer's DSP network. It must be removed before being reinserted or released.";
|
||||||
case RESULT.ERR_FILE_NOTFOUND: return "File not found.";
|
case RESULT.ERR_DSP_NOTFOUND:
|
||||||
case RESULT.ERR_FORMAT: return "Unsupported file or audio format.";
|
return "DSP connection error. Couldn't find the DSP unit specified.";
|
||||||
case RESULT.ERR_HEADER_MISMATCH: return "There is a version mismatch between the FMOD header and either the FMOD Studio library or the FMOD Low Level library.";
|
case RESULT.ERR_DSP_RESERVED:
|
||||||
case RESULT.ERR_HTTP: return "A HTTP error occurred. This is a catch-all for HTTP errors not listed elsewhere.";
|
return "DSP operation error. Cannot perform operation on this DSP as it is reserved by the system.";
|
||||||
case RESULT.ERR_HTTP_ACCESS: return "The specified resource requires authentication or is forbidden.";
|
case RESULT.ERR_DSP_SILENCE:
|
||||||
case RESULT.ERR_HTTP_PROXY_AUTH: return "Proxy authentication is required to access the specified resource.";
|
return "DSP return code from a DSP process query callback. Tells mixer silence would be produced from read, so go idle and not consume CPU. Use this to optimize the DSP graph.";
|
||||||
case RESULT.ERR_HTTP_SERVER_ERROR: return "A HTTP server error occurred.";
|
case RESULT.ERR_DSP_TYPE:
|
||||||
case RESULT.ERR_HTTP_TIMEOUT: return "The HTTP request timed out.";
|
return "DSP operation cannot be performed on a DSP of this type.";
|
||||||
case RESULT.ERR_INITIALIZATION: return "FMOD was not initialized correctly to support this function.";
|
case RESULT.ERR_FILE_BAD:
|
||||||
case RESULT.ERR_INITIALIZED: return "Cannot call this command after System::init.";
|
return "Error loading file.";
|
||||||
case RESULT.ERR_INTERNAL: return "An error occured in the FMOD system. Use the logging version of FMOD for more information.";
|
case RESULT.ERR_FILE_COULDNOTSEEK:
|
||||||
case RESULT.ERR_INVALID_FLOAT: return "Value passed in was a NaN, Inf or denormalized float.";
|
return "Couldn't perform seek operation. This is a limitation of the medium (ie netstreams) or the file format.";
|
||||||
case RESULT.ERR_INVALID_HANDLE: return "An invalid object handle was used.";
|
case RESULT.ERR_FILE_DISKEJECTED:
|
||||||
case RESULT.ERR_INVALID_PARAM: return "An invalid parameter was passed to this function.";
|
return "Media was ejected while reading.";
|
||||||
case RESULT.ERR_INVALID_POSITION: return "An invalid seek position was passed to this function.";
|
case RESULT.ERR_FILE_EOF:
|
||||||
case RESULT.ERR_INVALID_SPEAKER: return "An invalid speaker was passed to this function based on the current speaker mode.";
|
return "End of file unexpectedly reached while trying to read essential data (truncated?).";
|
||||||
case RESULT.ERR_INVALID_SYNCPOINT: return "The syncpoint did not come from this sound handle.";
|
case RESULT.ERR_FILE_ENDOFDATA:
|
||||||
case RESULT.ERR_INVALID_THREAD: return "Tried to call a function on a thread that is not supported.";
|
return "End of current chunk reached while trying to read data.";
|
||||||
case RESULT.ERR_INVALID_VECTOR: return "The vectors passed in are not unit length, or perpendicular.";
|
case RESULT.ERR_FILE_NOTFOUND:
|
||||||
case RESULT.ERR_MAXAUDIBLE: return "Reached maximum audible playback count for this sound's soundgroup.";
|
return "File not found.";
|
||||||
case RESULT.ERR_MEMORY: return "Not enough memory or resources.";
|
case RESULT.ERR_FORMAT:
|
||||||
case RESULT.ERR_MEMORY_CANTPOINT: return "Can't use FMOD_OPENMEMORY_POINT on non PCM source data, or non mp3/xma/adpcm data if FMOD_CREATECOMPRESSEDSAMPLE was used.";
|
return "Unsupported file or audio format.";
|
||||||
case RESULT.ERR_NEEDS3D: return "Tried to call a command on a 2d sound when the command was meant for 3d sound.";
|
case RESULT.ERR_HEADER_MISMATCH:
|
||||||
case RESULT.ERR_NEEDSHARDWARE: return "Tried to use a feature that requires hardware support.";
|
return "There is a version mismatch between the FMOD header and either the FMOD Studio library or the FMOD Low Level library.";
|
||||||
case RESULT.ERR_NET_CONNECT: return "Couldn't connect to the specified host.";
|
case RESULT.ERR_HTTP:
|
||||||
case RESULT.ERR_NET_SOCKET_ERROR: return "A socket error occurred. This is a catch-all for socket-related errors not listed elsewhere.";
|
return "A HTTP error occurred. This is a catch-all for HTTP errors not listed elsewhere.";
|
||||||
case RESULT.ERR_NET_URL: return "The specified URL couldn't be resolved.";
|
case RESULT.ERR_HTTP_ACCESS:
|
||||||
case RESULT.ERR_NET_WOULD_BLOCK: return "Operation on a non-blocking socket could not complete immediately.";
|
return "The specified resource requires authentication or is forbidden.";
|
||||||
case RESULT.ERR_NOTREADY: return "Operation could not be performed because specified sound/DSP connection is not ready.";
|
case RESULT.ERR_HTTP_PROXY_AUTH:
|
||||||
case RESULT.ERR_OUTPUT_ALLOCATED: return "Error initializing output device, but more specifically, the output device is already in use and cannot be reused.";
|
return "Proxy authentication is required to access the specified resource.";
|
||||||
case RESULT.ERR_OUTPUT_CREATEBUFFER: return "Error creating hardware sound buffer.";
|
case RESULT.ERR_HTTP_SERVER_ERROR:
|
||||||
case RESULT.ERR_OUTPUT_DRIVERCALL: return "A call to a standard soundcard driver failed, which could possibly mean a bug in the driver or resources were missing or exhausted.";
|
return "A HTTP server error occurred.";
|
||||||
case RESULT.ERR_OUTPUT_FORMAT: return "Soundcard does not support the specified format.";
|
case RESULT.ERR_HTTP_TIMEOUT:
|
||||||
case RESULT.ERR_OUTPUT_INIT: return "Error initializing output device.";
|
return "The HTTP request timed out.";
|
||||||
case RESULT.ERR_OUTPUT_NODRIVERS: return "The output device has no drivers installed. If pre-init, FMOD_OUTPUT_NOSOUND is selected as the output mode. If post-init, the function just fails.";
|
case RESULT.ERR_INITIALIZATION:
|
||||||
case RESULT.ERR_PLUGIN: return "An unspecified error has been returned from a plugin.";
|
return "FMOD was not initialized correctly to support this function.";
|
||||||
case RESULT.ERR_PLUGIN_MISSING: return "A requested output, dsp unit type or codec was not available.";
|
case RESULT.ERR_INITIALIZED:
|
||||||
case RESULT.ERR_PLUGIN_RESOURCE: return "A resource that the plugin requires cannot be allocated or found. (ie the DLS file for MIDI playback)";
|
return "Cannot call this command after System::init.";
|
||||||
case RESULT.ERR_PLUGIN_VERSION: return "A plugin was built with an unsupported SDK version.";
|
case RESULT.ERR_INTERNAL:
|
||||||
case RESULT.ERR_RECORD: return "An error occurred trying to initialize the recording device.";
|
return "An error occured in the FMOD system. Use the logging version of FMOD for more information.";
|
||||||
case RESULT.ERR_REVERB_CHANNELGROUP: return "Reverb properties cannot be set on this channel because a parent channelgroup owns the reverb connection.";
|
case RESULT.ERR_INVALID_FLOAT:
|
||||||
case RESULT.ERR_REVERB_INSTANCE: return "Specified instance in FMOD_REVERB_PROPERTIES couldn't be set. Most likely because it is an invalid instance number or the reverb doesn't exist.";
|
return "Value passed in was a NaN, Inf or denormalized float.";
|
||||||
case RESULT.ERR_SUBSOUNDS: return "The error occurred because the sound referenced contains subsounds when it shouldn't have, or it doesn't contain subsounds when it should have. The operation may also not be able to be performed on a parent sound.";
|
case RESULT.ERR_INVALID_HANDLE:
|
||||||
case RESULT.ERR_SUBSOUND_ALLOCATED: return "This subsound is already being used by another sound, you cannot have more than one parent to a sound. Null out the other parent's entry first.";
|
return "An invalid object handle was used.";
|
||||||
case RESULT.ERR_SUBSOUND_CANTMOVE: return "Shared subsounds cannot be replaced or moved from their parent stream, such as when the parent stream is an FSB file.";
|
case RESULT.ERR_INVALID_PARAM:
|
||||||
case RESULT.ERR_TAGNOTFOUND: return "The specified tag could not be found or there are no tags.";
|
return "An invalid parameter was passed to this function.";
|
||||||
case RESULT.ERR_TOOMANYCHANNELS: return "The sound created exceeds the allowable input channel count. This can be increased using the 'maxinputchannels' parameter in System::setSoftwareFormat.";
|
case RESULT.ERR_INVALID_POSITION:
|
||||||
case RESULT.ERR_TRUNCATED: return "The retrieved string is too long to fit in the supplied buffer and has been truncated.";
|
return "An invalid seek position was passed to this function.";
|
||||||
case RESULT.ERR_UNIMPLEMENTED: return "Something in FMOD hasn't been implemented when it should be. Contact support.";
|
case RESULT.ERR_INVALID_SPEAKER:
|
||||||
case RESULT.ERR_UNINITIALIZED: return "This command failed because System::init or System::setDriver was not called.";
|
return "An invalid speaker was passed to this function based on the current speaker mode.";
|
||||||
case RESULT.ERR_UNSUPPORTED: return "A command issued was not supported by this object. Possibly a plugin without certain callbacks specified.";
|
case RESULT.ERR_INVALID_SYNCPOINT:
|
||||||
case RESULT.ERR_VERSION: return "The version number of this file format is not supported.";
|
return "The syncpoint did not come from this sound handle.";
|
||||||
case RESULT.ERR_EVENT_ALREADY_LOADED: return "The specified bank has already been loaded.";
|
case RESULT.ERR_INVALID_THREAD:
|
||||||
case RESULT.ERR_EVENT_LIVEUPDATE_BUSY: return "The live update connection failed due to the game already being connected.";
|
return "Tried to call a function on a thread that is not supported.";
|
||||||
case RESULT.ERR_EVENT_LIVEUPDATE_MISMATCH: return "The live update connection failed due to the game data being out of sync with the tool.";
|
case RESULT.ERR_INVALID_VECTOR:
|
||||||
case RESULT.ERR_EVENT_LIVEUPDATE_TIMEOUT: return "The live update connection timed out.";
|
return "The vectors passed in are not unit length, or perpendicular.";
|
||||||
case RESULT.ERR_EVENT_NOTFOUND: return "The requested event, bus or vca could not be found.";
|
case RESULT.ERR_MAXAUDIBLE:
|
||||||
case RESULT.ERR_STUDIO_UNINITIALIZED: return "The Studio::System object is not yet initialized.";
|
return "Reached maximum audible playback count for this sound's soundgroup.";
|
||||||
case RESULT.ERR_STUDIO_NOT_LOADED: return "The specified resource is not loaded, so it can't be unloaded.";
|
case RESULT.ERR_MEMORY:
|
||||||
case RESULT.ERR_INVALID_STRING: return "An invalid string was passed to this function.";
|
return "Not enough memory or resources.";
|
||||||
case RESULT.ERR_ALREADY_LOCKED: return "The specified resource is already locked.";
|
case RESULT.ERR_MEMORY_CANTPOINT:
|
||||||
case RESULT.ERR_NOT_LOCKED: return "The specified resource is not locked, so it can't be unlocked.";
|
return "Can't use FMOD_OPENMEMORY_POINT on non PCM source data, or non mp3/xma/adpcm data if FMOD_CREATECOMPRESSEDSAMPLE was used.";
|
||||||
case RESULT.ERR_RECORD_DISCONNECTED: return "The specified recording driver has been disconnected.";
|
case RESULT.ERR_NEEDS3D:
|
||||||
case RESULT.ERR_TOOMANYSAMPLES: return "The length provided exceed the allowable limit.";
|
return "Tried to call a command on a 2d sound when the command was meant for 3d sound.";
|
||||||
default: return "Unknown error.";
|
case RESULT.ERR_NEEDSHARDWARE:
|
||||||
|
return "Tried to use a feature that requires hardware support.";
|
||||||
|
case RESULT.ERR_NET_CONNECT:
|
||||||
|
return "Couldn't connect to the specified host.";
|
||||||
|
case RESULT.ERR_NET_SOCKET_ERROR:
|
||||||
|
return "A socket error occurred. This is a catch-all for socket-related errors not listed elsewhere.";
|
||||||
|
case RESULT.ERR_NET_URL:
|
||||||
|
return "The specified URL couldn't be resolved.";
|
||||||
|
case RESULT.ERR_NET_WOULD_BLOCK:
|
||||||
|
return "Operation on a non-blocking socket could not complete immediately.";
|
||||||
|
case RESULT.ERR_NOTREADY:
|
||||||
|
return "Operation could not be performed because specified sound/DSP connection is not ready.";
|
||||||
|
case RESULT.ERR_OUTPUT_ALLOCATED:
|
||||||
|
return "Error initializing output device, but more specifically, the output device is already in use and cannot be reused.";
|
||||||
|
case RESULT.ERR_OUTPUT_CREATEBUFFER:
|
||||||
|
return "Error creating hardware sound buffer.";
|
||||||
|
case RESULT.ERR_OUTPUT_DRIVERCALL:
|
||||||
|
return "A call to a standard soundcard driver failed, which could possibly mean a bug in the driver or resources were missing or exhausted.";
|
||||||
|
case RESULT.ERR_OUTPUT_FORMAT:
|
||||||
|
return "Soundcard does not support the specified format.";
|
||||||
|
case RESULT.ERR_OUTPUT_INIT:
|
||||||
|
return "Error initializing output device.";
|
||||||
|
case RESULT.ERR_OUTPUT_NODRIVERS:
|
||||||
|
return "The output device has no drivers installed. If pre-init, FMOD_OUTPUT_NOSOUND is selected as the output mode. If post-init, the function just fails.";
|
||||||
|
case RESULT.ERR_PLUGIN:
|
||||||
|
return "An unspecified error has been returned from a plugin.";
|
||||||
|
case RESULT.ERR_PLUGIN_MISSING:
|
||||||
|
return "A requested output, dsp unit type or codec was not available.";
|
||||||
|
case RESULT.ERR_PLUGIN_RESOURCE:
|
||||||
|
return "A resource that the plugin requires cannot be allocated or found. (ie the DLS file for MIDI playback)";
|
||||||
|
case RESULT.ERR_PLUGIN_VERSION:
|
||||||
|
return "A plugin was built with an unsupported SDK version.";
|
||||||
|
case RESULT.ERR_RECORD:
|
||||||
|
return "An error occurred trying to initialize the recording device.";
|
||||||
|
case RESULT.ERR_REVERB_CHANNELGROUP:
|
||||||
|
return "Reverb properties cannot be set on this channel because a parent channelgroup owns the reverb connection.";
|
||||||
|
case RESULT.ERR_REVERB_INSTANCE:
|
||||||
|
return "Specified instance in FMOD_REVERB_PROPERTIES couldn't be set. Most likely because it is an invalid instance number or the reverb doesn't exist.";
|
||||||
|
case RESULT.ERR_SUBSOUNDS:
|
||||||
|
return "The error occurred because the sound referenced contains subsounds when it shouldn't have, or it doesn't contain subsounds when it should have. The operation may also not be able to be performed on a parent sound.";
|
||||||
|
case RESULT.ERR_SUBSOUND_ALLOCATED:
|
||||||
|
return "This subsound is already being used by another sound, you cannot have more than one parent to a sound. Null out the other parent's entry first.";
|
||||||
|
case RESULT.ERR_SUBSOUND_CANTMOVE:
|
||||||
|
return "Shared subsounds cannot be replaced or moved from their parent stream, such as when the parent stream is an FSB file.";
|
||||||
|
case RESULT.ERR_TAGNOTFOUND:
|
||||||
|
return "The specified tag could not be found or there are no tags.";
|
||||||
|
case RESULT.ERR_TOOMANYCHANNELS:
|
||||||
|
return "The sound created exceeds the allowable input channel count. This can be increased using the 'maxinputchannels' parameter in System::setSoftwareFormat.";
|
||||||
|
case RESULT.ERR_TRUNCATED:
|
||||||
|
return "The retrieved string is too long to fit in the supplied buffer and has been truncated.";
|
||||||
|
case RESULT.ERR_UNIMPLEMENTED:
|
||||||
|
return "Something in FMOD hasn't been implemented when it should be. Contact support.";
|
||||||
|
case RESULT.ERR_UNINITIALIZED:
|
||||||
|
return "This command failed because System::init or System::setDriver was not called.";
|
||||||
|
case RESULT.ERR_UNSUPPORTED:
|
||||||
|
return "A command issued was not supported by this object. Possibly a plugin without certain callbacks specified.";
|
||||||
|
case RESULT.ERR_VERSION:
|
||||||
|
return "The version number of this file format is not supported.";
|
||||||
|
case RESULT.ERR_EVENT_ALREADY_LOADED:
|
||||||
|
return "The specified bank has already been loaded.";
|
||||||
|
case RESULT.ERR_EVENT_LIVEUPDATE_BUSY:
|
||||||
|
return "The live update connection failed due to the game already being connected.";
|
||||||
|
case RESULT.ERR_EVENT_LIVEUPDATE_MISMATCH:
|
||||||
|
return "The live update connection failed due to the game data being out of sync with the tool.";
|
||||||
|
case RESULT.ERR_EVENT_LIVEUPDATE_TIMEOUT:
|
||||||
|
return "The live update connection timed out.";
|
||||||
|
case RESULT.ERR_EVENT_NOTFOUND:
|
||||||
|
return "The requested event, bus or vca could not be found.";
|
||||||
|
case RESULT.ERR_STUDIO_UNINITIALIZED:
|
||||||
|
return "The Studio::System object is not yet initialized.";
|
||||||
|
case RESULT.ERR_STUDIO_NOT_LOADED:
|
||||||
|
return "The specified resource is not loaded, so it can't be unloaded.";
|
||||||
|
case RESULT.ERR_INVALID_STRING:
|
||||||
|
return "An invalid string was passed to this function.";
|
||||||
|
case RESULT.ERR_ALREADY_LOCKED:
|
||||||
|
return "The specified resource is already locked.";
|
||||||
|
case RESULT.ERR_NOT_LOCKED:
|
||||||
|
return "The specified resource is not locked, so it can't be unlocked.";
|
||||||
|
case RESULT.ERR_RECORD_DISCONNECTED:
|
||||||
|
return "The specified recording driver has been disconnected.";
|
||||||
|
case RESULT.ERR_TOOMANYSAMPLES:
|
||||||
|
return "The length provided exceed the allowable limit.";
|
||||||
|
default:
|
||||||
|
return "Unknown error.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Ghost.Editor.Core.SceneGraph;
|
using Ghost.Editor.Core.SceneGraph;
|
||||||
using Ghost.Entities;
|
using Ghost.Entities;
|
||||||
using Ghost.UnitTest.TestFramework;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace Ghost.UnitTest.Test;
|
namespace Ghost.UnitTest.Test;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ghost.Test.Core;
|
using Ghost.UnitTest.Windows;
|
||||||
using Ghost.UnitTest.Windows;
|
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
|
using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
global using static TerraFX.Interop.Windows.Windows;
|
global using static TerraFX.Interop.DirectX.D3D12;
|
||||||
global using static TerraFX.Interop.DirectX.DirectX;
|
global using static TerraFX.Interop.DirectX.DirectX;
|
||||||
global using static TerraFX.Interop.DirectX.D3D12;
|
|
||||||
global using static TerraFX.Interop.DirectX.DXGI;
|
global using static TerraFX.Interop.DirectX.DXGI;
|
||||||
|
global using static TerraFX.Interop.Windows.Windows;
|
||||||
using Ghost.Core.Attributes;
|
using Ghost.Core.Attributes;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.Versioning;
|
using System.Runtime.Versioning;
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
|
using Ghost.Core.Utilities;
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.Data;
|
using Ghost.Graphics.Data;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
|
using static TerraFX.Aliases.D3D_Alias;
|
||||||
using static TerraFX.Aliases.D3D12_Alias;
|
using static TerraFX.Aliases.D3D12_Alias;
|
||||||
using static TerraFX.Aliases.DXGI_Alias;
|
using static TerraFX.Aliases.DXGI_Alias;
|
||||||
using static TerraFX.Aliases.D3D_Alias;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics.D3D12;
|
namespace Ghost.Graphics.D3D12;
|
||||||
|
|
||||||
@@ -65,11 +66,13 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
Dispose();
|
Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ThrowIfDisposed()
|
private void ThrowIfDisposed()
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ThrowIfNotRecording()
|
private void ThrowIfNotRecording()
|
||||||
{
|
{
|
||||||
if (!_isRecording)
|
if (!_isRecording)
|
||||||
@@ -78,6 +81,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void IncrementCommandCount()
|
private void IncrementCommandCount()
|
||||||
{
|
{
|
||||||
_commandCount++;
|
_commandCount++;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Ghost.Core.Utilities;
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Core.Utilities;
|
||||||
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
{
|
{
|
||||||
_rtvHeap = new D3D12DescriptorHeap("rtv", device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, initialRtvCount, initialRtvCount / 2);
|
_rtvHeap = new D3D12DescriptorHeap("rtv", device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, initialRtvCount, initialRtvCount / 2);
|
||||||
_dsvHeap = new D3D12DescriptorHeap("dsv", device, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, initialDsvCount, initialDsvCount / 2);
|
_dsvHeap = new D3D12DescriptorHeap("dsv", device, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, initialDsvCount, initialDsvCount / 2);
|
||||||
_cbvSrvUavHeap = new D3D12DescriptorHeap("srv", device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, initialSrvCount, initialSrvCount /2);
|
_cbvSrvUavHeap = new D3D12DescriptorHeap("srv", device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, initialSrvCount, initialSrvCount / 2);
|
||||||
_samplerHeap = new D3D12DescriptorHeap("sampler", device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, initialSamplerCount, initialSamplerCount);
|
_samplerHeap = new D3D12DescriptorHeap("sampler", device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, initialSamplerCount, initialSamplerCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,52 +1,64 @@
|
|||||||
#undef USE_TRADITIONAL_BINDLESS
|
using Ghost.Core;
|
||||||
|
using Ghost.Core.Graphics;
|
||||||
using Ghost.Core;
|
using Ghost.Core.Utilities;
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.Data;
|
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
|
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||||
|
using Misaki.HighPerformance.Utilities;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
|
||||||
|
|
||||||
using static TerraFX.Aliases.D3D12_Alias;
|
|
||||||
using static TerraFX.Aliases.D3D_Alias;
|
using static TerraFX.Aliases.D3D_Alias;
|
||||||
using static TerraFX.Aliases.DXGI_Alias;
|
using static TerraFX.Aliases.D3D12_Alias;
|
||||||
|
|
||||||
namespace Ghost.Graphics.D3D12;
|
namespace Ghost.Graphics.D3D12;
|
||||||
|
|
||||||
// TODO: Fixed root signature and use bindless samplers and textures.
|
internal struct D3D12GraphicsCompiledResult : IDisposable
|
||||||
// This can dramatically reduce the number of root parameters needed and improve performance.
|
|
||||||
internal class D3D12ShaderPipeline : IShaderPipeline, IDisposable
|
|
||||||
{
|
{
|
||||||
public ComPtr<ID3D12PipelineState> pipelineState;
|
public CompileResult tsResult;
|
||||||
public D3D12ShaderCompiler.CompileResult vsResult;
|
public CompileResult msResult;
|
||||||
public D3D12ShaderCompiler.CompileResult psResult;
|
public CompileResult psResult;
|
||||||
public D3D12ShaderCompiler.CompileResult csResult;
|
|
||||||
|
|
||||||
public PipelineType Type
|
|
||||||
{
|
|
||||||
get; init;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
pipelineState.Dispose();
|
tsResult.Dispose();
|
||||||
vsResult.Dispose();
|
msResult.Dispose();
|
||||||
psResult.Dispose();
|
psResult.Dispose();
|
||||||
csResult.Dispose();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal struct D3D12PipelineState : IDisposable
|
||||||
|
{
|
||||||
|
// NOTE: This is just a temporary cache for compiled shader code. We will implement a proper disk cache later.
|
||||||
|
public D3D12GraphicsCompiledResult compileResult;
|
||||||
|
public D3DX12_MESH_SHADER_PIPELINE_STATE_DESC psoDesc;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
compileResult.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||||
{
|
{
|
||||||
|
private const int _ROOT_PARAM_COUNT =
|
||||||
|
#if USE_TRADITIONAL_BINDLESS
|
||||||
|
6
|
||||||
|
#else
|
||||||
|
4
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
private readonly D3D12RenderDevice _device;
|
private readonly D3D12RenderDevice _device;
|
||||||
private readonly D3D12ResourceDatabase _resourceDatabase;
|
private readonly D3D12ResourceDatabase _resourceDatabase;
|
||||||
|
|
||||||
private ComPtr<ID3D12PipelineLibrary1> _library;
|
private ComPtr<ID3D12PipelineLibrary1> _library;
|
||||||
private ComPtr<ID3D12RootSignature> _defaultRootSignature;
|
private ComPtr<ID3D12RootSignature> _defaultRootSignature;
|
||||||
|
|
||||||
private readonly Dictionary<Identifier<Shader>, D3D12ShaderPipeline> _shaderPipelines;
|
private readonly Dictionary<GraphicsPipelineKey, D3D12PipelineState> _pipelineCache;
|
||||||
|
|
||||||
public ID3D12RootSignature* DefaultRootSignature => _defaultRootSignature.Get();
|
public ID3D12RootSignature* DefaultRootSignature => _defaultRootSignature.Get();
|
||||||
|
|
||||||
@@ -55,20 +67,20 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
|||||||
_device = device;
|
_device = device;
|
||||||
_resourceDatabase = resourceDatabase;
|
_resourceDatabase = resourceDatabase;
|
||||||
|
|
||||||
_shaderPipelines = new();
|
_pipelineCache = new();
|
||||||
|
|
||||||
InitializePipelineLibrary(cachePath);
|
InitializeLibrary(cachePath);
|
||||||
CreateDefaultRootSignature();
|
CreateDefaultRootSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializePipelineLibrary(string? cachePath)
|
private void InitializeLibrary(string? filePath)
|
||||||
{
|
{
|
||||||
if (!File.Exists(cachePath))
|
if (!File.Exists(filePath))
|
||||||
{
|
{
|
||||||
_device.NativeDevice->CreatePipelineLibrary(null, 0, __uuidof<ID3D12PipelineLibrary1>(), _library.GetVoidAddressOf()).ThrowIfFailed();
|
_device.NativeDevice->CreatePipelineLibrary(null, 0, __uuidof<ID3D12PipelineLibrary1>(), _library.GetVoidAddressOf()).ThrowIfFailed();
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileBytes = File.ReadAllBytes(cachePath!);
|
var fileBytes = File.ReadAllBytes(filePath!);
|
||||||
fixed (byte* pFileBytes = fileBytes)
|
fixed (byte* pFileBytes = fileBytes)
|
||||||
{
|
{
|
||||||
_device.NativeDevice->CreatePipelineLibrary(pFileBytes, (nuint)fileBytes.Length, __uuidof<ID3D12PipelineLibrary1>(), _library.GetVoidAddressOf()).ThrowIfFailed();
|
_device.NativeDevice->CreatePipelineLibrary(pFileBytes, (nuint)fileBytes.Length, __uuidof<ID3D12PipelineLibrary1>(), _library.GetVoidAddressOf()).ThrowIfFailed();
|
||||||
@@ -77,18 +89,10 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
|||||||
|
|
||||||
private void CreateDefaultRootSignature()
|
private void CreateDefaultRootSignature()
|
||||||
{
|
{
|
||||||
const int rootParamCount =
|
|
||||||
#if USE_TRADITIONAL_BINDLESS
|
|
||||||
6
|
|
||||||
#else
|
|
||||||
4
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
|
|
||||||
_defaultRootSignature = default;
|
_defaultRootSignature = default;
|
||||||
|
|
||||||
// NOTE: Since we are targeting SM 6.6, we can use ResourceDescriptorHeap and SamplerDescriptorHeap directly without needing to set up descriptor tables.
|
// NOTE: Since we are targeting SM 6.6, we can use ResourceDescriptorHeap and SamplerDescriptorHeap directly without needing to set up descriptor tables.
|
||||||
var rootParameters = stackalloc D3D12_ROOT_PARAMETER1[rootParamCount];
|
var rootParameters = stackalloc D3D12_ROOT_PARAMETER1[_ROOT_PARAM_COUNT];
|
||||||
rootParameters[0] = new D3D12_ROOT_PARAMETER1
|
rootParameters[0] = new D3D12_ROOT_PARAMETER1
|
||||||
{
|
{
|
||||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
|
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||||
@@ -151,7 +155,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
|||||||
|
|
||||||
var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC1
|
var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC1
|
||||||
{
|
{
|
||||||
NumParameters = rootParamCount,
|
NumParameters = _ROOT_PARAM_COUNT,
|
||||||
pParameters = rootParameters,
|
pParameters = rootParameters,
|
||||||
NumStaticSamplers = 0,
|
NumStaticSamplers = 0,
|
||||||
pStaticSamplers = null,
|
pStaticSamplers = null,
|
||||||
@@ -175,71 +179,227 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
|||||||
var serializeResult = D3D12SerializeVersionedRootSignature(&versionedDesc, signature.GetAddressOf(), error.GetAddressOf());
|
var serializeResult = D3D12SerializeVersionedRootSignature(&versionedDesc, signature.GetAddressOf(), error.GetAddressOf());
|
||||||
if (serializeResult.FAILED)
|
if (serializeResult.FAILED)
|
||||||
{
|
{
|
||||||
var errorMsg = error.Get() != null ? Marshal.PtrToStringAnsi((nint)error.Get()->GetBufferPointer()) : "Unknown error";
|
var errorMsg = error.Get() != null ? Marshal.PtrToStringUTF8((nint)error.Get()->GetBufferPointer()) : "Unknown error";
|
||||||
throw new InvalidOperationException($"Failed to serialize default root signature: {errorMsg}");
|
throw new InvalidOperationException($"Failed to serialize default root signature: {errorMsg}");
|
||||||
}
|
}
|
||||||
|
|
||||||
_device.NativeDevice->CreateRootSignature(0, signature.Get()->GetBufferPointer(), signature.Get()->GetBufferSize(),
|
ThrowIfFailed(_device.NativeDevice->CreateRootSignature(0, signature.Get()->GetBufferPointer(), signature.Get()->GetBufferSize(),
|
||||||
__uuidof<ID3D12RootSignature>(), _defaultRootSignature.GetVoidAddressOf()).ThrowIfFailed();
|
__uuidof<ID3D12RootSignature>(), _defaultRootSignature.GetVoidAddressOf()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StorePipeline(string psoIdentifier, ID3D12PipelineState* pso)
|
private static void ValidateReflectionData(ShaderReflectionData reflectionData)
|
||||||
{
|
{
|
||||||
_library.Get()->StorePipeline(psoIdentifier.AsSpan().GetUnsafePtr(), pso);
|
if (reflectionData.ConstantBuffers.Count != _ROOT_PARAM_COUNT)
|
||||||
}
|
|
||||||
|
|
||||||
public void* LoadGraphicsPipeline(string psoIdentifier)
|
|
||||||
{
|
|
||||||
if (_library.Get()->LoadGraphicsPipeline(psoIdentifier.AsSpan().GetUnsafePtr(), __uuidof<ID3D12PipelineState>(), out var pso).Failure)
|
|
||||||
{
|
{
|
||||||
return null;
|
throw new InvalidOperationException($"Shader reflection data has {reflectionData.ConstantBuffers.Count} constant buffers, expected {_ROOT_PARAM_COUNT}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return pso;
|
if (reflectionData.OtherResources.Count != 0)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Shader reflection data contains unsupported resource types. Only constant buffers are supported in the current root signature.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Validate Cbuffer sizes and bindings.
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CompileShader(Identifier<Shader> id, string shaderPath)
|
private static Result<D3D12GraphicsCompiledResult> CompileAndValidateFullPass(FullPassDescriptor descriptor)
|
||||||
{
|
{
|
||||||
var vsResult = D3D12ShaderCompiler.Compile(shaderPath, D3D12ShaderCompiler.ShaderStage.VertexShader, D3D12ShaderCompiler.CompilerVersion.SM_6_6);
|
static CompileResult CompileAndValidate(ref CompilerConfig config)
|
||||||
var psResult = D3D12ShaderCompiler.Compile(shaderPath, D3D12ShaderCompiler.ShaderStage.PixelShader, D3D12ShaderCompiler.CompilerVersion.SM_6_6);
|
|
||||||
|
|
||||||
ref var shader = ref _resourceDatabase.GetShaderReference(id);
|
|
||||||
|
|
||||||
D3D12ShaderCompiler.PerformDXCReflection(ref shader, vsResult.reflection.Get());
|
|
||||||
D3D12ShaderCompiler.PerformDXCReflection(ref shader, psResult.reflection.Get());
|
|
||||||
|
|
||||||
var shaderPipeline = new D3D12ShaderPipeline
|
|
||||||
{
|
{
|
||||||
Type = PipelineType.Graphics,
|
var reflectionBlob = default(IDxcBlob*);
|
||||||
vsResult = vsResult,
|
var result = D3D12ShaderCompiler.Compile(ref config, Allocator.Persistent, &reflectionBlob).GetValueOrThrow();
|
||||||
|
|
||||||
|
if (reflectionBlob != null)
|
||||||
|
{
|
||||||
|
var reflection = D3D12ShaderCompiler.PerformDXCReflection(reflectionBlob).GetValueOrThrow();
|
||||||
|
ValidateReflectionData(reflection);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tsResult = default(CompileResult);
|
||||||
|
var tsEntry = descriptor.taskShader;
|
||||||
|
if (tsEntry.IsCreated)
|
||||||
|
{
|
||||||
|
var config = new CompilerConfig
|
||||||
|
{
|
||||||
|
defines = descriptor.defines.AsSpan(),
|
||||||
|
includes = descriptor.includes.AsSpan(),
|
||||||
|
shaderPath = tsEntry.shader,
|
||||||
|
entryPoint = tsEntry.entry,
|
||||||
|
stage = ShaderStage.TaskShader,
|
||||||
|
tier = CompilerTier.Tier0,
|
||||||
|
optimizeLevel = CompilerOptimizeLevel.O3,
|
||||||
|
options = CompilerOption.KeepReflections,
|
||||||
|
};
|
||||||
|
|
||||||
|
tsResult = CompileAndValidate(ref config);
|
||||||
|
}
|
||||||
|
|
||||||
|
CompileResult msResult;
|
||||||
|
var msEntry = descriptor.meshShader;
|
||||||
|
if (msEntry.IsCreated)
|
||||||
|
{
|
||||||
|
var config = new CompilerConfig
|
||||||
|
{
|
||||||
|
defines = descriptor.defines.AsSpan(),
|
||||||
|
includes = descriptor.includes.AsSpan(),
|
||||||
|
shaderPath = msEntry.shader,
|
||||||
|
entryPoint = msEntry.entry,
|
||||||
|
stage = ShaderStage.MeshShader,
|
||||||
|
tier = CompilerTier.Tier0,
|
||||||
|
optimizeLevel = CompilerOptimizeLevel.O3,
|
||||||
|
options = CompilerOption.KeepReflections,
|
||||||
|
};
|
||||||
|
|
||||||
|
msResult = CompileAndValidate(ref config);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Result<D3D12GraphicsCompiledResult>.Fail("Mesh shader expected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
CompileResult psResult;
|
||||||
|
var psEntry = descriptor.pixelShader;
|
||||||
|
if (psEntry.IsCreated)
|
||||||
|
{
|
||||||
|
var config = new CompilerConfig
|
||||||
|
{
|
||||||
|
defines = descriptor.defines.AsSpan(),
|
||||||
|
includes = descriptor.includes.AsSpan(),
|
||||||
|
shaderPath = psEntry.shader,
|
||||||
|
entryPoint = psEntry.entry,
|
||||||
|
stage = ShaderStage.PixelShader,
|
||||||
|
tier = CompilerTier.Tier0,
|
||||||
|
optimizeLevel = CompilerOptimizeLevel.O3,
|
||||||
|
options = CompilerOption.KeepReflections,
|
||||||
|
};
|
||||||
|
|
||||||
|
psResult = CompileAndValidate(ref config);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Result<D3D12GraphicsCompiledResult>.Fail("Pixel shader expected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new D3D12GraphicsCompiledResult
|
||||||
|
{
|
||||||
|
tsResult = tsResult,
|
||||||
|
msResult = msResult,
|
||||||
psResult = psResult
|
psResult = psResult
|
||||||
};
|
};
|
||||||
|
|
||||||
_shaderPipelines[id] = shaderPipeline;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create PSO from SDL (Shader Definition Language) file
|
private static D3D12_COMPARISON_FUNC ToD3DCompare(ZTestOptions z) => z switch
|
||||||
private void CreatePipelineStateObject(D3D12ShaderPipeline shaderPipeline)
|
|
||||||
{
|
{
|
||||||
var psoDesc = new D3D12_GRAPHICS_PIPELINE_STATE_DESC
|
ZTestOptions.Disabled => D3D12_COMPARISON_FUNC_ALWAYS,
|
||||||
|
ZTestOptions.Less => D3D12_COMPARISON_FUNC_LESS,
|
||||||
|
ZTestOptions.LessEqual => D3D12_COMPARISON_FUNC_LESS_EQUAL,
|
||||||
|
ZTestOptions.Equal => D3D12_COMPARISON_FUNC_EQUAL,
|
||||||
|
ZTestOptions.GreaterEqual => D3D12_COMPARISON_FUNC_GREATER_EQUAL,
|
||||||
|
ZTestOptions.Greater => D3D12_COMPARISON_FUNC_GREATER,
|
||||||
|
ZTestOptions.NotEqual => D3D12_COMPARISON_FUNC_NOT_EQUAL,
|
||||||
|
ZTestOptions.Always => D3D12_COMPARISON_FUNC_ALWAYS,
|
||||||
|
_ => D3D12_COMPARISON_FUNC_LESS_EQUAL
|
||||||
|
};
|
||||||
|
|
||||||
|
private static D3D12_DEPTH_STENCIL_DESC BuildDepthStencil(ref readonly PipelineDescriptor pipeline)
|
||||||
|
{
|
||||||
|
var depthEnabled = pipeline.zTest != ZTestOptions.Disabled;
|
||||||
|
var writeEnabled = pipeline.zWrite == ZWriteOptions.On;
|
||||||
|
var cmp = ToD3DCompare(pipeline.zTest);
|
||||||
|
return D3D12_DEPTH_STENCIL_DESC.Create(depthEnabled, writeEnabled, cmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StorePassState(ShaderPassKey id, ref readonly D3D12GraphicsCompiledResult compiled, ref readonly PipelineDescriptor pipelineDescriptor, ReadOnlySpan<TextureFormat> rtvs, TextureFormat dsv)
|
||||||
|
{
|
||||||
|
var rtvCount = (uint)Math.Min(rtvs.Length, D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT);
|
||||||
|
|
||||||
|
var desc = new D3DX12_MESH_SHADER_PIPELINE_STATE_DESC
|
||||||
{
|
{
|
||||||
pRootSignature = _defaultRootSignature.Get(),
|
pRootSignature = _defaultRootSignature.Get(),
|
||||||
VS = new D3D12_SHADER_BYTECODE(shaderPipeline.vsResult.bytecode.GetUnsafePtr(), (nuint)shaderPipeline.vsResult.bytecode.Count),
|
MS = new D3D12_SHADER_BYTECODE(compiled.msResult.bytecode.GetUnsafePtr(), (nuint)compiled.msResult.bytecode.Count),
|
||||||
PS = new D3D12_SHADER_BYTECODE(shaderPipeline.psResult.bytecode.GetUnsafePtr(), (nuint)shaderPipeline.psResult.bytecode.Count),
|
PS = new D3D12_SHADER_BYTECODE(compiled.psResult.bytecode.GetUnsafePtr(), (nuint)compiled.psResult.bytecode.Count),
|
||||||
InputLayout = D3D12PipelineResource.InputLayoutDescription,
|
|
||||||
RasterizerState = D3D12_RASTERIZER_DESC.CULL_NONE,
|
|
||||||
BlendState = D3D12_BLEND_DESC.OPAQUE,
|
|
||||||
DepthStencilState = D3D12_DEPTH_STENCIL_DESC.DEFAULT,
|
|
||||||
SampleMask = uint.MaxValue,
|
|
||||||
PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
||||||
NumRenderTargets = 1,
|
SampleMask = UINT32_MAX,
|
||||||
SampleDesc = new DXGI_SAMPLE_DESC(1, 0),
|
SampleDesc = new DXGI_SAMPLE_DESC(1, 0),
|
||||||
DSVFormat = DXGI_FORMAT_UNKNOWN,
|
NumRenderTargets = rtvCount,
|
||||||
|
DSVFormat = dsv.ToD3D12Format(),
|
||||||
|
DepthStencilState = BuildDepthStencil(in pipelineDescriptor),
|
||||||
|
NodeMask = 0,
|
||||||
|
Flags = D3D12_PIPELINE_STATE_FLAG_NONE,
|
||||||
|
|
||||||
|
BlendState = pipelineDescriptor.blend switch
|
||||||
|
{
|
||||||
|
BlendOptions.Opaque => D3D12_BLEND_DESC.OPAQUE,
|
||||||
|
BlendOptions.Alpha => D3D12_BLEND_DESC.ALPHA_BLEND,
|
||||||
|
BlendOptions.Additive => D3D12_BLEND_DESC.ADDITIVE,
|
||||||
|
BlendOptions.Multiply => D3D12_BLEND_DESC.MULTIPLY,
|
||||||
|
BlendOptions.PremultipliedAlpha => D3D12_BLEND_DESC.PREMULTIPLIED,
|
||||||
|
_ => D3D12_BLEND_DESC.OPAQUE
|
||||||
|
},
|
||||||
|
RasterizerState = pipelineDescriptor.cull switch
|
||||||
|
{
|
||||||
|
CullOptions.Off => D3D12_RASTERIZER_DESC.CULL_NONE,
|
||||||
|
CullOptions.Front => D3D12_RASTERIZER_DESC.CULL_CLOCKWISE,
|
||||||
|
CullOptions.Back => D3D12_RASTERIZER_DESC.CULL_COUNTER_CLOCKWISE,
|
||||||
|
_ => D3D12_RASTERIZER_DESC.CULL_NONE
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
psoDesc.RTVFormats[0] = D3D12PipelineResource.SWAP_CHAIN_BACK_BUFFER_FORMAT;
|
if (compiled.tsResult.IsCreated)
|
||||||
|
{
|
||||||
|
desc.AS = new D3D12_SHADER_BYTECODE(compiled.tsResult.bytecode.GetUnsafePtr(), (nuint)compiled.tsResult.bytecode.Count);
|
||||||
|
}
|
||||||
|
|
||||||
_device.NativeDevice->CreateGraphicsPipelineState(&psoDesc, __uuidof<ID3D12PipelineState>(), shaderPipeline.pipelineState.GetVoidAddressOf());
|
var hash = new GraphicsPipelineHash
|
||||||
|
{
|
||||||
|
id = id,
|
||||||
|
rtvCount = rtvCount,
|
||||||
|
dsvFormat = dsv,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0; i < rtvCount && i < 6; i++)
|
||||||
|
{
|
||||||
|
desc.RTVFormats[i] = rtvs[i].ToD3D12Format();
|
||||||
|
desc.BlendState.RenderTarget[i].RenderTargetWriteMask = (byte)(pipelineDescriptor.colorMask & 0x0F);
|
||||||
|
hash.rtvFormats[i] = rtvs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
var key = hash.GetKey();
|
||||||
|
ref var existing = ref CollectionsMarshal.GetValueRefOrAddDefault(_pipelineCache, hash.GetKey(), out var exists);
|
||||||
|
if (exists)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Pass code cache already contains an entry for key: {key}");
|
||||||
|
}
|
||||||
|
|
||||||
|
existing.compileResult = compiled;
|
||||||
|
existing.psoDesc = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CompilePass(IPassDescriptor descriptor)
|
||||||
|
{
|
||||||
|
switch (descriptor)
|
||||||
|
{
|
||||||
|
case FullPassDescriptor fullPass:
|
||||||
|
var result = CompileAndValidateFullPass(fullPass).GetValueOrThrow();
|
||||||
|
StorePassState(new(fullPass.Identifier), in result, in fullPass.localPipeline, [TextureFormat.B8G8R8A8_UNorm], TextureFormat.Unknown);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Do we need to support other pass types?
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CompileShader(ShaderDescriptor descriptor)
|
||||||
|
{
|
||||||
|
foreach (var pass in descriptor.passes)
|
||||||
|
{
|
||||||
|
CompilePass(pass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Pipeline variants (keywords)
|
// TODO: Pipeline variants (keywords)
|
||||||
@@ -247,33 +407,67 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
|||||||
// TODO: Async compilation
|
// TODO: Async compilation
|
||||||
public void PreCookPipelineState()
|
public void PreCookPipelineState()
|
||||||
{
|
{
|
||||||
foreach (var kvp in _shaderPipelines)
|
foreach (var kvp in _pipelineCache)
|
||||||
{
|
{
|
||||||
ref var shader = ref _resourceDatabase.GetShaderReference(kvp.Key);
|
var key = kvp.Key;
|
||||||
|
var state = kvp.Value;
|
||||||
|
|
||||||
CreatePipelineStateObject(kvp.Value);
|
var streamDesc = new D3D12_PIPELINE_STATE_STREAM_DESC
|
||||||
|
{
|
||||||
|
pPipelineStateSubobjectStream = &state.psoDesc,
|
||||||
|
SizeInBytes = (nuint)sizeof(D3DX12_MESH_SHADER_PIPELINE_STATE_DESC)
|
||||||
|
};
|
||||||
|
|
||||||
kvp.Value.vsResult.Dispose();
|
ComPtr<ID3D12PipelineState> pipelineState = default;
|
||||||
kvp.Value.psResult.Dispose();
|
ThrowIfFailed(_device.NativeDevice->CreatePipelineState(&streamDesc, __uuidof<ID3D12PipelineState>(), pipelineState.GetVoidAddressOf()));
|
||||||
kvp.Value.csResult.Dispose();
|
|
||||||
|
var name = key.ToString();
|
||||||
|
fixed (char* pName = name)
|
||||||
|
{
|
||||||
|
ThrowIfFailed(_library.Get()->StorePipeline(pName, pipelineState.Get()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IShaderPipeline GetShaderPipeline(Identifier<Shader> id)
|
public ID3D12PipelineState* LoadPipelineState(GraphicsPipelineKey key)
|
||||||
{
|
{
|
||||||
if (_shaderPipelines.TryGetValue(id, out var pipeline))
|
var name = key.ToString();
|
||||||
|
var state = _pipelineCache[key];
|
||||||
|
var streamDesc = new D3D12_PIPELINE_STATE_STREAM_DESC
|
||||||
{
|
{
|
||||||
return pipeline;
|
pPipelineStateSubobjectStream = &state.psoDesc,
|
||||||
}
|
SizeInBytes = (nuint)sizeof(D3DX12_MESH_SHADER_PIPELINE_STATE_DESC)
|
||||||
|
};
|
||||||
|
|
||||||
throw new KeyNotFoundException($"Shader pipeline not found for shader ID: {id}");
|
fixed (char* pName = name)
|
||||||
|
{
|
||||||
|
ID3D12PipelineState* pipelineState;
|
||||||
|
ThrowIfFailed(_library.Get()->LoadPipeline(pName, &streamDesc, __uuidof<ID3D12PipelineState>(), (void**)&pipelineState));
|
||||||
|
|
||||||
|
return pipelineState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveLibraryToDisk(string filePath)
|
||||||
|
{
|
||||||
|
var size = _library.Get()->GetSerializedSize();
|
||||||
|
using var buffer = new UnsafeArray<byte>((int)size, Allocator.Persistent); // We use persistent heap allocation instead of stack allocation to avoid stack overflow for large pipeline libraries.
|
||||||
|
|
||||||
|
ThrowIfFailed(_library.Get()->Serialize(buffer.GetUnsafePtr(), size));
|
||||||
|
|
||||||
|
var fs = File.Open(filePath, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||||
|
fs.Write(buffer.AsSpan());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
foreach (var kvp in _shaderPipelines)
|
_defaultRootSignature.Dispose();
|
||||||
|
|
||||||
|
foreach (var kvp in _pipelineCache)
|
||||||
{
|
{
|
||||||
kvp.Value.Dispose();
|
kvp.Value.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_library.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Ghost.Core.Utilities;
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
@@ -34,9 +35,9 @@ internal unsafe class D3D12RenderDevice : IRenderDevice
|
|||||||
{
|
{
|
||||||
InitializeDevice();
|
InitializeDevice();
|
||||||
|
|
||||||
_graphicsQueue = new D3D12CommandQueue(_device, CommandQueueType.Graphics);
|
_graphicsQueue = new D3D12CommandQueue(_device.Get(), CommandQueueType.Graphics);
|
||||||
_computeQueue = new D3D12CommandQueue(_device, CommandQueueType.Compute);
|
_computeQueue = new D3D12CommandQueue(_device.Get(), CommandQueueType.Compute);
|
||||||
_copyQueue = new D3D12CommandQueue(_device, CommandQueueType.Copy);
|
_copyQueue = new D3D12CommandQueue(_device.Get(), CommandQueueType.Copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
~D3D12RenderDevice()
|
~D3D12RenderDevice()
|
||||||
@@ -52,7 +53,7 @@ internal unsafe class D3D12RenderDevice : IRenderDevice
|
|||||||
CreateDXGIFactory2(FALSE, __uuidof<IDXGIFactory7>(), _dxgiFactory.GetVoidAddressOf());
|
CreateDXGIFactory2(FALSE, __uuidof<IDXGIFactory7>(), _dxgiFactory.GetVoidAddressOf());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using ComPtr<IDXGIAdapter1> adapter = default;
|
ComPtr<IDXGIAdapter1> adapter = default;
|
||||||
|
|
||||||
for (uint adapterIndex = 0;
|
for (uint adapterIndex = 0;
|
||||||
_dxgiFactory.Get()->EnumAdapterByGpuPreference(adapterIndex, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, __uuidof<IDXGIAdapter1>(), adapter.ReleaseAndGetVoidAddressOf()).SUCCEEDED;
|
_dxgiFactory.Get()->EnumAdapterByGpuPreference(adapterIndex, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, __uuidof<IDXGIAdapter1>(), adapter.ReleaseAndGetVoidAddressOf()).SUCCEEDED;
|
||||||
@@ -76,6 +77,7 @@ internal unsafe class D3D12RenderDevice : IRenderDevice
|
|||||||
|
|
||||||
if (_device.Get() == null)
|
if (_device.Get() == null)
|
||||||
{
|
{
|
||||||
|
adapter.Dispose(); // Dispose the last adapter we tried. If the operation succeeded, we would have moved it.
|
||||||
throw new PlatformNotSupportedException("Cannot create ID3D12Device with feature level 12.0");
|
throw new PlatformNotSupportedException("Cannot create ID3D12Device with feature level 12.0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Core.Graphics;
|
using Ghost.Core.Graphics;
|
||||||
|
using Ghost.Core.Utilities;
|
||||||
using Ghost.Graphics.Data;
|
using Ghost.Graphics.Data;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
@@ -28,17 +29,6 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
|
|
||||||
private UnsafeQueue<Handle<GPUResource>> _temResources = new(64, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
private UnsafeQueue<Handle<GPUResource>> _temResources = new(64, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
||||||
|
|
||||||
private Guid* IID_NULL
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
fixed (Guid* pGuid = &Guid.Empty)
|
|
||||||
{
|
|
||||||
return pGuid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public D3D12ResourceAllocator(RenderSystem renderSystem, D3D12RenderDevice device, D3D12DescriptorAllocator descriptorAllocator, D3D12ResourceDatabase resourceDatabase)
|
public D3D12ResourceAllocator(RenderSystem renderSystem, D3D12RenderDevice device, D3D12DescriptorAllocator descriptorAllocator, D3D12ResourceDatabase resourceDatabase)
|
||||||
{
|
{
|
||||||
var desc = new D3D12MA_ALLOCATOR_DESC
|
var desc = new D3D12MA_ALLOCATOR_DESC
|
||||||
@@ -62,7 +52,7 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static void CheckBufferSize(uint sizeInBytes)
|
private static void CheckBufferSize(ulong sizeInBytes)
|
||||||
{
|
{
|
||||||
if (sizeInBytes > _MAX_BYTES)
|
if (sizeInBytes > _MAX_BYTES)
|
||||||
{
|
{
|
||||||
@@ -409,7 +399,7 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
var initialState = DetermineInitialTextureState(desc.Usage);
|
var initialState = DetermineInitialTextureState(desc.Usage);
|
||||||
|
|
||||||
ComPtr<D3D12MA_Allocation> allocation = default;
|
ComPtr<D3D12MA_Allocation> allocation = default;
|
||||||
ThrowIfFailed(_allocator.Get()->CreateResource(&allocationDesc, &resourceDesc, initialState, null, allocation.GetAddressOf(), IID_NULL, null));
|
ThrowIfFailed(_allocator.Get()->CreateResource(&allocationDesc, &resourceDesc, initialState, null, allocation.GetAddressOf(), Win32Utility.IID_NULL, null));
|
||||||
|
|
||||||
var resourceDescriptor = ResourceViewGroup.Invalid;
|
var resourceDescriptor = ResourceViewGroup.Invalid;
|
||||||
if (desc.Usage.HasFlag(TextureUsage.ShaderResource))
|
if (desc.Usage.HasFlag(TextureUsage.ShaderResource))
|
||||||
@@ -482,8 +472,8 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
var initialState = DetermineInitialBufferState(desc.Usage, desc.MemoryType);
|
var initialState = DetermineInitialBufferState(desc.Usage, desc.MemoryType);
|
||||||
|
|
||||||
ComPtr<D3D12MA_Allocation> allocation = default;
|
ComPtr<D3D12MA_Allocation> allocation = default;
|
||||||
ThrowIfFailed(_allocator.Get()->CreateResource(&allocationDesc, &resourceDescription, initialState, null, allocation.GetAddressOf(), IID_NULL, null));
|
ThrowIfFailed(_allocator.Get()->CreateResource(&allocationDesc, &resourceDescription, initialState, null, allocation.GetAddressOf(), Win32Utility.IID_NULL, null));
|
||||||
|
|
||||||
var resourceDescriptor = ResourceViewGroup.Invalid;
|
var resourceDescriptor = ResourceViewGroup.Invalid;
|
||||||
if (desc.Usage.HasFlag(BufferUsage.ShaderResource))
|
if (desc.Usage.HasFlag(BufferUsage.ShaderResource))
|
||||||
{
|
{
|
||||||
@@ -499,7 +489,7 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
{
|
{
|
||||||
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
|
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
|
||||||
srvDesc.Buffer.FirstElement = 0;
|
srvDesc.Buffer.FirstElement = 0;
|
||||||
srvDesc.Buffer.NumElements = desc.Size / 4;
|
srvDesc.Buffer.NumElements = (uint)(desc.Size / 4u);
|
||||||
srvDesc.Buffer.StructureByteStride = 0;
|
srvDesc.Buffer.StructureByteStride = 0;
|
||||||
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
|
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
|
||||||
}
|
}
|
||||||
@@ -507,7 +497,7 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
{
|
{
|
||||||
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
|
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||||
srvDesc.Buffer.FirstElement = 0;
|
srvDesc.Buffer.FirstElement = 0;
|
||||||
srvDesc.Buffer.NumElements = desc.Size / desc.Stride;
|
srvDesc.Buffer.NumElements = (uint)(desc.Size / desc.Stride);
|
||||||
srvDesc.Buffer.StructureByteStride = desc.Stride;
|
srvDesc.Buffer.StructureByteStride = desc.Stride;
|
||||||
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
|
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
|
||||||
}
|
}
|
||||||
@@ -519,13 +509,13 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
return handle.AsGraphicsBuffer();
|
return handle.AsGraphicsBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Handle<GraphicsBuffer> CreateUploadBuffer(uint size, bool isTemp = true)
|
public Handle<GraphicsBuffer> CreateUploadBuffer(ulong size, bool isTemp = true)
|
||||||
{
|
{
|
||||||
var desc = new BufferDesc
|
var desc = new BufferDesc
|
||||||
{
|
{
|
||||||
Size = size,
|
Size = size,
|
||||||
Usage = BufferUsage.Upload,
|
Usage = BufferUsage.Upload,
|
||||||
MemoryType = MemoryType.Upload,
|
MemoryType = ResourceMemoryType.Upload,
|
||||||
};
|
};
|
||||||
|
|
||||||
return CreateBuffer(ref desc, isTemp);
|
return CreateBuffer(ref desc, isTemp);
|
||||||
@@ -538,7 +528,7 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
Size = (uint)(vertices.Count * Unsafe.SizeOf<Vertex>()),
|
Size = (uint)(vertices.Count * Unsafe.SizeOf<Vertex>()),
|
||||||
Stride = (uint)Unsafe.SizeOf<Vertex>(),
|
Stride = (uint)Unsafe.SizeOf<Vertex>(),
|
||||||
Usage = BufferUsage.Vertex | BufferUsage.ShaderResource,
|
Usage = BufferUsage.Vertex | BufferUsage.ShaderResource,
|
||||||
MemoryType = MemoryType.Default,
|
MemoryType = ResourceMemoryType.Default,
|
||||||
};
|
};
|
||||||
|
|
||||||
var indexBufferDesc = new BufferDesc
|
var indexBufferDesc = new BufferDesc
|
||||||
@@ -546,7 +536,7 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
Size = (uint)(indices.Count * sizeof(uint)),
|
Size = (uint)(indices.Count * sizeof(uint)),
|
||||||
Stride = sizeof(uint),
|
Stride = sizeof(uint),
|
||||||
Usage = BufferUsage.Index | BufferUsage.ShaderResource,
|
Usage = BufferUsage.Index | BufferUsage.ShaderResource,
|
||||||
MemoryType = MemoryType.Default,
|
MemoryType = ResourceMemoryType.Default,
|
||||||
};
|
};
|
||||||
|
|
||||||
var vertexBuffer = CreateBuffer(ref vertexBufferDesc);
|
var vertexBuffer = CreateBuffer(ref vertexBufferDesc);
|
||||||
@@ -572,11 +562,13 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
|
|
||||||
ref var shaderRef = ref _resourceDatabase.GetShaderReference(shader);
|
ref var shaderRef = ref _resourceDatabase.GetShaderReference(shader);
|
||||||
|
|
||||||
|
// TODO: Get per-material constant buffer size from database
|
||||||
|
|
||||||
var desc = new BufferDesc
|
var desc = new BufferDesc
|
||||||
{
|
{
|
||||||
Size = shaderRef.PerMaterialBufferInfo.Size,
|
Size = shaderRef.PerMaterialBufferInfo.Size,
|
||||||
Usage = BufferUsage.Constant,
|
Usage = BufferUsage.Constant,
|
||||||
MemoryType = MemoryType.Default,
|
MemoryType = ResourceMemoryType.Default,
|
||||||
};
|
};
|
||||||
|
|
||||||
var buffer = CreateBuffer(ref desc);
|
var buffer = CreateBuffer(ref desc);
|
||||||
@@ -641,13 +633,13 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static D3D12_HEAP_TYPE ConvertMemoryType(MemoryType memoryType)
|
private static D3D12_HEAP_TYPE ConvertMemoryType(ResourceMemoryType memoryType)
|
||||||
{
|
{
|
||||||
return memoryType switch
|
return memoryType switch
|
||||||
{
|
{
|
||||||
MemoryType.Default => D3D12_HEAP_TYPE_DEFAULT,
|
ResourceMemoryType.Default => D3D12_HEAP_TYPE_DEFAULT,
|
||||||
MemoryType.Upload => D3D12_HEAP_TYPE_UPLOAD,
|
ResourceMemoryType.Upload => D3D12_HEAP_TYPE_UPLOAD,
|
||||||
MemoryType.Readback => D3D12_HEAP_TYPE_READBACK,
|
ResourceMemoryType.Readback => D3D12_HEAP_TYPE_READBACK,
|
||||||
_ => throw new ArgumentException($"Unsupported memory type: {memoryType}")
|
_ => throw new ArgumentException($"Unsupported memory type: {memoryType}")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -672,14 +664,14 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
|||||||
return D3D12_RESOURCE_STATE_COMMON;
|
return D3D12_RESOURCE_STATE_COMMON;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static D3D12_RESOURCE_STATES DetermineInitialBufferState(BufferUsage usage, MemoryType memoryType)
|
private static D3D12_RESOURCE_STATES DetermineInitialBufferState(BufferUsage usage, ResourceMemoryType memoryType)
|
||||||
{
|
{
|
||||||
if (memoryType == MemoryType.Upload)
|
if (memoryType == ResourceMemoryType.Upload)
|
||||||
{
|
{
|
||||||
return D3D12_RESOURCE_STATE_GENERIC_READ;
|
return D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memoryType == MemoryType.Readback)
|
if (memoryType == ResourceMemoryType.Readback)
|
||||||
{
|
{
|
||||||
return D3D12_RESOURCE_STATE_COPY_DEST;
|
return D3D12_RESOURCE_STATE_COPY_DEST;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
|
||||||
using Ghost.Graphics.Data;
|
using Ghost.Graphics.Data;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.Collections;
|
using Misaki.HighPerformance.Collections;
|
||||||
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
@@ -12,7 +12,7 @@ namespace Ghost.Graphics.D3D12;
|
|||||||
|
|
||||||
internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||||
{
|
{
|
||||||
internal unsafe struct ResourceInfo
|
internal unsafe struct ResourceRecord
|
||||||
{
|
{
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
public struct ResourceUnion
|
public struct ResourceUnion
|
||||||
@@ -36,14 +36,14 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
public ResourceDesc desc;
|
public ResourceDesc desc;
|
||||||
public ResourceViewGroup descriptor;
|
public ResourceViewGroup descriptor;
|
||||||
public ResourceUnion resourceUnion;
|
public ResourceUnion resourceUnion;
|
||||||
public uint cpuFenceValue;
|
|
||||||
public ResourceState state;
|
public ResourceState state;
|
||||||
|
public uint cpuFenceValue;
|
||||||
public readonly bool isExternal;
|
public readonly bool isExternal;
|
||||||
|
|
||||||
public readonly bool Allocated => isExternal ? resourceUnion.resource.Get() != null : resourceUnion.allocation.Get()->IsNotNull;
|
public readonly bool Allocated => isExternal ? resourceUnion.resource.Get() != null : resourceUnion.allocation.Get() != null;
|
||||||
public readonly ID3D12Resource* ResourcePtr => isExternal ? resourceUnion.resource.Get() : resourceUnion.allocation.Get()->GetResource();
|
public readonly ID3D12Resource* ResourcePtr => isExternal ? resourceUnion.resource.Get() : resourceUnion.allocation.Get()->GetResource();
|
||||||
|
|
||||||
public ResourceInfo(ComPtr<D3D12MA_Allocation> allocation, uint cpuFenceValue, ResourceState state, ResourceViewGroup resourceDescriptor, ResourceDesc desc)
|
public ResourceRecord(ComPtr<D3D12MA_Allocation> allocation, uint cpuFenceValue, ResourceState state, ResourceViewGroup resourceDescriptor, ResourceDesc desc)
|
||||||
{
|
{
|
||||||
this.resourceUnion = new ResourceUnion(allocation);
|
this.resourceUnion = new ResourceUnion(allocation);
|
||||||
this.isExternal = false;
|
this.isExternal = false;
|
||||||
@@ -54,7 +54,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
this.desc = desc;
|
this.desc = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceInfo(ComPtr<ID3D12Resource> resource, ResourceState state)
|
public ResourceRecord(ComPtr<ID3D12Resource> resource, ResourceState state)
|
||||||
{
|
{
|
||||||
this.resourceUnion = new ResourceUnion(resource);
|
this.resourceUnion = new ResourceUnion(resource);
|
||||||
this.isExternal = true;
|
this.isExternal = true;
|
||||||
@@ -65,24 +65,26 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
this.desc = ResourceDesc.FromD3D12(resource.Get()->GetDesc());
|
this.desc = ResourceDesc.FromD3D12(resource.Get()->GetDesc());
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint Release()
|
public uint Release(D3D12DescriptorAllocator descriptorAllocator)
|
||||||
{
|
{
|
||||||
var refCount = 0u;
|
var refCount = 0u;
|
||||||
if (Allocated)
|
if (Allocated)
|
||||||
{
|
{
|
||||||
if (isExternal)
|
if (isExternal)
|
||||||
{
|
{
|
||||||
refCount = resourceUnion.resource.Get()->Release();
|
refCount = resourceUnion.resource.Reset();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
refCount = resourceUnion.allocation.Get()->Release();
|
refCount = resourceUnion.allocation.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceUnion = default;
|
resourceUnion = default;
|
||||||
descriptor = default;
|
descriptor = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
descriptorAllocator.Release(descriptor);
|
||||||
|
|
||||||
return refCount;
|
return refCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,31 +95,33 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
public bool occupied;
|
public bool occupied;
|
||||||
}
|
}
|
||||||
|
|
||||||
private UnsafeSlotMap<ResourceInfo> _resources;
|
private readonly D3D12DescriptorAllocator _descriptorAllocator;
|
||||||
|
|
||||||
|
private UnsafeSlotMap<ResourceRecord> _resources;
|
||||||
#if DEBUG || GHOST_EDITOR
|
#if DEBUG || GHOST_EDITOR
|
||||||
private readonly Dictionary<ResourceInfo, string> _resourceName;
|
private readonly Dictionary<ResourceRecord, string> _resourceName;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private readonly UnsafeSlotMap<Mesh> _meshes;
|
private readonly UnsafeSlotMap<Mesh> _meshes;
|
||||||
private readonly UnsafeSlotMap<Material> _materials;
|
private readonly UnsafeSlotMap<Material> _materials;
|
||||||
|
|
||||||
// NOTE: We use a simple list since shader is not frequently added/removed. This can save 4 bytes for each ecs component.
|
// NOTE: We use a simple list since shaderSlot is not frequently added/removed. This can save 4 bytes for each ecs component.
|
||||||
private readonly DynamicArray<Slot<Shader>> _shaders;
|
private readonly DynamicArray<Slot<Shader>> _shaders;
|
||||||
|
private readonly Dictionary<ShaderPassKey, ShaderPass> _shaderPasses;
|
||||||
private readonly D3D12DescriptorAllocator _descriptorAllocator;
|
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
public D3D12ResourceDatabase(D3D12DescriptorAllocator descriptorAllocator)
|
public D3D12ResourceDatabase(D3D12DescriptorAllocator descriptorAllocator)
|
||||||
{
|
{
|
||||||
_resources = new(64, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
_resources = new(64, Allocator.Persistent);
|
||||||
#if DEBUG || GHOST_EDITOR
|
#if DEBUG || GHOST_EDITOR
|
||||||
_resourceName = new(64);
|
_resourceName = new(64);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_meshes = new(64, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
_meshes = new(64, Allocator.Persistent);
|
||||||
_materials = new(16, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
_materials = new(16, Allocator.Persistent);
|
||||||
_shaders = new(16);
|
_shaders = new(16);
|
||||||
|
_shaderPasses = new(16);
|
||||||
|
|
||||||
_descriptorAllocator = descriptorAllocator;
|
_descriptorAllocator = descriptorAllocator;
|
||||||
}
|
}
|
||||||
@@ -127,6 +131,12 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
Dispose();
|
Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ReleaseResource<T>(ref T resource)
|
||||||
|
where T : IResourceReleasable
|
||||||
|
{
|
||||||
|
resource.ReleaseResource(this);
|
||||||
|
}
|
||||||
|
|
||||||
public Handle<GPUResource> ImportExternalResource<T>(T resource, ResourceState initialState)
|
public Handle<GPUResource> ImportExternalResource<T>(T resource, ResourceState initialState)
|
||||||
where T : unmanaged
|
where T : unmanaged
|
||||||
{
|
{
|
||||||
@@ -137,7 +147,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
throw new InvalidOperationException($"Expect ComPtr<ID3D12Resource> in D3D12ResourceDatabase, but got {typeof(T)}.");
|
throw new InvalidOperationException($"Expect ComPtr<ID3D12Resource> in D3D12ResourceDatabase, but got {typeof(T)}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var id = _resources.Add(new ResourceInfo(d3d12Resource, initialState), out var generation);
|
var id = _resources.Add(new ResourceRecord(d3d12Resource, initialState), out var generation);
|
||||||
return new Handle<GPUResource>(id, generation);
|
return new Handle<GPUResource>(id, generation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,11 +155,11 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
var id = _resources.Add(new ResourceInfo(allocation, cpuFenceValue, initialState, resourceDescriptor, desc), out var generation);
|
var id = _resources.Add(new ResourceRecord(allocation, cpuFenceValue, initialState, resourceDescriptor, desc), out var generation);
|
||||||
return new Handle<GPUResource>(id, generation);
|
return new Handle<GPUResource>(id, generation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref ResourceInfo GetResourceInfo(Handle<GPUResource> handle)
|
public ref ResourceRecord GetResourceInfo(Handle<GPUResource> handle)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -162,7 +172,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
return ref info;
|
return ref info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref ResourceInfo GetResourceInfo(Handle<GPUResource> handle, out bool exist)
|
public ref ResourceRecord GetResourceInfo(Handle<GPUResource> handle, out bool exist)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
return ref _resources.GetElementReferenceAt(handle.id, handle.generation, out exist);
|
return ref _resources.GetElementReferenceAt(handle.id, handle.generation, out exist);
|
||||||
@@ -232,7 +242,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var refCount = info.Release();
|
var refCount = info.Release(_descriptorAllocator);
|
||||||
#if DEBUG || GHOST_EDITOR
|
#if DEBUG || GHOST_EDITOR
|
||||||
if (refCount > 0)
|
if (refCount > 0)
|
||||||
{
|
{
|
||||||
@@ -268,28 +278,15 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
return ref mesh;
|
return ref mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReleaseMeshResources(ref readonly Mesh mesh)
|
|
||||||
{
|
|
||||||
mesh.ReleaseCpuResources();
|
|
||||||
|
|
||||||
ref var vertexRef = ref GetResourceInfo(mesh.vertexBuffer.AsResource());
|
|
||||||
ref var indexRef = ref GetResourceInfo(mesh.indexBuffer.AsResource());
|
|
||||||
_descriptorAllocator.Release(vertexRef.descriptor);
|
|
||||||
_descriptorAllocator.Release(indexRef.descriptor);
|
|
||||||
|
|
||||||
ReleaseResource(mesh.vertexBuffer.AsResource());
|
|
||||||
ReleaseResource(mesh.indexBuffer.AsResource());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReleaseMesh(Handle<Mesh> handle)
|
public void ReleaseMesh(Handle<Mesh> handle)
|
||||||
{
|
{
|
||||||
ref var meshSlot = ref _meshes.GetElementReferenceAt(handle.id, handle.generation, out var exist);
|
ref var mesh = ref _meshes.GetElementReferenceAt(handle.id, handle.generation, out var exist);
|
||||||
if (!exist)
|
if (!exist)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReleaseMeshResources(ref meshSlot);
|
ReleaseResource(ref mesh);
|
||||||
_meshes.Remove(handle.id, handle.generation);
|
_meshes.Remove(handle.id, handle.generation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +323,8 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
material.Dispose();
|
ReleaseResource(ref material);
|
||||||
|
_materials.Remove(handle.id, handle.generation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier<Shader> AddShader(ref readonly Shader shader)
|
public Identifier<Shader> AddShader(ref readonly Shader shader)
|
||||||
@@ -355,17 +353,39 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
|||||||
return ref shader;
|
return ref shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReleaseShader(Identifier<Shader> handle)
|
public void ReleaseShader(Identifier<Shader> id)
|
||||||
{
|
{
|
||||||
if (!HasShader(handle))
|
if (!HasShader(id))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref var shader = ref _shaders[handle.value].value;
|
ref var shaderSlot = ref _shaders[id.value];
|
||||||
shader.Dispose();
|
|
||||||
|
ReleaseResource(ref shaderSlot.value);
|
||||||
|
shaderSlot.occupied = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddShaderPass(ShaderPassKey passKey, ShaderPass pass)
|
||||||
|
{
|
||||||
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
_shaderPasses.Add(passKey, pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShaderPass GetShaderPass(ShaderPassKey passKey)
|
||||||
|
{
|
||||||
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
if (!_shaderPasses.TryGetValue(passKey, out var pass))
|
||||||
|
{
|
||||||
|
throw new KeyNotFoundException($"Shader pass '{passKey}' not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should we need to release the shaderSlot pass?
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#undef SUPPORT_TEXTURE_BINDING
|
using Ghost.Core;
|
||||||
|
using Ghost.Core.Utilities;
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.Data;
|
using Ghost.Graphics.RHI;
|
||||||
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
|
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
@@ -10,63 +12,192 @@ using TerraFX.Interop.Windows;
|
|||||||
|
|
||||||
namespace Ghost.Graphics.D3D12;
|
namespace Ghost.Graphics.D3D12;
|
||||||
|
|
||||||
internal unsafe static class D3D12ShaderCompiler
|
internal unsafe struct CompileResult : IDisposable
|
||||||
{
|
{
|
||||||
public enum CompilerVersion
|
public UnsafeArray<byte> bytecode;
|
||||||
|
|
||||||
|
public readonly bool IsCreated => bytecode.IsCreated;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
{
|
{
|
||||||
SM_6_6,
|
bytecode.Dispose();
|
||||||
SM_7_0
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal readonly struct CBufferVariableInfo
|
||||||
|
{
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get; init;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ShaderStage
|
public uint StartOffset
|
||||||
{
|
{
|
||||||
VertexShader,
|
get; init;
|
||||||
PixelShader,
|
|
||||||
MeshShader,
|
|
||||||
ComputeShader
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct CompileResult : IDisposable
|
public uint Size
|
||||||
{
|
{
|
||||||
public UnsafeArray<byte> bytecode;
|
get; init;
|
||||||
public ComPtr<IDxcBlob> reflection;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
internal readonly struct CBufferInfo
|
||||||
{
|
{
|
||||||
bytecode.Dispose();
|
public string Name
|
||||||
reflection.Dispose();
|
{
|
||||||
}
|
get; init;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetProfileString(ShaderStage stage, CompilerVersion version)
|
public uint RegisterSlot
|
||||||
|
{
|
||||||
|
get; init;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint RegisterSpace
|
||||||
|
{
|
||||||
|
get; init;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint SizeInBytes
|
||||||
|
{
|
||||||
|
get; init;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReadOnlyList<CBufferVariableInfo> Variables
|
||||||
|
{
|
||||||
|
get; init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal readonly struct ResourceBindingInfo
|
||||||
|
{
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get; init;
|
||||||
|
}
|
||||||
|
|
||||||
|
public D3D_SHADER_INPUT_TYPE Type
|
||||||
|
{
|
||||||
|
get; init;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint BindPoint
|
||||||
|
{
|
||||||
|
get; init;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint BindCount
|
||||||
|
{
|
||||||
|
get; init;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint Space
|
||||||
|
{
|
||||||
|
get; init;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal readonly struct ShaderReflectionData
|
||||||
|
{
|
||||||
|
public List<CBufferInfo> ConstantBuffers
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ResourceBindingInfo> OtherResources
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public List<ResourceBindingInfo> Samplers { get; } = new();
|
||||||
|
// public List<ResourceBindingInfo> ShaderResourceViews { get; } = new();
|
||||||
|
// public List<ResourceBindingInfo> UnorderedAccessViews { get; } = new();
|
||||||
|
|
||||||
|
public ShaderReflectionData()
|
||||||
|
{
|
||||||
|
ConstantBuffers = new List<CBufferInfo>();
|
||||||
|
OtherResources = new List<ResourceBindingInfo>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static unsafe class D3D12ShaderCompiler
|
||||||
|
{
|
||||||
|
|
||||||
|
private static string GetProfileString(ShaderStage stage, CompilerTier version)
|
||||||
{
|
{
|
||||||
return (stage, version) switch
|
return (stage, version) switch
|
||||||
{
|
{
|
||||||
(ShaderStage.VertexShader, CompilerVersion.SM_6_6) => "vs_6_6",
|
(ShaderStage.TaskShader, CompilerTier.Tier0) => "as_6_6",
|
||||||
(ShaderStage.PixelShader, CompilerVersion.SM_6_6) => "ps_6_6",
|
(ShaderStage.PixelShader, CompilerTier.Tier0) => "ps_6_6",
|
||||||
(ShaderStage.MeshShader, CompilerVersion.SM_6_6) => "ms_6_6",
|
(ShaderStage.MeshShader, CompilerTier.Tier0) => "ms_6_6",
|
||||||
(ShaderStage.ComputeShader, CompilerVersion.SM_6_6) => "cs_6_6",
|
(ShaderStage.ComputeShader, CompilerTier.Tier0) => "cs_6_6",
|
||||||
(ShaderStage.VertexShader, CompilerVersion.SM_7_0) => "vs_7_0",
|
(ShaderStage.TaskShader, CompilerTier.Tier1) => "as_6_7",
|
||||||
(ShaderStage.PixelShader, CompilerVersion.SM_7_0) => "ps_7_0",
|
(ShaderStage.PixelShader, CompilerTier.Tier1) => "ps_6_7",
|
||||||
(ShaderStage.MeshShader, CompilerVersion.SM_7_0) => "ms_7_0",
|
(ShaderStage.MeshShader, CompilerTier.Tier1) => "ms_6_7",
|
||||||
(ShaderStage.ComputeShader, CompilerVersion.SM_7_0) => "cs_7_0",
|
(ShaderStage.ComputeShader, CompilerTier.Tier1) => "cs_6_7",
|
||||||
|
(ShaderStage.TaskShader, CompilerTier.Tier2) => "as_6_8",
|
||||||
|
(ShaderStage.PixelShader, CompilerTier.Tier2) => "ps_6_8",
|
||||||
|
(ShaderStage.MeshShader, CompilerTier.Tier2) => "ms_6_8",
|
||||||
|
(ShaderStage.ComputeShader, CompilerTier.Tier2) => "cs_6_8",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(stage), "Unsupported shader stage or compiler version")
|
_ => throw new ArgumentOutOfRangeException(nameof(stage), "Unsupported shader stage or compiler version")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetEntryPoint(ShaderStage stage)
|
private static string GetOptimizeLevelString(CompilerOptimizeLevel level)
|
||||||
{
|
{
|
||||||
return stage switch
|
return level switch
|
||||||
{
|
{
|
||||||
ShaderStage.VertexShader => "VSMain",
|
CompilerOptimizeLevel.O0 => "-O0",
|
||||||
ShaderStage.PixelShader => "PSMain",
|
CompilerOptimizeLevel.O1 => "-O1",
|
||||||
ShaderStage.MeshShader => "MSMain",
|
CompilerOptimizeLevel.O2 => "-O2",
|
||||||
ShaderStage.ComputeShader => "CSMain",
|
CompilerOptimizeLevel.O3 => "-O3",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(stage), "Unsupported shader stage")
|
_ => throw new ArgumentOutOfRangeException(nameof(level), "Unsupported optimization level")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompileResult Compile(string shaderPath, ShaderStage stage, CompilerVersion version)
|
private static List<string> GetCompilerArguments(ref readonly CompilerConfig config)
|
||||||
|
{
|
||||||
|
var argsArray = new List<string>
|
||||||
|
{
|
||||||
|
"-T", GetProfileString(config.stage, config.tier), // Target profile (ms_6_6, ps_6_6)
|
||||||
|
"-E", config.entryPoint, // Entry point
|
||||||
|
"-HV", "2021", // HLSL version 2021
|
||||||
|
"-enable-16bit-types", // Enable 16-bit types
|
||||||
|
GetOptimizeLevelString(config.optimizeLevel), // Optimization level
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var include in config.includes)
|
||||||
|
{
|
||||||
|
argsArray.Add("-I");
|
||||||
|
argsArray.Add(include);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var define in config.defines)
|
||||||
|
{
|
||||||
|
argsArray.Add("-D");
|
||||||
|
argsArray.Add(define);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.options.HasFlag(CompilerOption.KeepDebugInfo))
|
||||||
|
{
|
||||||
|
argsArray.Add("-Qstrip_debug");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.options.HasFlag(CompilerOption.KeepReflections))
|
||||||
|
{
|
||||||
|
argsArray.Add("-Qstrip_reflect");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.options.HasFlag(CompilerOption.WarnAsError))
|
||||||
|
{
|
||||||
|
argsArray.Add("-WX");
|
||||||
|
}
|
||||||
|
|
||||||
|
return argsArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result<CompileResult> Compile(ref readonly CompilerConfig config, Allocator allocator, IDxcBlob** ppReflectionBlob)
|
||||||
{
|
{
|
||||||
using ComPtr<IDxcCompiler3> compiler = default;
|
using ComPtr<IDxcCompiler3> compiler = default;
|
||||||
using ComPtr<IDxcUtils> utils = default;
|
using ComPtr<IDxcUtils> utils = default;
|
||||||
@@ -76,56 +207,38 @@ internal unsafe static class D3D12ShaderCompiler
|
|||||||
var pDxcCompiler = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcCompiler);
|
var pDxcCompiler = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcCompiler);
|
||||||
var pDxcUtils = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcUtils);
|
var pDxcUtils = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcUtils);
|
||||||
|
|
||||||
DxcCreateInstance(pDxcCompiler, __uuidof<IDxcCompiler3>(), compiler.GetVoidAddressOf());
|
ThrowIfFailed(DxcCreateInstance(pDxcCompiler, __uuidof<IDxcCompiler3>(), compiler.GetVoidAddressOf()));
|
||||||
DxcCreateInstance(pDxcUtils, __uuidof<IDxcUtils>(), utils.GetVoidAddressOf());
|
ThrowIfFailed(DxcCreateInstance(pDxcUtils, __uuidof<IDxcUtils>(), utils.GetVoidAddressOf()));
|
||||||
|
|
||||||
|
//includeHandler.Get()->LoadSource();
|
||||||
utils.Get()->CreateDefaultIncludeHandler(includeHandler.GetAddressOf());
|
utils.Get()->CreateDefaultIncludeHandler(includeHandler.GetAddressOf());
|
||||||
|
|
||||||
// Create source blob
|
// Create source blob
|
||||||
using ComPtr<IDxcBlobEncoding> sourceBlob = default;
|
using ComPtr<IDxcBlobEncoding> sourceBlob = default;
|
||||||
//var sourceBytes = System.Text.Encoding.UTF8.GetBytes(shaderPath);
|
if (utils.Get()->LoadFile(config.shaderPath.AsSpan().GetUnsafePtr(), null, sourceBlob.GetAddressOf()).FAILED)
|
||||||
|
|
||||||
fixed (char* pShaderPath = shaderPath.AsSpan())
|
|
||||||
{
|
{
|
||||||
utils.Get()->LoadFile(pShaderPath, null, sourceBlob.GetAddressOf());
|
return Result<CompileResult>.Fail($"Failed to load shader file: {config.shaderPath}");
|
||||||
//utils.Get()->CreateBlob(sourceBytesPtr, (uint)sourceBytes.Length, DXC_CP_UTF8, sourceBlob.GetAddressOf());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare compilation arguments - NOTE: NO -Qstrip_reflect to keep reflection data
|
var argsArray = GetCompilerArguments(in config);
|
||||||
var argsArray = new string[]
|
var argPtrs = stackalloc char*[argsArray.Count];
|
||||||
|
for (var i = 0; i < argsArray.Count; i++)
|
||||||
{
|
{
|
||||||
"-T", GetProfileString(stage, version), // Target profile (vs_6_6, ps_6_6)
|
argPtrs[i] = (char*)Marshal.StringToHGlobalUni(argsArray[i]);
|
||||||
"-E", GetEntryPoint(stage), // Entry point
|
|
||||||
"-HV", "2021", // HLSL version 2021 (required for SM 6.6)
|
|
||||||
"-enable-16bit-types", // Enable 16-bit types
|
|
||||||
"-O3", // Optimization level
|
|
||||||
"-Qstrip_debug" // Strip debug info but KEEP reflection
|
|
||||||
};
|
|
||||||
|
|
||||||
// Convert to wide strings (DXC expects LPCWSTR)
|
|
||||||
var wideArgs = new nuint[argsArray.Length];
|
|
||||||
var argPointers = new IntPtr[argsArray.Length];
|
|
||||||
|
|
||||||
for (var i = 0; i < argsArray.Length; i++)
|
|
||||||
{
|
|
||||||
argPointers[i] = Marshal.StringToHGlobalUni(argsArray[i]);
|
|
||||||
wideArgs[i] = (nuint)argPointers[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Compile shader
|
// Compile shader
|
||||||
using ComPtr<IDxcResult> result = default;
|
using ComPtr<IDxcResult> result = default;
|
||||||
fixed (nuint* argsPtr = wideArgs)
|
var buffer = new DxcBuffer
|
||||||
{
|
{
|
||||||
var buffer = new DxcBuffer
|
Ptr = sourceBlob.Get()->GetBufferPointer(),
|
||||||
{
|
Size = sourceBlob.Get()->GetBufferSize(),
|
||||||
Ptr = sourceBlob.Get()->GetBufferPointer(),
|
Encoding = DXC.DXC_CP_UTF8
|
||||||
Size = sourceBlob.Get()->GetBufferSize(),
|
};
|
||||||
Encoding = DXC.DXC_CP_UTF8
|
|
||||||
};
|
|
||||||
|
|
||||||
compiler.Get()->Compile(&buffer, (char**)argsPtr, (uint)argsArray.Length, includeHandler.Get(), __uuidof<IDxcResult>(), result.GetVoidAddressOf());
|
ThrowIfFailed(compiler.Get()->Compile(&buffer, argPtrs, (uint)argsArray.Count, includeHandler.Get(), __uuidof<IDxcResult>(), result.GetVoidAddressOf()));
|
||||||
}
|
|
||||||
|
|
||||||
// Check compilation result
|
// Check compilation result
|
||||||
HRESULT hrStatus;
|
HRESULT hrStatus;
|
||||||
@@ -139,11 +252,11 @@ internal unsafe static class D3D12ShaderCompiler
|
|||||||
if (errorBlob.Get() != null)
|
if (errorBlob.Get() != null)
|
||||||
{
|
{
|
||||||
var errorMessage = Marshal.PtrToStringUni((IntPtr)errorBlob.Get()->GetBufferPointer());
|
var errorMessage = Marshal.PtrToStringUni((IntPtr)errorBlob.Get()->GetBufferPointer());
|
||||||
throw new Exception($"DXC shader compilation failed: {errorMessage}");
|
return Result<CompileResult>.Fail($"DXC shader compilation failed:\n{errorMessage}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new Exception("DXC shader compilation failed with unknown error");
|
return Result<CompileResult>.Fail("DXC shader compilation failed with unknown error.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,47 +265,46 @@ internal unsafe static class D3D12ShaderCompiler
|
|||||||
ThrowIfFailed(result.Get()->GetResult(bytecodeBlob.GetAddressOf()));
|
ThrowIfFailed(result.Get()->GetResult(bytecodeBlob.GetAddressOf()));
|
||||||
|
|
||||||
// Get reflection data using DXC API
|
// Get reflection data using DXC API
|
||||||
using ComPtr<IDxcBlob> reflectionBlob = default;
|
if (ppReflectionBlob != null)
|
||||||
ThrowIfFailed(result.Get()->GetOutput(DXC_OUT_KIND.DXC_OUT_REFLECTION, __uuidof<IDxcBlob>(), reflectionBlob.GetVoidAddressOf(), null));
|
{
|
||||||
|
ThrowIfFailed(result.Get()->GetOutput(DXC_OUT_KIND.DXC_OUT_REFLECTION, __uuidof<IDxcBlob>(), (void**)ppReflectionBlob, null));
|
||||||
|
}
|
||||||
|
|
||||||
var bytecodeSize = bytecodeBlob.Get()->GetBufferSize();
|
var bytecodeSize = bytecodeBlob.Get()->GetBufferSize();
|
||||||
var bytecode = new UnsafeArray<byte>((int)bytecodeSize, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
var bytecode = new UnsafeArray<byte>((int)bytecodeSize, allocator);
|
||||||
|
|
||||||
NativeMemory.Copy(bytecodeBlob.Get()->GetBufferPointer(), bytecode.GetUnsafePtr(), bytecodeSize);
|
NativeMemory.Copy(bytecodeBlob.Get()->GetBufferPointer(), bytecode.GetUnsafePtr(), bytecodeSize);
|
||||||
|
|
||||||
return new CompileResult
|
return new CompileResult
|
||||||
{
|
{
|
||||||
bytecode = bytecode,
|
bytecode = bytecode,
|
||||||
reflection = reflectionBlob.Move()
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
// Free allocated wide strings
|
for (var i = 0; i < argsArray.Count; i++)
|
||||||
for (var i = 0; i < argPointers.Length; i++)
|
|
||||||
{
|
{
|
||||||
Marshal.FreeHGlobal(argPointers[i]);
|
Marshal.FreeHGlobal((nint)argPtrs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddProperty(ref Shader shader, string name, PropertyInfo propertyInfo)
|
|
||||||
{
|
|
||||||
var id = shader.Properties.Count;
|
|
||||||
shader.Properties.Add(propertyInfo);
|
|
||||||
shader.PropertyNameToIdMap[name] = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Since we are using fixed root signature layout, the reflection pass should only validate the layout, not generate it.
|
// TODO: Since we are using fixed root signature layout, the reflection pass should only validate the layout, not generate it.
|
||||||
public static void PerformDXCReflection(ref Shader shader, IDxcBlob* reflectionBlob)
|
// TODO: Ideally this should return a structured reflection data instead of populating raw lists/dictionaries.
|
||||||
|
public static Result<ShaderReflectionData> PerformDXCReflection(IDxcBlob* reflectionBlob)
|
||||||
{
|
{
|
||||||
|
if (reflectionBlob == null)
|
||||||
|
{
|
||||||
|
return Result<ShaderReflectionData>.Fail("Reflection blob is null.");
|
||||||
|
}
|
||||||
|
|
||||||
// Create DXC utils to parse reflection data
|
// Create DXC utils to parse reflection data
|
||||||
var pDxcUtils = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcUtils);
|
var pDxcUtils = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcUtils);
|
||||||
using ComPtr<IDxcUtils> utils = default;
|
using ComPtr<IDxcUtils> utils = default;
|
||||||
DxcCreateInstance(pDxcUtils, __uuidof<IDxcUtils>(), utils.GetVoidAddressOf());
|
ThrowIfFailed(DxcCreateInstance(pDxcUtils, __uuidof<IDxcUtils>(), utils.GetVoidAddressOf()));
|
||||||
|
|
||||||
// Create reflection interface from blob
|
// Create reflection interface from blob
|
||||||
var reflectionData = new DxcBuffer
|
var reflectionBuffer = new DxcBuffer
|
||||||
{
|
{
|
||||||
Ptr = reflectionBlob->GetBufferPointer(),
|
Ptr = reflectionBlob->GetBufferPointer(),
|
||||||
Size = reflectionBlob->GetBufferSize(),
|
Size = reflectionBlob->GetBufferSize(),
|
||||||
@@ -200,94 +312,84 @@ internal unsafe static class D3D12ShaderCompiler
|
|||||||
};
|
};
|
||||||
|
|
||||||
using ComPtr<ID3D12ShaderReflection> reflection = default;
|
using ComPtr<ID3D12ShaderReflection> reflection = default;
|
||||||
ThrowIfFailed(utils.Get()->CreateReflection(&reflectionData, __uuidof<ID3D12ShaderReflection>(), reflection.GetVoidAddressOf()));
|
ThrowIfFailed(utils.Get()->CreateReflection(&reflectionBuffer, __uuidof<ID3D12ShaderReflection>(), reflection.GetVoidAddressOf()));
|
||||||
|
|
||||||
D3D12_SHADER_DESC shaderDesc;
|
D3D12_SHADER_DESC shaderDesc;
|
||||||
reflection.Get()->GetDesc(&shaderDesc);
|
ThrowIfFailed(reflection.Get()->GetDesc(&shaderDesc));
|
||||||
|
|
||||||
var cbufferRegistry = new Dictionary<string, CBufferInfo>();
|
var reflectionData = new ShaderReflectionData();
|
||||||
var textureRegistry = new Dictionary<string, TextureInfo>();
|
|
||||||
|
|
||||||
for (uint i = 0; i < shaderDesc.BoundResources; i++)
|
for (uint i = 0; i < shaderDesc.BoundResources; i++)
|
||||||
{
|
{
|
||||||
D3D12_SHADER_INPUT_BIND_DESC bindDesc;
|
D3D12_SHADER_INPUT_BIND_DESC bindDesc;
|
||||||
reflection.Get()->GetResourceBindingDesc(i, &bindDesc);
|
ThrowIfFailed(reflection.Get()->GetResourceBindingDesc(i, &bindDesc));
|
||||||
|
|
||||||
|
var resourceName = Marshal.PtrToStringUTF8((IntPtr)bindDesc.Name);
|
||||||
|
if (resourceName == null)
|
||||||
|
{
|
||||||
|
return Result<ShaderReflectionData>.Fail("Failed to get resource name from reflection data.");
|
||||||
|
}
|
||||||
|
|
||||||
switch (bindDesc.Type)
|
switch (bindDesc.Type)
|
||||||
{
|
{
|
||||||
case D3D_SHADER_INPUT_TYPE.D3D_SIT_CBUFFER:
|
case D3D_SHADER_INPUT_TYPE.D3D_SIT_CBUFFER:
|
||||||
{
|
{
|
||||||
var cbufferName = Marshal.PtrToStringAnsi((IntPtr)bindDesc.Name);
|
|
||||||
if (cbufferName == null || cbufferRegistry.ContainsKey(cbufferName))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var cbuffer = reflection.Get()->GetConstantBufferByName(bindDesc.Name);
|
var cbuffer = reflection.Get()->GetConstantBufferByName(bindDesc.Name);
|
||||||
D3D12_SHADER_BUFFER_DESC cbufferDesc;
|
D3D12_SHADER_BUFFER_DESC cbufferDesc;
|
||||||
cbuffer->GetDesc(&cbufferDesc);
|
ThrowIfFailed(cbuffer->GetDesc(&cbufferDesc));
|
||||||
|
|
||||||
var cbufferInfo = new CBufferInfo
|
var variables = new List<CBufferVariableInfo>((int)cbufferDesc.Variables);
|
||||||
{
|
|
||||||
Size = cbufferDesc.Size,
|
|
||||||
RegisterSlot = bindDesc.BindPoint
|
|
||||||
};
|
|
||||||
cbufferRegistry.Add(cbufferName, cbufferInfo);
|
|
||||||
|
|
||||||
|
// Now we iterate all variables for *every* cbuffer, not just b3
|
||||||
for (uint j = 0; j < cbufferDesc.Variables; j++)
|
for (uint j = 0; j < cbufferDesc.Variables; j++)
|
||||||
{
|
{
|
||||||
var variable = cbuffer->GetVariableByIndex(j);
|
var variable = cbuffer->GetVariableByIndex(j);
|
||||||
D3D12_SHADER_VARIABLE_DESC varDesc;
|
D3D12_SHADER_VARIABLE_DESC varDesc;
|
||||||
variable->GetDesc(&varDesc);
|
variable->GetDesc(&varDesc);
|
||||||
|
|
||||||
var variableName = Marshal.PtrToStringAnsi((IntPtr)varDesc.Name);
|
var variableName = Marshal.PtrToStringUTF8((IntPtr)varDesc.Name);
|
||||||
if (variableName == null || shader.PropertyNameToIdMap.ContainsKey(variableName))
|
if (variableName == null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var propInfo = new PropertyInfo
|
variables.Add(new CBufferVariableInfo
|
||||||
{
|
{
|
||||||
CBufferIndex = cbufferInfo.RegisterSlot,
|
Name = variableName,
|
||||||
ByteOffset = varDesc.StartOffset,
|
StartOffset = varDesc.StartOffset,
|
||||||
Size = varDesc.Size
|
Size = varDesc.Size
|
||||||
};
|
});
|
||||||
|
|
||||||
AddProperty(ref shader, variableName, propInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reflectionData.ConstantBuffers.Add(new CBufferInfo
|
||||||
|
{
|
||||||
|
Name = resourceName,
|
||||||
|
RegisterSlot = bindDesc.BindPoint,
|
||||||
|
RegisterSpace = bindDesc.Space,
|
||||||
|
SizeInBytes = cbufferDesc.Size,
|
||||||
|
Variables = variables
|
||||||
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case D3D_SHADER_INPUT_TYPE.D3D_SIT_TEXTURE:
|
// NOTE: Currently we are not support resource bindings yet, everything access through bindless heaps.
|
||||||
|
default:
|
||||||
{
|
{
|
||||||
#if SUPPORT_TEXTURE_BINDING
|
reflectionData.OtherResources.Add(new ResourceBindingInfo
|
||||||
var textureName = Marshal.PtrToStringAnsi((IntPtr)bindDesc.Name);
|
|
||||||
if (textureName == null || textureRegistry.ContainsKey(textureName))
|
|
||||||
{
|
{
|
||||||
continue;
|
Name = resourceName,
|
||||||
}
|
Type = bindDesc.Type,
|
||||||
|
BindPoint = bindDesc.BindPoint,
|
||||||
|
BindCount = bindDesc.BindCount,
|
||||||
|
Space = bindDesc.Space
|
||||||
|
});
|
||||||
|
|
||||||
// ALL texture input slots are regular textures!
|
|
||||||
// Bindless textures don't use explicit texture inputs - they use ResourceDescriptorHeap[index]
|
|
||||||
var textureInfo = new TextureInfo
|
|
||||||
{
|
|
||||||
RegisterSlot = bindDesc.BindPoint,
|
|
||||||
RootParameterIndex = (uint)shader.ConstantBuffers.Count // Descriptor table comes after CBVs
|
|
||||||
};
|
|
||||||
|
|
||||||
textureRegistry.Add(textureName, textureInfo);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
throw new NotSupportedException("Texture bindings are not supported in current version. Please use bindless textures.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shader.PerMaterialBufferInfo.Clear();
|
return reflectionData;
|
||||||
foreach (var cbuf in cbufferRegistry.Values)
|
|
||||||
{
|
|
||||||
shader.PerMaterialBufferInfo.Add(cbuf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
|
using Ghost.Core.Utilities;
|
||||||
using Ghost.Graphics.Contracts;
|
using Ghost.Graphics.Contracts;
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.Data;
|
using Ghost.Graphics.Data;
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ internal static class D3D12_BLEND_DESC_Extensions
|
|||||||
public static D3D12_BLEND_DESC OPAQUE => Create(D3D12_BLEND_ONE, D3D12_BLEND_ZERO);
|
public static D3D12_BLEND_DESC OPAQUE => Create(D3D12_BLEND_ONE, D3D12_BLEND_ZERO);
|
||||||
public static D3D12_BLEND_DESC ALPHA_BLEND => Create(D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA);
|
public static D3D12_BLEND_DESC ALPHA_BLEND => Create(D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA);
|
||||||
public static D3D12_BLEND_DESC ADDITIVE => Create(D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_ONE);
|
public static D3D12_BLEND_DESC ADDITIVE => Create(D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_ONE);
|
||||||
|
public static D3D12_BLEND_DESC MULTIPLY => Create(D3D12_BLEND_DEST_COLOR, D3D12_BLEND_ZERO);
|
||||||
|
public static D3D12_BLEND_DESC PREMULTIPLIED => Create(D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA);
|
||||||
public static D3D12_BLEND_DESC NON_PREMULTIPLIED => Create(D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA);
|
public static D3D12_BLEND_DESC NON_PREMULTIPLIED => Create(D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA);
|
||||||
|
|
||||||
public static D3D12_BLEND_DESC Create(D3D12_BLEND srcBlend, D3D12_BLEND destBlend)
|
public static D3D12_BLEND_DESC Create(D3D12_BLEND srcBlend, D3D12_BLEND destBlend)
|
||||||
@@ -148,16 +150,4 @@ internal static class D3D12_DEPTH_STENCILOP_DESC_Extensions
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
internal unsafe static class D3D12MA_Allocation_Extensions
|
|
||||||
{
|
|
||||||
extension(ref readonly D3D12MA_Allocation allocation)
|
|
||||||
{
|
|
||||||
public bool IsNull => allocation.GetResource() == null
|
|
||||||
&& allocation.GetHeap() == null
|
|
||||||
&& allocation.GetSize() == 0;
|
|
||||||
|
|
||||||
public bool IsNotNull => !allocation.IsNull;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
using Ghost.Core;
|
|
||||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics.Data;
|
|
||||||
|
|
||||||
internal struct CBufferCache : IDisposable
|
|
||||||
{
|
|
||||||
public UnsafeArray<byte> CpuData
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Handle<GraphicsBuffer> GpuResource
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly uint _alignedSize;
|
|
||||||
|
|
||||||
internal unsafe CBufferCache(Handle<GraphicsBuffer> buffer, uint bufferSize)
|
|
||||||
{
|
|
||||||
_alignedSize = (bufferSize + 255u) & ~255u;
|
|
||||||
|
|
||||||
CpuData = new((int)_alignedSize, Allocator.Persistent);
|
|
||||||
GpuResource = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly void Dispose()
|
|
||||||
{
|
|
||||||
CpuData.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +1,93 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||||
using System.Numerics;
|
using Misaki.HighPerformance.Mathematics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Ghost.Graphics.Data;
|
namespace Ghost.Graphics.Data;
|
||||||
|
|
||||||
public struct Material : IHandleType
|
internal struct CBufferCache : IResourceReleasable
|
||||||
{
|
{
|
||||||
internal CBufferCache _materialPropertiesCache;
|
private UnsafeArray<byte> _cpuData;
|
||||||
|
private Handle<GraphicsBuffer> _gpuResource;
|
||||||
|
private uint _alignedSize;
|
||||||
|
|
||||||
public Identifier<Shader> Shader
|
public readonly UnsafeArray<byte> CpuData => _cpuData;
|
||||||
|
public readonly Handle<GraphicsBuffer> GpuResource => _gpuResource;
|
||||||
|
public readonly uint AlignedSize => _alignedSize;
|
||||||
|
|
||||||
|
public unsafe CBufferCache(IResourceAllocator allocator, uint bufferSize)
|
||||||
{
|
{
|
||||||
get; internal set;
|
_alignedSize = (bufferSize + 255u) & ~255u;
|
||||||
|
|
||||||
|
_cpuData = new((int)AlignedSize, Allocator.Persistent);
|
||||||
|
|
||||||
|
var desc = new BufferDesc
|
||||||
|
{
|
||||||
|
Size = bufferSize,
|
||||||
|
Usage = BufferUsage.Constant,
|
||||||
|
MemoryType = ResourceMemoryType.Default,
|
||||||
|
};
|
||||||
|
|
||||||
|
_gpuResource = allocator.CreateBuffer(ref desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal readonly void Dispose()
|
public void ReleaseResource(IResourceDatabase database)
|
||||||
{
|
{
|
||||||
|
_cpuData.Dispose();
|
||||||
|
|
||||||
|
database.ReleaseResource(GpuResource.AsResource());
|
||||||
|
_gpuResource = Handle<GraphicsBuffer>.Invalid;
|
||||||
|
|
||||||
|
_alignedSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Material : IResourceReleasable, IHandleType
|
||||||
|
{
|
||||||
|
private Identifier<Shader> _shader;
|
||||||
|
private UnsafeArray<CBufferCache> _materialPropertiesCache; // One per shader pass
|
||||||
|
|
||||||
|
public readonly Identifier<Shader> Shader => _shader;
|
||||||
|
|
||||||
|
public Material(Identifier<Shader> shader, IResourceAllocator allocator, IResourceDatabase database)
|
||||||
|
{
|
||||||
|
SetShader(shader, allocator, database);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ref CBufferCache GetPassCache(int passIndex)
|
||||||
|
{
|
||||||
|
return ref _materialPropertiesCache[passIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetShader(Identifier<Shader> shaderId, IResourceAllocator allocator, IResourceDatabase database)
|
||||||
|
{
|
||||||
|
if (!shaderId.IsValid)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Shader ID is invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_shader = shaderId;
|
||||||
|
|
||||||
|
var shader = database.GetShaderReference(shaderId);
|
||||||
|
_materialPropertiesCache = new UnsafeArray<CBufferCache>(shader.PassCount, Allocator.Persistent);
|
||||||
|
for (var i = 0; i < shader.PassCount; i++)
|
||||||
|
{
|
||||||
|
var pass = database.GetShaderPass(shader.GetPassKey(i));
|
||||||
|
var cbufferInfo = pass.PassPropertyInfo;
|
||||||
|
_materialPropertiesCache[i] = new CBufferCache(allocator, cbufferInfo.Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IResourceReleasable.ReleaseResource(IResourceDatabase database)
|
||||||
|
{
|
||||||
|
foreach (var cache in _materialPropertiesCache)
|
||||||
|
{
|
||||||
|
cache.ReleaseResource(database);
|
||||||
|
}
|
||||||
|
|
||||||
_materialPropertiesCache.Dispose();
|
_materialPropertiesCache.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,46 +95,35 @@ public struct Material : IHandleType
|
|||||||
public ref struct MaterialAccessor
|
public ref struct MaterialAccessor
|
||||||
{
|
{
|
||||||
private ref Material _materialData;
|
private ref Material _materialData;
|
||||||
private ref Shader _shader;
|
private readonly ref Shader _shader;
|
||||||
|
|
||||||
private readonly IResourceDatabase _resourceDatabase;
|
private readonly IResourceDatabase _resourceDatabase;
|
||||||
|
|
||||||
internal MaterialAccessor(ref Material materialData, IResourceDatabase resourceDatabase)
|
public MaterialAccessor(Handle<Material> material, IResourceDatabase resourceDatabase)
|
||||||
{
|
{
|
||||||
_resourceDatabase = resourceDatabase;
|
_resourceDatabase = resourceDatabase;
|
||||||
|
|
||||||
_materialData = ref materialData;
|
_materialData = ref resourceDatabase.GetMaterialReference(material);
|
||||||
_shader = ref resourceDatabase.GetShaderReference(materialData.Shader);
|
_shader = ref resourceDatabase.GetShaderReference(_materialData.Shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly unsafe void WriteToCache<T>(int propertyId, in T value)
|
private readonly unsafe void WriteToCache<T>(string propertyName, in T value)
|
||||||
where T : unmanaged
|
where T : unmanaged
|
||||||
{
|
{
|
||||||
if (propertyId == -1)
|
foreach (var index in _shader.GetPropertyPassIndices(propertyName))
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Property ID is invalid.");
|
var passKey = _shader.GetPassKey(index);
|
||||||
|
var pass = _resourceDatabase.GetShaderPass(passKey);
|
||||||
|
var propertyInfo = pass.GetPropertyInfo(propertyName);
|
||||||
|
|
||||||
|
if (propertyInfo.Size != sizeof(T))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"Property '{propertyName}' has a size mismatch. Expected {propertyInfo.Size} bytes, but got {sizeof(T)} bytes.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ref var cache = ref _materialData.GetPassCache(index);
|
||||||
|
Unsafe.WriteUnaligned(ref cache.CpuData[propertyInfo.ByteOffset], value);
|
||||||
}
|
}
|
||||||
|
|
||||||
var propInfo = _shader.Properties[propertyId];
|
|
||||||
if (propInfo.Size != sizeof(T))
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Property '{propertyId}' has a size mismatch. Expected {propInfo.Size} bytes, but got {sizeof(T)} bytes.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var cache = _materialData._materialPropertiesCache[propInfo.CBufferIndex];
|
|
||||||
|
|
||||||
Unsafe.WriteUnaligned(ref cache.CpuData[(int)propInfo.ByteOffset], value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets a float property in the material's constant buffer.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="propertyId">The ID of the property to set.</param>
|
|
||||||
/// <param name="value">The value to set for the property.</param>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public readonly void SetFloat(int propertyId, in float value)
|
|
||||||
{
|
|
||||||
WriteToCache(propertyId, in value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -75,18 +134,7 @@ public ref struct MaterialAccessor
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly void SetFloat(string propertyName, in float value)
|
public readonly void SetFloat(string propertyName, in float value)
|
||||||
{
|
{
|
||||||
SetFloat(_shader.GetPropertyId(propertyName), in value);
|
WriteToCache(propertyName, in value);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets a uint property in the material's constant buffer (useful for texture indices).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="propertyId">The ID of the property to set.</param>
|
|
||||||
/// <param name="value">The value to set for the property.</param>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public readonly void SetUInt(int propertyId, in uint value)
|
|
||||||
{
|
|
||||||
WriteToCache(propertyId, in value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -97,18 +145,7 @@ public ref struct MaterialAccessor
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly void SetUInt(string propertyName, in uint value)
|
public readonly void SetUInt(string propertyName, in uint value)
|
||||||
{
|
{
|
||||||
SetUInt(_shader.GetPropertyId(propertyName), in value);
|
WriteToCache(propertyName, in value);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets a Vector property in the material's constant buffer.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="propertyId">The ID of the property to set.</param>
|
|
||||||
/// <param name="value">The value to set for the property.</param>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public readonly void SetVector(int propertyId, in Vector4 value)
|
|
||||||
{
|
|
||||||
WriteToCache(propertyId, in value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -117,20 +154,9 @@ public ref struct MaterialAccessor
|
|||||||
/// <param name="propertyName">The name of the property to set.</param>
|
/// <param name="propertyName">The name of the property to set.</param>
|
||||||
/// <param name="value">The value to set for the property.</param>
|
/// <param name="value">The value to set for the property.</param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly void SetVector(string propertyName, in Vector4 value)
|
public readonly void SetVector(string propertyName, in float4 value)
|
||||||
{
|
{
|
||||||
SetVector(_shader.GetPropertyId(propertyName), in value);
|
WriteToCache(propertyName, in value);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets a Matrix property in the material's constant buffer.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="propertyId">The ID of the property to set.</param>
|
|
||||||
/// <param name="value">The value to set for the property.</param>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public readonly void SetMatrix(int propertyId, in Matrix4x4 value)
|
|
||||||
{
|
|
||||||
WriteToCache(propertyId, in value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -139,9 +165,9 @@ public ref struct MaterialAccessor
|
|||||||
/// <param name="propertyName">The name of the property to set.</param>
|
/// <param name="propertyName">The name of the property to set.</param>
|
||||||
/// <param name="value">The value to set for the property.</param>
|
/// <param name="value">The value to set for the property.</param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly void SetMatrix(string propertyName, in Matrix4x4 value)
|
public readonly void SetMatrix(string propertyName, in float4x4 value)
|
||||||
{
|
{
|
||||||
SetMatrix(_shader.GetPropertyId(propertyName), in value);
|
WriteToCache(propertyName, in value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -186,8 +212,9 @@ public ref struct MaterialAccessor
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly void UploadMaterialData(ICommandBuffer cmb)
|
public readonly void UploadMaterialData(ICommandBuffer cmb)
|
||||||
{
|
{
|
||||||
foreach (var cache in _materialData._materialPropertiesCache)
|
for (var i = 0; i < _shader.PassCount; i++)
|
||||||
{
|
{
|
||||||
|
ref var cache = ref _materialData.GetPassCache(i);
|
||||||
cmb.Upload(cache.GpuResource, cache.CpuData.AsSpan());
|
cmb.Upload(cache.GpuResource, cache.CpuData.AsSpan());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
|
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 Misaki.HighPerformance.LowLevel.Utilities;
|
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||||
@@ -7,7 +8,7 @@ using Misaki.HighPerformance.Mathematics.Geometry;
|
|||||||
|
|
||||||
namespace Ghost.Graphics.Data;
|
namespace Ghost.Graphics.Data;
|
||||||
|
|
||||||
public struct Mesh : IHandleType
|
public struct Mesh : IResourceReleasable, IHandleType
|
||||||
{
|
{
|
||||||
public UnsafeList<Vertex> vertices;
|
public UnsafeList<Vertex> vertices;
|
||||||
public UnsafeList<uint> indices;
|
public UnsafeList<uint> indices;
|
||||||
@@ -38,6 +39,14 @@ public struct Mesh : IHandleType
|
|||||||
vertices.Dispose();
|
vertices.Dispose();
|
||||||
indices.Dispose();
|
indices.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IResourceReleasable.ReleaseResource(IResourceDatabase database)
|
||||||
|
{
|
||||||
|
ReleaseCpuResources();
|
||||||
|
|
||||||
|
database.ReleaseResource(vertexBuffer.AsResource());
|
||||||
|
database.ReleaseResource(indexBuffer.AsResource());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MeshExtension
|
public static class MeshExtension
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ public unsafe readonly ref struct RenderingContext
|
|||||||
|
|
||||||
public void RenderMesh(Handle<Mesh> mesh, Handle<Material> material)
|
public void RenderMesh(Handle<Mesh> mesh, Handle<Material> material)
|
||||||
{
|
{
|
||||||
_cmd.DrawMesh(mesh, material);
|
//_cmd.DrawMesh(mesh, material);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExecuteCopyCommands()
|
public void ExecuteCopyCommands()
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
|
using Ghost.Core.Contracts;
|
||||||
using Ghost.Core.Graphics;
|
using Ghost.Core.Graphics;
|
||||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ghost.Graphics.Data;
|
namespace Ghost.Graphics.Data;
|
||||||
|
|
||||||
internal readonly struct TextureInfo
|
public readonly struct TextureInfo
|
||||||
{
|
{
|
||||||
public uint RegisterSlot
|
public uint RegisterSlot
|
||||||
{
|
{
|
||||||
@@ -18,7 +20,7 @@ internal readonly struct TextureInfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal readonly struct PropertyInfo
|
public readonly struct PropertyInfo
|
||||||
{
|
{
|
||||||
public uint CBufferIndex
|
public uint CBufferIndex
|
||||||
{
|
{
|
||||||
@@ -36,7 +38,7 @@ internal readonly struct PropertyInfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal readonly struct CBufferInfo
|
public readonly struct CBufferInfo
|
||||||
{
|
{
|
||||||
public uint Size
|
public uint Size
|
||||||
{
|
{
|
||||||
@@ -49,65 +51,117 @@ internal readonly struct CBufferInfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal struct ShaderPass
|
public readonly unsafe struct ShaderPass
|
||||||
{
|
{
|
||||||
|
// NOTE: This is for per pass cbuffer only. Global, per view, and per mesh cbuffers are fixed.
|
||||||
|
private readonly Dictionary<string, int> _propertyLookup;
|
||||||
|
private readonly UnsafeList<PropertyInfo> _properties;
|
||||||
|
|
||||||
|
internal readonly CBufferInfo PassPropertyInfo
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShaderPass(CBufferInfo info, UnsafeList<PropertyInfo> properties, Dictionary<string, int> propertyNameToIdMap)
|
||||||
|
{
|
||||||
|
PassPropertyInfo = info;
|
||||||
|
_properties = properties;
|
||||||
|
_propertyLookup = propertyNameToIdMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly int GetPropertyId(string propertyName)
|
||||||
|
{
|
||||||
|
return _propertyLookup.TryGetValue(propertyName, out var id) ? id : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly PropertyInfo GetPropertyInfo(int id)
|
||||||
|
{
|
||||||
|
return _properties[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly PropertyInfo GetPropertyInfo(string propertyName)
|
||||||
|
{
|
||||||
|
return _properties[GetPropertyId(propertyName)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A representation of a GPU shader, including its metadata about its resources.
|
/// A representation of a GPU shader, including all the passes it contains.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
public readonly struct Shader : IResourceReleasable, IIdentifierType
|
||||||
// TODO: Multi pass and keyword support
|
|
||||||
public struct Shader : IIdentifierType
|
|
||||||
{
|
{
|
||||||
private readonly ShaderDescriptor _descriptor;
|
private readonly ShaderPassKey[] _passIDs;
|
||||||
|
private readonly Dictionary<string, int> _passLookup; // pass name to index
|
||||||
|
private readonly Dictionary<string, List<int>> _propertyLookup; // property name to pass index (property name to list of pass indices that contain the property)
|
||||||
|
|
||||||
private CBufferInfo _perMaterialBufferInfo;
|
public int PassCount => _passIDs.Length;
|
||||||
private UnsafeList<PropertyInfo> _properties;
|
|
||||||
private Dictionary<string, int> _propertyNameToIdMap;
|
|
||||||
|
|
||||||
private bool _disposed;
|
internal Shader(ShaderDescriptor descriptor)
|
||||||
|
|
||||||
internal CBufferInfo PerMaterialBufferInfo
|
|
||||||
{
|
{
|
||||||
readonly get => _perMaterialBufferInfo;
|
_passIDs = new ShaderPassKey[descriptor.passes.Count];
|
||||||
set => _perMaterialBufferInfo = value;
|
_passLookup = new(descriptor.passes.Count);
|
||||||
}
|
_propertyLookup = new(descriptor.passes.Count);
|
||||||
|
|
||||||
internal readonly UnsafeList<PropertyInfo> Properties => _properties;
|
for (var i = 0; i < descriptor.passes.Count; i++)
|
||||||
internal readonly Dictionary<string, int> PropertyNameToIdMap => _propertyNameToIdMap;
|
|
||||||
public Shader(ShaderDescriptor descriptor)
|
|
||||||
{
|
|
||||||
_descriptor = descriptor;
|
|
||||||
|
|
||||||
_properties = new(8, Allocator.Persistent);
|
|
||||||
_propertyNameToIdMap = new(8);
|
|
||||||
|
|
||||||
_disposed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a unique, stable ID for a shader property.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="propertyName">The name of the shader property.</param>
|
|
||||||
/// <returns>The integer ID of the property, or -1 if not found.</returns>
|
|
||||||
public readonly int GetPropertyId(string propertyName)
|
|
||||||
{
|
|
||||||
return _propertyNameToIdMap.TryGetValue(propertyName, out var id) ? id : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Dispose()
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
{
|
{
|
||||||
return;
|
var pass = descriptor.passes[i];
|
||||||
|
var passKey = new ShaderPassKey(pass.Identifier);
|
||||||
|
|
||||||
|
_passIDs[i] = passKey;
|
||||||
|
_passLookup[pass.Name] = i;
|
||||||
|
|
||||||
|
if (pass is FullPassDescriptor fullPass)
|
||||||
|
{
|
||||||
|
if (fullPass.properties == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var property in fullPass.properties)
|
||||||
|
{
|
||||||
|
ref var passIndices = ref CollectionsMarshal.GetValueRefOrAddDefault(_propertyLookup, property.name, out var exists);
|
||||||
|
if (!exists || passIndices == null)
|
||||||
|
{
|
||||||
|
passIndices = new List<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
passIndices.Add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: handle inherited passes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly ShaderPassKey GetPassKey(int index)
|
||||||
|
{
|
||||||
|
return _passIDs[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly bool TryGetPassKey(string passName, out ShaderPassKey? passID)
|
||||||
|
{
|
||||||
|
var index = _passLookup.GetValueOrDefault(passName, -1);
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
passID = new(0);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_properties.Dispose();
|
passID = _passIDs[index];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
_propertyNameToIdMap.Clear();
|
public readonly IReadOnlyCollection<int> GetPropertyPassIndices(string propertyName)
|
||||||
_propertyNameToIdMap = null!;
|
{
|
||||||
|
if (_propertyLookup.TryGetValue(propertyName, out var passIndices))
|
||||||
|
{
|
||||||
|
return passIndices;
|
||||||
|
}
|
||||||
|
|
||||||
_disposed = true;
|
return Array.Empty<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IResourceReleasable.ReleaseResource(IResourceDatabase database)
|
||||||
|
{
|
||||||
|
// Should we do something here?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,11 +13,11 @@ public struct Vertex
|
|||||||
public const DXGI_FORMAT ALIGNED_FORMAT = DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT;
|
public const DXGI_FORMAT ALIGNED_FORMAT = DXGI_FORMAT.DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||||
public const int COUNT = 5;
|
public const int COUNT = 5;
|
||||||
|
|
||||||
public static readonly FixedString32 position = new("POSITION");
|
public static readonly FixedText32 position = new("POSITION");
|
||||||
public static readonly FixedString32 normal = new("NORMAL");
|
public static readonly FixedText32 normal = new("NORMAL");
|
||||||
public static readonly FixedString32 tangent = new("TANGENT");
|
public static readonly FixedText32 tangent = new("TANGENT");
|
||||||
public static readonly FixedString32 uv = new("TEXCOORD");
|
public static readonly FixedText32 uv = new("TEXCOORD");
|
||||||
public static readonly FixedString32 color = new("COLOR");
|
public static readonly FixedText32 color = new("COLOR");
|
||||||
}
|
}
|
||||||
|
|
||||||
public float4 position;
|
public float4 position;
|
||||||
|
|||||||
603
Ghost.Graphics/RHI/Common.cs
Normal file
603
Ghost.Graphics/RHI/Common.cs
Normal file
@@ -0,0 +1,603 @@
|
|||||||
|
using Misaki.HighPerformance.Utilities;
|
||||||
|
using System.IO.Hashing;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using TerraFX.Interop.DirectX;
|
||||||
|
|
||||||
|
namespace Ghost.Graphics.RHI;
|
||||||
|
|
||||||
|
public readonly struct ShaderPassKey
|
||||||
|
{
|
||||||
|
public readonly ulong value;
|
||||||
|
|
||||||
|
public ShaderPassKey(ulong value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShaderPassKey(string passId)
|
||||||
|
{
|
||||||
|
var passIdSpan = passId.AsSpan();
|
||||||
|
value = XxHash3.HashToUInt64(MemoryMarshal.AsBytes(passIdSpan));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return value.ToString("X16");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return value.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct GraphicsPipelineKey
|
||||||
|
{
|
||||||
|
public readonly ulong value;
|
||||||
|
|
||||||
|
public GraphicsPipelineKey(ulong value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return value.ToString("X16");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return value.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal struct GraphicsPipelineHash
|
||||||
|
{
|
||||||
|
[InlineArray(8)]
|
||||||
|
public struct rtv_array
|
||||||
|
{
|
||||||
|
public TextureFormat rtvFormats;
|
||||||
|
}
|
||||||
|
|
||||||
|
public rtv_array rtvFormats;
|
||||||
|
public ShaderPassKey id;
|
||||||
|
public uint rtvCount;
|
||||||
|
public TextureFormat dsvFormat;
|
||||||
|
// Do we need to store blend state?
|
||||||
|
// TODO: Variants
|
||||||
|
|
||||||
|
public readonly GraphicsPipelineKey GetKey()
|
||||||
|
{
|
||||||
|
Span<ulong> data = stackalloc ulong[3 + 8];
|
||||||
|
data[0] = id.value;
|
||||||
|
data[1] = rtvCount;
|
||||||
|
data[2] = (ulong)dsvFormat;
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
data[3 + i] = (ulong)rtvFormats[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
var bytes = MemoryMarshal.AsBytes(data);
|
||||||
|
return new GraphicsPipelineKey(XxHash3.HashToUInt64(bytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public struct ViewportDesc
|
||||||
|
{
|
||||||
|
public float x;
|
||||||
|
public float y;
|
||||||
|
public float width;
|
||||||
|
public float height;
|
||||||
|
public float minDepth;
|
||||||
|
public float maxDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct RectDesc
|
||||||
|
{
|
||||||
|
public uint left;
|
||||||
|
public uint top;
|
||||||
|
public uint right;
|
||||||
|
public uint bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct SubResourceData
|
||||||
|
{
|
||||||
|
public unsafe void* pData;
|
||||||
|
public nint rowPitch;
|
||||||
|
public nint slicePitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
public struct ResourceDesc
|
||||||
|
{
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public TextureDesc textureDescription;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public BufferDesc bufferDescription;
|
||||||
|
|
||||||
|
public static ResourceDesc Buffer(BufferDesc desc)
|
||||||
|
{
|
||||||
|
return new ResourceDesc
|
||||||
|
{
|
||||||
|
bufferDescription = desc
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ResourceDesc Texture(TextureDesc desc)
|
||||||
|
{
|
||||||
|
return new ResourceDesc
|
||||||
|
{
|
||||||
|
textureDescription = desc
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ResourceDesc FromD3D12(D3D12_RESOURCE_DESC desc)
|
||||||
|
{
|
||||||
|
if (desc.Dimension == D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||||
|
{
|
||||||
|
return Buffer(new BufferDesc
|
||||||
|
{
|
||||||
|
Size = (uint)desc.Width,
|
||||||
|
Stride = 0,
|
||||||
|
Usage = BufferUsage.None,
|
||||||
|
MemoryType = ResourceMemoryType.Default
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Texture(new TextureDesc
|
||||||
|
{
|
||||||
|
Width = (uint)desc.Width,
|
||||||
|
Height = desc.Height,
|
||||||
|
Slice = desc.DepthOrArraySize,
|
||||||
|
Format = desc.Format.ToTextureFormat(),
|
||||||
|
Dimension = desc.Dimension.ToTextureDimension(),
|
||||||
|
MipLevels = desc.MipLevels,
|
||||||
|
Usage = TextureUsage.None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render target description
|
||||||
|
/// Supports either color OR depth rendering, not both
|
||||||
|
/// </summary>
|
||||||
|
public struct RenderTargetDesc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Width of the render target
|
||||||
|
/// </summary>
|
||||||
|
public uint Width
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Height of the render target
|
||||||
|
/// </summary>
|
||||||
|
public uint Height
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Slice of the render target
|
||||||
|
/// </summary>
|
||||||
|
public uint Slice
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Type of render target
|
||||||
|
/// </summary>
|
||||||
|
public RenderTargetType Type
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Target texture format
|
||||||
|
/// </summary>
|
||||||
|
public TextureFormat Format
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture dimension
|
||||||
|
/// </summary>
|
||||||
|
public TextureDimension Dimension
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creation flags for the render target
|
||||||
|
/// </summary>
|
||||||
|
public RenderTargetCreationFlags CreationFlags
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of mip levels. 0 to generate full mip chain
|
||||||
|
/// </summary>
|
||||||
|
public uint MipLevels
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of samples for MSAA
|
||||||
|
/// </summary>
|
||||||
|
public uint SampleCount
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a color render target
|
||||||
|
/// </summary>
|
||||||
|
public static RenderTargetDesc Color(uint width, uint height, uint slice = 1,
|
||||||
|
TextureFormat format = TextureFormat.R8G8B8A8_UNorm, TextureDimension dimension = TextureDimension.Texture2D,
|
||||||
|
RenderTargetCreationFlags creationFlags = RenderTargetCreationFlags.AllowUAV | RenderTargetCreationFlags.DynamicallyResolution | RenderTargetCreationFlags.GenerateMips,
|
||||||
|
uint mipLevels = 0u, uint sampleCount = 1)
|
||||||
|
{
|
||||||
|
return new RenderTargetDesc
|
||||||
|
{
|
||||||
|
Width = width,
|
||||||
|
Height = height,
|
||||||
|
Slice = slice,
|
||||||
|
Type = RenderTargetType.Color,
|
||||||
|
Format = format,
|
||||||
|
Dimension = dimension,
|
||||||
|
CreationFlags = creationFlags,
|
||||||
|
MipLevels = mipLevels,
|
||||||
|
SampleCount = sampleCount
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a depth render target
|
||||||
|
/// </summary>
|
||||||
|
public static RenderTargetDesc Depth(uint width, uint height, uint slice = 1,
|
||||||
|
TextureFormat format = TextureFormat.D24_UNorm_S8_UInt, TextureDimension dimension = TextureDimension.Texture2D,
|
||||||
|
RenderTargetCreationFlags creationFlags = RenderTargetCreationFlags.AllowUAV | RenderTargetCreationFlags.DynamicallyResolution,
|
||||||
|
uint mipLevels = 0u, uint sampleCount = 1)
|
||||||
|
{
|
||||||
|
return new RenderTargetDesc
|
||||||
|
{
|
||||||
|
Width = width,
|
||||||
|
Height = height,
|
||||||
|
Slice = slice,
|
||||||
|
Type = RenderTargetType.Depth,
|
||||||
|
Format = format,
|
||||||
|
Dimension = dimension,
|
||||||
|
CreationFlags = creationFlags,
|
||||||
|
MipLevels = mipLevels,
|
||||||
|
SampleCount = sampleCount
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static TextureDesc ToTextureDescripton(RenderTargetDesc desc)
|
||||||
|
{
|
||||||
|
var usage = desc.Type == RenderTargetType.Color ? TextureUsage.RenderTarget : TextureUsage.DepthStencil;
|
||||||
|
if (desc.CreationFlags.HasFlag(RenderTargetCreationFlags.AllowUAV))
|
||||||
|
{
|
||||||
|
usage |= TextureUsage.UnorderedAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TextureDesc
|
||||||
|
{
|
||||||
|
Width = desc.Width,
|
||||||
|
Height = desc.Height,
|
||||||
|
Slice = desc.Slice,
|
||||||
|
Format = desc.Format,
|
||||||
|
Dimension = desc.Dimension,
|
||||||
|
MipLevels = desc.MipLevels,
|
||||||
|
Usage = usage,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture description
|
||||||
|
/// </summary>
|
||||||
|
public struct TextureDesc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Width of the texture
|
||||||
|
/// </summary>
|
||||||
|
public uint Width
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Height of the texture
|
||||||
|
/// </summary>
|
||||||
|
public uint Height
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Slice of the texture
|
||||||
|
/// </summary>
|
||||||
|
public uint Slice
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture format
|
||||||
|
/// </summary>
|
||||||
|
public TextureFormat Format
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture dimension
|
||||||
|
/// </summary>
|
||||||
|
public TextureDimension Dimension
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of mip levels. 0 to generate full mip chain
|
||||||
|
/// </summary>
|
||||||
|
public uint MipLevels
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture usage flags
|
||||||
|
/// </summary>
|
||||||
|
public TextureUsage Usage
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Buffer description
|
||||||
|
/// </summary>
|
||||||
|
public struct BufferDesc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Size of the buffer in bytes
|
||||||
|
/// </summary>
|
||||||
|
public ulong Size
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint Stride
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Buffer usage flags
|
||||||
|
/// </summary>
|
||||||
|
public BufferUsage Usage
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Memory type for the buffer
|
||||||
|
/// </summary>
|
||||||
|
public ResourceMemoryType MemoryType
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TextureDimensionExtension
|
||||||
|
{
|
||||||
|
public static TextureDimension ToTextureDimension(this D3D12_RESOURCE_DIMENSION dimension)
|
||||||
|
{
|
||||||
|
return dimension switch
|
||||||
|
{
|
||||||
|
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE1D => TextureDimension.Texture2D,
|
||||||
|
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE2D => TextureDimension.Texture2D,
|
||||||
|
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE3D => TextureDimension.Texture3D,
|
||||||
|
_ => TextureDimension.Unknown,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum ResourceState
|
||||||
|
{
|
||||||
|
Common = 0,
|
||||||
|
VertexAndConstantBuffer = 1 << 0,
|
||||||
|
IndexBuffer = 1 << 1,
|
||||||
|
RenderTarget = 1 << 2,
|
||||||
|
UnorderedAccess = 1 << 3,
|
||||||
|
DepthWrite = 1 << 4,
|
||||||
|
DepthRead = 1 << 5,
|
||||||
|
PixelShaderResource = 1 << 6,
|
||||||
|
CopyDest = 1 << 7,
|
||||||
|
CopySource = 1 << 8,
|
||||||
|
GenericRead = 1 << 9,
|
||||||
|
IndirectArgument = 1 << 10,
|
||||||
|
Present = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CommandQueueType
|
||||||
|
{
|
||||||
|
Graphics,
|
||||||
|
Compute,
|
||||||
|
Copy
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum CommandBufferType
|
||||||
|
{
|
||||||
|
Graphics,
|
||||||
|
Compute,
|
||||||
|
Copy
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PipelineType
|
||||||
|
{
|
||||||
|
Graphics,
|
||||||
|
Compute
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum RenderTargetCreationFlags
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
AllowUAV = 1 << 0,
|
||||||
|
AllowMSAA = 1 << 1,
|
||||||
|
DynamicallyResolution = 1 << 2,
|
||||||
|
GenerateMips = 1 << 3
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ResourceMemoryType
|
||||||
|
{
|
||||||
|
Default, // GPU memory
|
||||||
|
Upload, // CPU-to-GPU memory
|
||||||
|
Readback // GPU-to-CPU memory
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum TextureUsage
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
ShaderResource = 1 << 0,
|
||||||
|
RenderTarget = 1 << 1,
|
||||||
|
DepthStencil = 1 << 2,
|
||||||
|
UnorderedAccess = 1 << 3
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TextureDimension
|
||||||
|
{
|
||||||
|
Unknown = -1,
|
||||||
|
None = 0,
|
||||||
|
Texture2D = 1,
|
||||||
|
Texture3D = 2,
|
||||||
|
TextureCube = 3,
|
||||||
|
Texture2DArray = 4,
|
||||||
|
TextureCubeArray = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum RenderTargetType
|
||||||
|
{
|
||||||
|
Color,
|
||||||
|
Depth
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Support compressed formats (BCn, ASTC, ETC2, etc)
|
||||||
|
public enum TextureFormat
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
R8G8B8A8_UNorm,
|
||||||
|
B8G8R8A8_UNorm,
|
||||||
|
R16G16B16A16_Float,
|
||||||
|
R32G32B32A32_Float,
|
||||||
|
D24_UNorm_S8_UInt,
|
||||||
|
D32_Float
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum BufferUsage
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Vertex = 1 << 0,
|
||||||
|
Index = 1 << 1,
|
||||||
|
Constant = 1 << 2,
|
||||||
|
Structured = 1 << 3,
|
||||||
|
Raw = 1 << 4,
|
||||||
|
Upload = 1 << 5,
|
||||||
|
Readback = 1 << 6,
|
||||||
|
IndirectArgument = 1 << 7,
|
||||||
|
|
||||||
|
ShaderResource = Vertex | Index | Constant
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum IndexType
|
||||||
|
{
|
||||||
|
UInt16,
|
||||||
|
UInt32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shader compiler
|
||||||
|
|
||||||
|
internal ref struct CompilerConfig
|
||||||
|
{
|
||||||
|
public ReadOnlySpan<string> includes;
|
||||||
|
public ReadOnlySpan<string> defines;
|
||||||
|
public string shaderPath;
|
||||||
|
public string entryPoint;
|
||||||
|
public ShaderStage stage;
|
||||||
|
public CompilerTier tier;
|
||||||
|
public CompilerOptimizeLevel optimizeLevel;
|
||||||
|
public CompilerOption options;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum CompilerTier
|
||||||
|
{
|
||||||
|
Tier0,
|
||||||
|
Tier1,
|
||||||
|
Tier2
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum CompilerOptimizeLevel
|
||||||
|
{
|
||||||
|
O0,
|
||||||
|
O1,
|
||||||
|
O2,
|
||||||
|
O3
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
internal enum CompilerOption
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
KeepDebugInfo = 1 << 0,
|
||||||
|
KeepReflections = 1 << 1,
|
||||||
|
WarnAsError = 1 << 2
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum ShaderStage
|
||||||
|
{
|
||||||
|
TaskShader,
|
||||||
|
MeshShader,
|
||||||
|
PixelShader,
|
||||||
|
ComputeShader
|
||||||
|
}
|
||||||
@@ -131,51 +131,6 @@ public interface ICommandBuffer : IDisposable
|
|||||||
public void CopyBuffer(Handle<GraphicsBuffer> dest, Handle<GraphicsBuffer> src, ulong destOffset = 0, ulong srcOffset = 0, ulong numBytes = 0);
|
public void CopyBuffer(Handle<GraphicsBuffer> dest, Handle<GraphicsBuffer> src, ulong destOffset = 0, ulong srcOffset = 0, ulong numBytes = 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Viewport description
|
|
||||||
/// </summary>
|
|
||||||
public struct ViewportDesc
|
|
||||||
{
|
|
||||||
public float x;
|
|
||||||
public float y;
|
|
||||||
public float width;
|
|
||||||
public float height;
|
|
||||||
public float minDepth;
|
|
||||||
public float maxDepth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Rectangle description
|
|
||||||
/// </summary>
|
|
||||||
public struct RectDesc
|
|
||||||
{
|
|
||||||
public uint left;
|
|
||||||
public uint top;
|
|
||||||
public uint right;
|
|
||||||
public uint bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resource states
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
public enum ResourceState
|
|
||||||
{
|
|
||||||
Common = 0,
|
|
||||||
VertexAndConstantBuffer = 1 << 0,
|
|
||||||
IndexBuffer = 1 << 1,
|
|
||||||
RenderTarget = 1 << 2,
|
|
||||||
UnorderedAccess = 1 << 3,
|
|
||||||
DepthWrite = 1 << 4,
|
|
||||||
DepthRead = 1 << 5,
|
|
||||||
PixelShaderResource = 1 << 6,
|
|
||||||
CopyDest = 1 << 7,
|
|
||||||
CopySource = 1 << 8,
|
|
||||||
GenericRead = 1 << 9,
|
|
||||||
IndirectArgument = 1 << 10,
|
|
||||||
Present = 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class ResourceStateExtensions
|
internal static class ResourceStateExtensions
|
||||||
{
|
{
|
||||||
public static D3D12_RESOURCE_STATES ToD3D12States(this ResourceState state)
|
public static D3D12_RESOURCE_STATES ToD3D12States(this ResourceState state)
|
||||||
@@ -196,11 +151,3 @@ internal static class ResourceStateExtensions
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public struct SubResourceData
|
|
||||||
{
|
|
||||||
public unsafe void* pData;
|
|
||||||
public nint rowPitch;
|
|
||||||
public nint slicePitch;
|
|
||||||
}
|
|
||||||
@@ -48,14 +48,4 @@ public interface ICommandQueue : IDisposable
|
|||||||
/// Waits until all submitted commands have finished executing
|
/// Waits until all submitted commands have finished executing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void WaitIdle();
|
public void WaitIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command queue types
|
|
||||||
/// </summary>
|
|
||||||
public enum CommandQueueType
|
|
||||||
{
|
|
||||||
Graphics,
|
|
||||||
Compute,
|
|
||||||
Copy
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core.Graphics;
|
||||||
using Ghost.Graphics.Data;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics.RHI;
|
namespace Ghost.Graphics.RHI;
|
||||||
|
|
||||||
@@ -16,9 +15,8 @@ public interface IShaderPipeline
|
|||||||
|
|
||||||
public interface IPipelineLibrary
|
public interface IPipelineLibrary
|
||||||
{
|
{
|
||||||
public void CompileShader(Identifier<Shader> id, string shaderPath);
|
void CompilePass(IPassDescriptor descriptor);
|
||||||
|
void CompileShader(ShaderDescriptor descriptor);
|
||||||
public void PreCookPipelineState();
|
void PreCookPipelineState();
|
||||||
|
void SaveLibraryToDisk(string filePath);
|
||||||
public IShaderPipeline GetShaderPipeline(Identifier<Shader> id);
|
|
||||||
}
|
}
|
||||||
@@ -28,14 +28,4 @@ public interface IRenderDevice : IDisposable
|
|||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command buffer types
|
|
||||||
/// </summary>
|
|
||||||
public enum CommandBufferType
|
|
||||||
{
|
|
||||||
Graphics,
|
|
||||||
Compute,
|
|
||||||
Copy
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,3 @@
|
|||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using TerraFX.Interop.DirectX;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics.RHI;
|
namespace Ghost.Graphics.RHI;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -16,391 +12,4 @@ public interface IRootSignature : IDisposable
|
|||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pipeline types
|
|
||||||
/// </summary>
|
|
||||||
public enum PipelineType
|
|
||||||
{
|
|
||||||
Graphics,
|
|
||||||
Compute
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
|
||||||
public struct ResourceDesc
|
|
||||||
{
|
|
||||||
[FieldOffset(0)]
|
|
||||||
public TextureDesc textureDescription;
|
|
||||||
|
|
||||||
[FieldOffset(0)]
|
|
||||||
public BufferDesc bufferDescription;
|
|
||||||
|
|
||||||
public static ResourceDesc Buffer(BufferDesc desc)
|
|
||||||
{
|
|
||||||
return new ResourceDesc
|
|
||||||
{
|
|
||||||
bufferDescription = desc
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ResourceDesc Texture(TextureDesc desc)
|
|
||||||
{
|
|
||||||
return new ResourceDesc
|
|
||||||
{
|
|
||||||
textureDescription = desc
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static ResourceDesc FromD3D12(D3D12_RESOURCE_DESC desc)
|
|
||||||
{
|
|
||||||
if (desc.Dimension == D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_BUFFER)
|
|
||||||
{
|
|
||||||
return Buffer(new BufferDesc
|
|
||||||
{
|
|
||||||
Size = (uint)desc.Width,
|
|
||||||
Stride = 0,
|
|
||||||
Usage = BufferUsage.None,
|
|
||||||
MemoryType = MemoryType.Default
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Texture(new TextureDesc
|
|
||||||
{
|
|
||||||
Width = (uint)desc.Width,
|
|
||||||
Height = desc.Height,
|
|
||||||
Slice = desc.DepthOrArraySize,
|
|
||||||
Format = desc.Format.ToTextureFormat(),
|
|
||||||
Dimension = desc.Dimension.ToTextureDimension(),
|
|
||||||
MipLevels = desc.MipLevels,
|
|
||||||
Usage = TextureUsage.None,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Render target description
|
|
||||||
/// Supports either color OR depth rendering, not both
|
|
||||||
/// </summary>
|
|
||||||
public struct RenderTargetDesc
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Width of the render target
|
|
||||||
/// </summary>
|
|
||||||
public uint Width
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Height of the render target
|
|
||||||
/// </summary>
|
|
||||||
public uint Height
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Slice of the render target
|
|
||||||
/// </summary>
|
|
||||||
public uint Slice
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Type of render target
|
|
||||||
/// </summary>
|
|
||||||
public RenderTargetType Type
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Target texture format
|
|
||||||
/// </summary>
|
|
||||||
public TextureFormat Format
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Texture dimension
|
|
||||||
/// </summary>
|
|
||||||
public TextureDimension Dimension
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creation flags for the render target
|
|
||||||
/// </summary>
|
|
||||||
public RenderTargetCreationFlags CreationFlags
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of mip levels. 0 to generate full mip chain
|
|
||||||
/// </summary>
|
|
||||||
public uint MipLevels
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of samples for MSAA
|
|
||||||
/// </summary>
|
|
||||||
public uint SampleCount
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a color render target
|
|
||||||
/// </summary>
|
|
||||||
public static RenderTargetDesc Color(uint width, uint height, uint slice = 1,
|
|
||||||
TextureFormat format = TextureFormat.R8G8B8A8_UNorm, TextureDimension dimension = TextureDimension.Texture2D,
|
|
||||||
RenderTargetCreationFlags creationFlags = RenderTargetCreationFlags.AllowUAV | RenderTargetCreationFlags.DynamicallyResolution | RenderTargetCreationFlags.GenerateMips,
|
|
||||||
uint mipLevels = 0u, uint sampleCount = 1)
|
|
||||||
{
|
|
||||||
return new RenderTargetDesc
|
|
||||||
{
|
|
||||||
Width = width,
|
|
||||||
Height = height,
|
|
||||||
Slice = slice,
|
|
||||||
Type = RenderTargetType.Color,
|
|
||||||
Format = format,
|
|
||||||
Dimension = dimension,
|
|
||||||
CreationFlags = creationFlags,
|
|
||||||
MipLevels = mipLevels,
|
|
||||||
SampleCount = sampleCount
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a depth render target
|
|
||||||
/// </summary>
|
|
||||||
public static RenderTargetDesc Depth(uint width, uint height, uint slice = 1,
|
|
||||||
TextureFormat format = TextureFormat.D24_UNorm_S8_UInt, TextureDimension dimension = TextureDimension.Texture2D,
|
|
||||||
RenderTargetCreationFlags creationFlags = RenderTargetCreationFlags.AllowUAV | RenderTargetCreationFlags.DynamicallyResolution,
|
|
||||||
uint mipLevels = 0u, uint sampleCount = 1)
|
|
||||||
{
|
|
||||||
return new RenderTargetDesc
|
|
||||||
{
|
|
||||||
Width = width,
|
|
||||||
Height = height,
|
|
||||||
Slice = slice,
|
|
||||||
Type = RenderTargetType.Depth,
|
|
||||||
Format = format,
|
|
||||||
Dimension = dimension,
|
|
||||||
CreationFlags = creationFlags,
|
|
||||||
MipLevels = mipLevels,
|
|
||||||
SampleCount = sampleCount
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static TextureDesc ToTextureDescripton(RenderTargetDesc desc)
|
|
||||||
{
|
|
||||||
var usage = desc.Type == RenderTargetType.Color ? TextureUsage.RenderTarget : TextureUsage.DepthStencil;
|
|
||||||
if (desc.CreationFlags.HasFlag(RenderTargetCreationFlags.AllowUAV))
|
|
||||||
{
|
|
||||||
usage |= TextureUsage.UnorderedAccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TextureDesc
|
|
||||||
{
|
|
||||||
Width = desc.Width,
|
|
||||||
Height = desc.Height,
|
|
||||||
Slice = desc.Slice,
|
|
||||||
Format = desc.Format,
|
|
||||||
Dimension = desc.Dimension,
|
|
||||||
MipLevels = desc.MipLevels,
|
|
||||||
Usage = usage,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Texture description
|
|
||||||
/// </summary>
|
|
||||||
public struct TextureDesc
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Width of the texture
|
|
||||||
/// </summary>
|
|
||||||
public uint Width
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Height of the texture
|
|
||||||
/// </summary>
|
|
||||||
public uint Height
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Slice of the texture
|
|
||||||
/// </summary>
|
|
||||||
public uint Slice
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Texture format
|
|
||||||
/// </summary>
|
|
||||||
public TextureFormat Format
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Texture dimension
|
|
||||||
/// </summary>
|
|
||||||
public TextureDimension Dimension
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Number of mip levels. 0 to generate full mip chain
|
|
||||||
/// </summary>
|
|
||||||
public uint MipLevels
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Texture usage flags
|
|
||||||
/// </summary>
|
|
||||||
public TextureUsage Usage
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Buffer description
|
|
||||||
/// </summary>
|
|
||||||
public struct BufferDesc
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Size of the buffer in bytes
|
|
||||||
/// </summary>
|
|
||||||
public uint Size
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint Stride
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Buffer usage flags
|
|
||||||
/// </summary>
|
|
||||||
public BufferUsage Usage
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Memory type for the buffer
|
|
||||||
/// </summary>
|
|
||||||
public MemoryType MemoryType
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Texture usage flags
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
public enum TextureUsage
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
ShaderResource = 1 << 0,
|
|
||||||
RenderTarget = 1 << 1,
|
|
||||||
DepthStencil = 1 << 2,
|
|
||||||
UnorderedAccess = 1 << 3
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Dimensions of the texture
|
|
||||||
/// </summary>
|
|
||||||
public enum TextureDimension
|
|
||||||
{
|
|
||||||
Unknown = -1,
|
|
||||||
None = 0,
|
|
||||||
Texture2D = 1,
|
|
||||||
Texture3D = 2,
|
|
||||||
TextureCube = 3,
|
|
||||||
Texture2DArray = 4,
|
|
||||||
TextureCubeArray = 5
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TextureDimensionExtension
|
|
||||||
{
|
|
||||||
public static TextureDimension ToTextureDimension(this D3D12_RESOURCE_DIMENSION dimension)
|
|
||||||
{
|
|
||||||
return dimension switch
|
|
||||||
{
|
|
||||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE1D => TextureDimension.Texture2D,
|
|
||||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE2D => TextureDimension.Texture2D,
|
|
||||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE3D => TextureDimension.Texture3D,
|
|
||||||
_ => TextureDimension.Unknown,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Render target creation flags
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
public enum RenderTargetCreationFlags
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
AllowUAV = 1 << 0,
|
|
||||||
AllowMSAA = 1 << 1,
|
|
||||||
DynamicallyResolution = 1 << 2,
|
|
||||||
GenerateMips = 1 << 3
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Memory types for resources
|
|
||||||
/// </summary>
|
|
||||||
public enum MemoryType
|
|
||||||
{
|
|
||||||
Default, // GPU memory
|
|
||||||
Upload, // CPU-to-GPU memory
|
|
||||||
Readback // GPU-to-CPU memory
|
|
||||||
}
|
}
|
||||||
@@ -2,56 +2,6 @@ using TerraFX.Interop.DirectX;
|
|||||||
|
|
||||||
namespace Ghost.Graphics.RHI;
|
namespace Ghost.Graphics.RHI;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Type of render target
|
|
||||||
/// </summary>
|
|
||||||
public enum RenderTargetType
|
|
||||||
{
|
|
||||||
Color,
|
|
||||||
Depth
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Texture format enumeration
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
// TODO: Support compressed formats (BCn, ASTC, ETC2, etc)
|
|
||||||
public enum TextureFormat
|
|
||||||
{
|
|
||||||
Unknown,
|
|
||||||
R8G8B8A8_UNorm,
|
|
||||||
B8G8R8A8_UNorm,
|
|
||||||
R16G16B16A16_Float,
|
|
||||||
R32G32B32A32_Float,
|
|
||||||
D24_UNorm_S8_UInt,
|
|
||||||
D32_Float
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Buffer usage flags
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
public enum BufferUsage
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Vertex = 1 << 0,
|
|
||||||
Index = 1 << 1,
|
|
||||||
Constant = 1 << 2,
|
|
||||||
Structured = 1 << 3,
|
|
||||||
Raw = 1 << 4,
|
|
||||||
Upload = 1 << 5,
|
|
||||||
Readback = 1 << 6,
|
|
||||||
IndirectArgument = 1 << 7,
|
|
||||||
|
|
||||||
ShaderResource = Vertex | Index | Constant
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum IndexType
|
|
||||||
{
|
|
||||||
UInt16,
|
|
||||||
UInt32
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class TextureFormatExtensions
|
internal static class TextureFormatExtensions
|
||||||
{
|
{
|
||||||
public static DXGI_FORMAT ToD3D12Format(this TextureFormat format)
|
public static DXGI_FORMAT ToD3D12Format(this TextureFormat format)
|
||||||
|
|||||||
@@ -3,6 +3,14 @@ using Ghost.Graphics.Data;
|
|||||||
|
|
||||||
namespace Ghost.Graphics.RHI;
|
namespace Ghost.Graphics.RHI;
|
||||||
|
|
||||||
|
public interface IResourceReleasable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A method to release GPU resources.
|
||||||
|
/// </summary>
|
||||||
|
void ReleaseResource(IResourceDatabase database);
|
||||||
|
}
|
||||||
|
|
||||||
public interface IResourceDatabase
|
public interface IResourceDatabase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -12,7 +20,7 @@ public interface IResourceDatabase
|
|||||||
/// <param name="resourcePtr">A pointer to the external unmanaged resource to be imported. Must remain valid for the duration of the resource's usage.</param>
|
/// <param name="resourcePtr">A pointer to the external unmanaged resource to be imported. Must remain valid for the duration of the resource's usage.</param>
|
||||||
/// <param name="initialState">The initial state to assign to the imported resource.</param>
|
/// <param name="initialState">The initial state to assign to the imported resource.</param>
|
||||||
/// <returns>A handle representing the imported resource, which can be used for subsequent operations.</returns>
|
/// <returns>A handle representing the imported resource, which can be used for subsequent operations.</returns>
|
||||||
public unsafe Handle<GPUResource> ImportExternalResource<T>(T resourcePtr, ResourceState initialState)
|
unsafe Handle<GPUResource> ImportExternalResource<T>(T resourcePtr, ResourceState initialState)
|
||||||
where T : unmanaged;
|
where T : unmanaged;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -20,113 +28,129 @@ public interface IResourceDatabase
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">The handle that uniquely identifies the resource whose state is to be retrieved. Must not be null.</param>
|
/// <param name="handle">The handle that uniquely identifies the resource whose state is to be retrieved. Must not be null.</param>
|
||||||
/// <returns>A ResourceState value representing the current state of the resource associated with the specified handle.</returns>
|
/// <returns>A ResourceState value representing the current state of the resource associated with the specified handle.</returns>
|
||||||
public ResourceState GetResourceState(Handle<GPUResource> handle);
|
ResourceState GetResourceState(Handle<GPUResource> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the state of the specified resource handle to the given value.
|
/// Sets the state of the specified resource handle to the given value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">The handle that identifies the resource whose state will be updated. Cannot be null.</param>
|
/// <param name="handle">The handle that identifies the resource whose state will be updated. Cannot be null.</param>
|
||||||
/// <param name="state">The new state to assign to the resource represented by <paramref name="handle"/>.</param>
|
/// <param name="state">The new state to assign to the resource represented by <paramref name="handle"/>.</param>
|
||||||
public void SetResourceState(Handle<GPUResource> handle, ResourceState state);
|
void SetResourceState(Handle<GPUResource> handle, ResourceState state);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the description of a GPU resource associated with the specified handle.
|
/// Retrieves the description of a GPU resource associated with the specified handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">A handle that identifies the GPU resource for which to obtain the description. Must reference a valid resource.</param>
|
/// <param name="handle">A handle that identifies the GPU resource for which to obtain the description. Must reference a valid resource.</param>
|
||||||
/// <returns>A ResourceDesc structure containing details about the specified GPU resource.</returns>
|
/// <returns>A ResourceDesc structure containing details about the specified GPU resource.</returns>
|
||||||
public ResourceDesc GetResourceDescription(Handle<GPUResource> handle);
|
ResourceDesc GetResourceDescription(Handle<GPUResource> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the bindless index associated with the specified GPU resource handle.
|
/// Retrieves the bindless index associated with the specified GPU resource handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">A handle to the GPU resource for which to obtain the bindless index. Must reference a valid, currently registered resource.</param>
|
/// <param name="handle">A handle to the GPU resource for which to obtain the bindless index. Must reference a valid, currently registered resource.</param>
|
||||||
/// <returns>The bindless index corresponding to the specified GPU resource handle. -1 if the resource does not support bindless access or is not found.</returns>
|
/// <returns>The bindless index corresponding to the specified GPU resource handle. -1 if the resource does not support bindless access or is not found.</returns>
|
||||||
public int GetBindlessIndex(Handle<GPUResource> handle);
|
int GetBindlessIndex(Handle<GPUResource> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes a resource from the database using its handle.
|
/// Removes a resource from the database using its handle.
|
||||||
/// </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>
|
||||||
public void ReleaseResource(Handle<GPUResource> handle);
|
void ReleaseResource(Handle<GPUResource> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a mesh to the resource database and returns its handle.
|
/// Adds a mesh to the resource database and returns its handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mesh">The mesh data to be added to the database.</param>
|
/// <param name="mesh">The mesh data to be added to the database.</param>
|
||||||
/// <returns>The <see cref="Handle{Mesh}"/> representing the newly added mesh.</returns>"/>
|
/// <returns>The <see cref="Handle{Mesh}"/> representing the newly added mesh.</returns>"/>
|
||||||
public Handle<Mesh> AddMesh(ref readonly Mesh mesh);
|
Handle<Mesh> AddMesh(ref readonly Mesh mesh);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether a mesh with the specified Handle exists.
|
/// Determines whether a mesh with the specified Handle exists.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">The handle of the mesh to check for existence. Cannot be null.</param>
|
/// <param name="handle">The handle of the mesh to check for existence. Cannot be null.</param>
|
||||||
/// <returns>true if a mesh with the specified Handle exists; otherwise, false.</returns>
|
/// <returns>true if a mesh with the specified Handle exists; otherwise, false.</returns>
|
||||||
public bool HasMesh(Handle<Mesh> handle);
|
bool HasMesh(Handle<Mesh> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a reference to the mesh associated with the specified handle.
|
/// Returns a reference to the mesh associated with the specified handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">The handle of the mesh to retrieve. Must refer to a valid mesh; otherwise, the behavior is undefined.</param>
|
/// <param name="handle">The handle of the mesh to retrieve. Must refer to a valid mesh; otherwise, the behavior is undefined.</param>
|
||||||
/// <returns>A reference to the mesh corresponding to the specified handle.</returns>
|
/// <returns>A reference to the mesh corresponding to the specified handle.</returns>
|
||||||
public ref Mesh GetMeshReference(Handle<Mesh> handle);
|
ref Mesh GetMeshReference(Handle<Mesh> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Releases the mesh resource associated with the specified handle, freeing any resources held by it. Includes both CPU and GPU resources.
|
/// Releases the mesh resource associated with the specified handle, freeing any resources held by it. Includes both CPU and GPU resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">The handle of the mesh to release. Must refer to a mesh that was previously created and not already released.</param>
|
/// <param name="handle">The handle of the mesh to release. Must refer to a mesh that was previously created and not already released.</param>
|
||||||
public void ReleaseMesh(Handle<Mesh> handle);
|
void ReleaseMesh(Handle<Mesh> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a new material to the collection and returns its unique handle.
|
/// Adds a new material to the collection and returns its unique handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="material">The material to add. The material must be fully initialized before calling this method.</param>
|
/// <param name="material">The material to add. The material must be fully initialized before calling this method.</param>
|
||||||
/// <returns>The <see cref="Handle{Material}"/> representing the newly added material.</returns>
|
/// <returns>The <see cref="Handle{Material}"/> representing the newly added material.</returns>
|
||||||
public Handle<Material> AddMaterial(ref readonly Material material);
|
Handle<Material> AddMaterial(ref readonly Material material);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether a material with the specified handle exists in the collection.
|
/// Determines whether a material with the specified handle exists in the collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">The handle of the material to check for existence.</param>
|
/// <param name="handle">The handle of the material to check for existence.</param>
|
||||||
/// <returns>true if a material with the specified handle exists; otherwise, false.</returns>
|
/// <returns>true if a material with the specified handle exists; otherwise, false.</returns>
|
||||||
public bool HasMaterial(Handle<Material> handle);
|
bool HasMaterial(Handle<Material> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a reference to the material associated with the specified handle.
|
/// Gets a reference to the material associated with the specified handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">The handle of the material to retrieve. Must refer to a valid material.</param>
|
/// <param name="handle">The handle of the material to retrieve. Must refer to a valid material.</param>
|
||||||
/// <returns>A reference to the material corresponding to the specified handle.</returns>
|
/// <returns>A reference to the material corresponding to the specified handle.</returns>
|
||||||
public ref Material GetMaterialReference(Handle<Material> handle);
|
ref Material GetMaterialReference(Handle<Material> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Releases the material associated with the specified handle, making it available for reuse or disposal.
|
/// Releases the material associated with the specified handle, making it available for reuse or disposal.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">The handle of the material to release. Must refer to a material that has been previously acquired.</param>
|
/// <param name="handle">The handle of the material to release. Must refer to a material that has been previously acquired.</param>
|
||||||
public void ReleaseMaterial(Handle<Material> handle);
|
void ReleaseMaterial(Handle<Material> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the specified shader to the collection and returns its unique identifier.
|
/// Adds the specified shader to the collection and returns its unique identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="shader">The shader to add. The shader is passed by read-only reference and will not be modified.</param>
|
/// <param name="shader">The shader to add. The shader is passed by read-only reference and will not be modified.</param>
|
||||||
/// <returns>The <see cref="Identifier{Shader}"/> representing the newly added shader.</returns>
|
/// <returns>The <see cref="Identifier{Shader}"/> representing the newly added shader.</returns>
|
||||||
public Identifier<Shader> AddShader(ref readonly Shader shader);
|
Identifier<Shader> AddShader(ref readonly Shader shader);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether a shader with the specified identifier exists in the collection.
|
/// Determines whether a shader with the specified identifier exists in the collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The identifier of the shader to check for existence.</param>
|
/// <param name="id">The identifier of the shader to check for existence.</param>
|
||||||
/// <returns>true if a shader with the specified identifier exists; otherwise, false.</returns>
|
/// <returns>true if a shader with the specified identifier exists; otherwise, false.</returns>
|
||||||
public bool HasShader(Identifier<Shader> id);
|
bool HasShader(Identifier<Shader> id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a reference to the shader associated with the specified identifier.
|
/// Returns a reference to the shader associated with the specified identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The identifier of the shader to retrieve. Must refer to a valid shader.</param>
|
/// <param name="id">The identifier of the shader to retrieve. Must refer to a valid shader.</param>
|
||||||
/// <returns>A reference to the shader corresponding to the specified identifier.</returns>
|
/// <returns>A reference to the shader corresponding to the specified identifier.</returns>
|
||||||
public ref Shader GetShaderReference(Identifier<Shader> id);
|
ref Shader GetShaderReference(Identifier<Shader> id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Releases the shader associated with the specified identifier, freeing any resources allocated to it.
|
/// Releases the shader associated with the specified identifier, freeing any resources allocated to it.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">The identifier of the shader to release. Must refer to a valid, previously created shader.</param>
|
/// <param name="id">The identifier of the shader to release. Must refer to a valid, previously created shader.</param>
|
||||||
public void ReleaseShader(Identifier<Shader> id);
|
void ReleaseShader(Identifier<Shader> id);
|
||||||
|
|
||||||
|
// TODO: Use xxhash3 to generate passKey from string id.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a shader pass to the collection using the specified identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="passKey">The unique identifier for the shader pass.</param>
|
||||||
|
/// <param name="pass">The shader pass to add. Cannot be null.</param>
|
||||||
|
void AddShaderPass(ShaderPassKey passKey, ShaderPass pass);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the shader pass associated with the specified pass identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="passKey">The unique identifier of the shader pass to retrieve.</param>
|
||||||
|
/// <returns>The <see cref="ShaderPass"/> corresponding to the specified identifier, or null if no matching shader pass is found.</returns>
|
||||||
|
ShaderPass GetShaderPass(ShaderPassKey passKey);
|
||||||
}
|
}
|
||||||
@@ -4,8 +4,6 @@ using Ghost.Graphics.Data;
|
|||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Ghost.Graphics.Utilities;
|
using Ghost.Graphics.Utilities;
|
||||||
using Misaki.HighPerformance.Image;
|
using Misaki.HighPerformance.Image;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
|
||||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
|
||||||
|
|
||||||
namespace Ghost.Graphics.RenderPasses;
|
namespace Ghost.Graphics.RenderPasses;
|
||||||
|
|
||||||
|
|||||||
@@ -28,38 +28,43 @@ struct PixelInput
|
|||||||
float4 uv : TEXCOORD0;
|
float4 uv : TEXCOORD0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bindless vertex shader that fetches vertex data from bindless buffers
|
[NumThreads(3, 1, 1)] // 3 threads per triangle
|
||||||
PixelInput VSMain(uint vertexId : SV_VertexID, uint instanceId : SV_InstanceID)
|
[OutputTopology("triangle")]
|
||||||
|
void MSMain(
|
||||||
|
uint3 groupThreadID : SV_GroupThreadID,
|
||||||
|
uint groupID : SV_GroupID,
|
||||||
|
out vertices PixelInput outVerts[3],
|
||||||
|
out indices uint3 outTris[1])
|
||||||
{
|
{
|
||||||
// Get bindless buffers
|
// Fetch bindless buffers
|
||||||
ByteAddressBuffer vertexBuffer = ResourceDescriptorHeap[_VertexBufferIndex];
|
ByteAddressBuffer vertexBuffer = ResourceDescriptorHeap[_VertexBufferIndex];
|
||||||
ByteAddressBuffer indexBuffer = ResourceDescriptorHeap[_IndexBufferIndex];
|
ByteAddressBuffer indexBuffer = ResourceDescriptorHeap[_IndexBufferIndex];
|
||||||
|
|
||||||
// For fully bindless rendering, we use instanced drawing where:
|
// Compute the triangle’s vertex indices
|
||||||
// - Each instance represents a triangle (instanceId = triangle index)
|
uint vertexId = groupThreadID.x;
|
||||||
// - vertexId goes from 0 to 2 (the 3 vertices of the triangle)
|
uint indexOffset = (groupID.x * 3 + vertexId) * 4; // uint32 index
|
||||||
|
|
||||||
// Calculate the index into the index buffer
|
|
||||||
uint indexOffset = (instanceId * 3 + vertexId) * 4; // 4 bytes per index (uint32)
|
|
||||||
uint vertexIndex = indexBuffer.Load(indexOffset);
|
uint vertexIndex = indexBuffer.Load(indexOffset);
|
||||||
|
|
||||||
// Calculate the offset into the vertex buffer
|
// Load vertex attributes
|
||||||
uint vertexOffset = vertexIndex * 80; // 80 bytes per vertex (5 * float4)
|
uint vertexOffset = vertexIndex * 80; // 80 bytes per vertex
|
||||||
|
Vertex v;
|
||||||
// Load vertex data from bindless vertex buffer
|
v.position = asfloat(vertexBuffer.Load4(vertexOffset + 0));
|
||||||
Vertex vertex;
|
v.normal = asfloat(vertexBuffer.Load4(vertexOffset + 16));
|
||||||
vertex.position = asfloat(vertexBuffer.Load4(vertexOffset + 0));
|
v.tangent = asfloat(vertexBuffer.Load4(vertexOffset + 32));
|
||||||
vertex.normal = asfloat(vertexBuffer.Load4(vertexOffset + 16));
|
v.color = asfloat(vertexBuffer.Load4(vertexOffset + 48));
|
||||||
vertex.tangent = asfloat(vertexBuffer.Load4(vertexOffset + 32));
|
v.uv = asfloat(vertexBuffer.Load4(vertexOffset + 64));
|
||||||
vertex.color = asfloat(vertexBuffer.Load4(vertexOffset + 48));
|
|
||||||
vertex.uv = asfloat(vertexBuffer.Load4(vertexOffset + 64));
|
// Write vertex output
|
||||||
|
outVerts[vertexId].position = v.position;
|
||||||
// Output transformed vertex
|
outVerts[vertexId].color = v.color;
|
||||||
PixelInput output;
|
outVerts[vertexId].uv = v.uv;
|
||||||
output.position = vertex.position;
|
|
||||||
output.color = vertex.color;
|
// Thread 0 defines topology
|
||||||
output.uv = vertex.uv;
|
if (vertexId == 0)
|
||||||
return output;
|
{
|
||||||
|
SetMeshOutputCounts(3, 1);
|
||||||
|
outTris[0] = uint3(0, 1, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 PSMain(PixelInput input) : SV_TARGET
|
float4 PSMain(PixelInput input) : SV_TARGET
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
shader "MyShader/Standard"
|
shader "MyShader/Standard"
|
||||||
{
|
{
|
||||||
fallback("Ghost/Standard"); // This is a test comment.
|
|
||||||
|
|
||||||
// Another comment.
|
|
||||||
properties
|
properties
|
||||||
{
|
{
|
||||||
global uint test;
|
|
||||||
global texture2d global_texture;
|
|
||||||
float4 color = float4(1, 1, 1, 1);
|
float4 color = float4(1, 1, 1, 1);
|
||||||
texture2d texture1 = texture2d(black);
|
texture2d texture1 = texture2d(black);
|
||||||
texture2d texture2 = texture2d(white);
|
texture2d texture2 = texture2d(white);
|
||||||
@@ -23,30 +18,9 @@ shader "MyShader/Standard"
|
|||||||
color_mask = 0;
|
color_mask = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
This is a
|
|
||||||
multi-line comment.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pass "Forward"
|
pass "Forward"
|
||||||
{
|
{
|
||||||
vs("F:/csharp/GhostEngine/Ghost.Graphics/RenderPasses/ShaderCode.hlsl", "VSMain");
|
ms("F:/csharp/GhostEngine/Ghost.Graphics/RenderPasses/ShaderCode.hlsl", "MSMain");
|
||||||
ps("F:/csharp/GhostEngine/Ghost.Graphics/RenderPasses/ShaderCode.hlsl", "PSMain");
|
|
||||||
|
|
||||||
includes
|
|
||||||
{
|
|
||||||
"F:/csharp/GhostEngine/Ghost.Shader/BuiltIn/Common.hlsl";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pass "DepthOnly"
|
|
||||||
{
|
|
||||||
properties
|
|
||||||
{
|
|
||||||
float testProp = float(0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
vs("F:/csharp/GhostEngine/Ghost.Graphics/RenderPasses/ShaderCode.hlsl", "VSMain");
|
|
||||||
ps("F:/csharp/GhostEngine/Ghost.Graphics/RenderPasses/ShaderCode.hlsl", "PSMain");
|
ps("F:/csharp/GhostEngine/Ghost.Graphics/RenderPasses/ShaderCode.hlsl", "PSMain");
|
||||||
|
|
||||||
includes
|
includes
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
using Ghost.Shader.Compiler;
|
using Ghost.Shader.Compiler;
|
||||||
using Ghost.Shader.Generator;
|
|
||||||
using Misaki.HighPerformance.Mathematics;
|
using Misaki.HighPerformance.Mathematics;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
ShaderStructGenerator.GenerateHLSL([typeof(TestStruct), typeof(TestEnum), typeof(TestEnumFlags)], PackingRules.Exact, "C:/Users/Misaki/Downloads/Archive/Test.cs.hlsl");
|
//ShaderStructGenerator.GenerateHLSL([typeof(TestStruct), typeof(TestEnum), typeof(TestEnumFlags)], PackingRules.Exact, "C:/Users/Misaki/Downloads/Archive/Test.cs.hlsl");
|
||||||
|
|
||||||
return;
|
//return;
|
||||||
|
|
||||||
var source = File.ReadAllText("F:/csharp/GhostEngine/Ghost.Graphics/test.gshader");
|
var source = File.ReadAllText("F:/csharp/GhostEngine/Ghost.Graphics/test.gshader");
|
||||||
|
|
||||||
@@ -17,6 +16,10 @@ var model = ShaderCompiler.SemanticAnalysis(shaderInfo[0], out var errors);
|
|||||||
foreach (var error in errors)
|
foreach (var error in errors)
|
||||||
{
|
{
|
||||||
Console.WriteLine(error);
|
Console.WriteLine(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors.Count != 0)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Ghost.Shader.Compiler;
|
|
||||||
|
|
||||||
namespace Ghost.Shader.Compiler.Parser;
|
namespace Ghost.Shader.Compiler.Parser;
|
||||||
|
|
||||||
internal class DefinesBlock : IBlockParser<List<Token>, List<string>>
|
internal class DefinesBlock : IBlockParser<List<Token>, List<string>>
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using Ghost.Shader.Compiler;
|
|
||||||
|
|
||||||
namespace Ghost.Shader.Compiler.Parser;
|
namespace Ghost.Shader.Compiler.Parser;
|
||||||
|
|
||||||
internal class IncludesBlock : IBlockParser<List<Token>, List<string>>
|
internal class IncludesBlock : IBlockParser<List<Token>, List<string>>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Ghost.Shader.Compiler.Parser;
|
using Ghost.Core.Graphics;
|
||||||
|
|
||||||
namespace Ghost.Shader.Compiler.Parser;
|
namespace Ghost.Shader.Compiler.Parser;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Ghost.Core.Graphics;
|
||||||
|
|
||||||
namespace Ghost.Shader.Compiler.Parser;
|
namespace Ghost.Shader.Compiler.Parser;
|
||||||
|
|
||||||
// TODO: Add pass template support.
|
// TODO: Add pass template support.
|
||||||
@@ -66,7 +68,7 @@ internal class PassBlock : IBlockParser<PassSyntax, PassSemantic>
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var model = new PassSemantic
|
var semantic = new PassSemantic
|
||||||
{
|
{
|
||||||
name = syntax.name.lexeme,
|
name = syntax.name.lexeme,
|
||||||
defines = DefinesBlock.SemanticAnalysis(syntax.defines, errors),
|
defines = DefinesBlock.SemanticAnalysis(syntax.defines, errors),
|
||||||
@@ -76,8 +78,8 @@ internal class PassBlock : IBlockParser<PassSyntax, PassSemantic>
|
|||||||
localPipeline = PipelineBlock.SemanticAnalysis(syntax.localPipeline, errors),
|
localPipeline = PipelineBlock.SemanticAnalysis(syntax.localPipeline, errors),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (model.localProperties != null
|
if (semantic.localProperties != null
|
||||||
&& model.localProperties.Any(p => p.scope == PropertyScope.Global))
|
&& semantic.localProperties.Any(p => p.scope == PropertyScope.Global))
|
||||||
{
|
{
|
||||||
errors.Add(new ShaderError
|
errors.Add(new ShaderError
|
||||||
{
|
{
|
||||||
@@ -93,50 +95,22 @@ internal class PassBlock : IBlockParser<PassSyntax, PassSemantic>
|
|||||||
{
|
{
|
||||||
switch (func.name.lexeme)
|
switch (func.name.lexeme)
|
||||||
{
|
{
|
||||||
case "vs":
|
case TokenLexicon.KnownFunctions.TASK_SHADER:
|
||||||
if (func.arguments?.Count != 2)
|
AnalysisShaderEntry(errors, func, ref semantic.taskShader);
|
||||||
{
|
|
||||||
errors.Add(new ShaderError
|
|
||||||
{
|
|
||||||
message = "Vertex shader declaration requires exactly two arguments: (shaderPath, entryPoint).",
|
|
||||||
line = func.name.line,
|
|
||||||
column = func.name.column
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
model.vertexShader = new ShaderEntryPoint
|
|
||||||
{
|
|
||||||
shader = func.arguments[0].lexeme,
|
|
||||||
entry = func.arguments[1].lexeme
|
|
||||||
};
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "ps":
|
case TokenLexicon.KnownFunctions.MESH_SHADER:
|
||||||
if (func.arguments?.Count != 2)
|
AnalysisShaderEntry(errors, func, ref semantic.meshShader);
|
||||||
{
|
break;
|
||||||
errors.Add(new ShaderError
|
|
||||||
{
|
case TokenLexicon.KnownFunctions.PIXEL_SHADER:
|
||||||
message = "Pixel shader declaration requires exactly two arguments: (shaderPath, entryPoint).",
|
AnalysisShaderEntry(errors, func, ref semantic.pixelShader);
|
||||||
line = func.name.line,
|
|
||||||
column = func.name.column
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
model.pixelShader = new ShaderEntryPoint
|
|
||||||
{
|
|
||||||
shader = func.arguments[0].lexeme,
|
|
||||||
entry = func.arguments[1].lexeme
|
|
||||||
};
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
errors.Add(new ShaderError
|
errors.Add(new ShaderError
|
||||||
{
|
{
|
||||||
message = $"Unknown function '{func.name.lexeme}' in pass.",
|
message = $"Unknown function '{func.name.lexeme}' in pass {syntax.name.lexeme}.",
|
||||||
line = func.name.line,
|
line = func.name.line,
|
||||||
column = func.name.column
|
column = func.name.column
|
||||||
});
|
});
|
||||||
@@ -145,18 +119,39 @@ internal class PassBlock : IBlockParser<PassSyntax, PassSemantic>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model.vertexShader.shader == null || model.pixelShader.shader == null)
|
if (semantic.meshShader.shader == null || semantic.pixelShader.shader == null)
|
||||||
{
|
{
|
||||||
// TODO: Inheritance from base pass.
|
// TODO: Inheritance from base pass.
|
||||||
// TODO: Add mesh shader support.
|
// TODO: Add mesh shader support.
|
||||||
errors.Add(new ShaderError
|
errors.Add(new ShaderError
|
||||||
{
|
{
|
||||||
message = "Pass must contain a vertex shader (vs) and a pixel shader (ps) declaration.",
|
message = $"Pass {syntax.name.lexeme} must contain a mesh shader (ms) and a pixel shader (ps) declaration.",
|
||||||
line = syntax.name.line,
|
line = syntax.name.line,
|
||||||
column = syntax.name.column
|
column = syntax.name.column
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return model;
|
return semantic;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AnalysisShaderEntry(List<ShaderError> errors, FunctionCallDeclaration func, ref ShaderEntryPoint shaderEntryPoint)
|
||||||
|
{
|
||||||
|
if (func.arguments?.Count != 2)
|
||||||
|
{
|
||||||
|
errors.Add(new ShaderError
|
||||||
|
{
|
||||||
|
message = "Shader declaration requires exactly two arguments: (shaderPath, entryPoint).",
|
||||||
|
line = func.name.line,
|
||||||
|
column = func.name.column
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shaderEntryPoint = new ShaderEntryPoint
|
||||||
|
{
|
||||||
|
shader = func.arguments[0].lexeme,
|
||||||
|
entry = func.arguments[1].lexeme
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using Ghost.Core.Graphics;
|
||||||
|
|
||||||
namespace Ghost.Shader.Compiler.Parser;
|
namespace Ghost.Shader.Compiler.Parser;
|
||||||
|
|
||||||
internal class PipelineBlock : IBlockParser<PipelineSyntax, PipelineSemantic>
|
internal class PipelineBlock : IBlockParser<PipelineSyntax, PipelineSemantic>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using Ghost.Shader.Compiler.Parser;
|
using Ghost.Core.Graphics;
|
||||||
using Misaki.HighPerformance.Mathematics;
|
using Misaki.HighPerformance.Mathematics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Runtime.InteropServices;
|
namespace Ghost.Shader.Compiler.Parser;
|
||||||
|
|
||||||
namespace Ghost.Shader.Compiler.Parser;
|
|
||||||
|
|
||||||
internal class ShaderBlock : IBlockParser<ShaderSyntax, ShaderSemantics>
|
internal class ShaderBlock : IBlockParser<ShaderSyntax, ShaderSemantics>
|
||||||
{
|
{
|
||||||
@@ -110,7 +108,7 @@ internal class ShaderBlock : IBlockParser<ShaderSyntax, ShaderSemantics>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return shaderModel;
|
return shaderModel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Ghost.Shader.Compiler.Parser;
|
using Ghost.Core.Graphics;
|
||||||
using System.Collections.Generic;
|
using Ghost.Shader.Compiler.Parser;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Ghost.Shader.Compiler;
|
namespace Ghost.Shader.Compiler;
|
||||||
@@ -227,7 +227,8 @@ internal static class ShaderCompiler
|
|||||||
var fullPass = new FullPassDescriptor
|
var fullPass = new FullPassDescriptor
|
||||||
{
|
{
|
||||||
uniqueIdentifier = GetPassUniqueId(semantics, pass),
|
uniqueIdentifier = GetPassUniqueId(semantics, pass),
|
||||||
vertexShader = pass.vertexShader,
|
taskShader = pass.taskShader,
|
||||||
|
meshShader = pass.meshShader,
|
||||||
pixelShader = pass.pixelShader,
|
pixelShader = pass.pixelShader,
|
||||||
localPipeline = localPipeline,
|
localPipeline = localPipeline,
|
||||||
defines = pass.defines,
|
defines = pass.defines,
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ internal class PipelineSemantic
|
|||||||
internal class PassSemantic
|
internal class PassSemantic
|
||||||
{
|
{
|
||||||
public string name = string.Empty;
|
public string name = string.Empty;
|
||||||
public ShaderEntryPoint vertexShader;
|
public ShaderEntryPoint taskShader;
|
||||||
|
public ShaderEntryPoint meshShader;
|
||||||
public ShaderEntryPoint pixelShader;
|
public ShaderEntryPoint pixelShader;
|
||||||
public List<string>? defines;
|
public List<string>? defines;
|
||||||
public List<string>? includes;
|
public List<string>? includes;
|
||||||
|
|||||||
@@ -4,27 +4,27 @@
|
|||||||
public enum TokenType
|
public enum TokenType
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
|
|
||||||
// Literals
|
// Literals
|
||||||
Identifier = 1 << 0, // variable names, function names, etc.
|
Identifier = 1 << 0, // variable names, function names, etc.
|
||||||
Keyword = 1 << 1, // shader, properties, pipeline, pass, etc.
|
Keyword = 1 << 1, // shader, properties, pipeline, pass, etc.
|
||||||
Number = 1 << 2, // numeric literals (123, 45.67, .5)
|
Number = 1 << 2, // numeric literals (123, 45.67, .5)
|
||||||
StringLiteral = 1 << 3, // "ForwardVS.hlsl"
|
StringLiteral = 1 << 3, // "ForwardVS.hlsl"
|
||||||
|
|
||||||
// Operators and Punctuation
|
// Operators and Punctuation
|
||||||
Equals = 1 << 4, // =
|
Equals = 1 << 4, // =
|
||||||
Semicolon = 1 << 5, // ;
|
Semicolon = 1 << 5, // ;
|
||||||
Comma = 1 << 6, // ,
|
Comma = 1 << 6, // ,
|
||||||
|
|
||||||
// Delimiters
|
// Delimiters
|
||||||
LBrace = 1 << 7, // {
|
LBrace = 1 << 7, // {
|
||||||
RBrace = 1 << 8, // }
|
RBrace = 1 << 8, // }
|
||||||
LParen = 1 << 9, // (
|
LParen = 1 << 9, // (
|
||||||
RParen = 1 << 10, // )
|
RParen = 1 << 10, // )
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
EndOfFile = 1 << 11, // EOF
|
EndOfFile = 1 << 11, // EOF
|
||||||
|
|
||||||
// Future extensions (commented out for now)
|
// Future extensions (commented out for now)
|
||||||
// LBracket = 1 << 12, // [
|
// LBracket = 1 << 12, // [
|
||||||
// RBracket = 1 << 13, // ]
|
// RBracket = 1 << 13, // ]
|
||||||
@@ -137,9 +137,9 @@ internal static class TokenLexicon
|
|||||||
|
|
||||||
public static class KnownFunctions
|
public static class KnownFunctions
|
||||||
{
|
{
|
||||||
public const string VERTEX_SHADER = "vs";
|
public const string TASK_SHADER = "ts";
|
||||||
public const string PIXEL_SHADER = "ps";
|
|
||||||
public const string MESH_SHADER = "ms";
|
public const string MESH_SHADER = "ms";
|
||||||
|
public const string PIXEL_SHADER = "ps";
|
||||||
public const string COMPUTE_SHADER = "cs";
|
public const string COMPUTE_SHADER = "cs";
|
||||||
public const string DYNAMIC = "dynamic";
|
public const string DYNAMIC = "dynamic";
|
||||||
public const string STATIC = "static";
|
public const string STATIC = "static";
|
||||||
@@ -153,22 +153,22 @@ internal static class TokenLexicon
|
|||||||
public const string FLOAT2 = "float2";
|
public const string FLOAT2 = "float2";
|
||||||
public const string FLOAT3 = "float3";
|
public const string FLOAT3 = "float3";
|
||||||
public const string FLOAT4 = "float4";
|
public const string FLOAT4 = "float4";
|
||||||
|
|
||||||
public const string INT = "int";
|
public const string INT = "int";
|
||||||
public const string INT2 = "int2";
|
public const string INT2 = "int2";
|
||||||
public const string INT3 = "int3";
|
public const string INT3 = "int3";
|
||||||
public const string INT4 = "int4";
|
public const string INT4 = "int4";
|
||||||
|
|
||||||
public const string UINT = "uint";
|
public const string UINT = "uint";
|
||||||
public const string UINT2 = "uint2";
|
public const string UINT2 = "uint2";
|
||||||
public const string UINT3 = "uint3";
|
public const string UINT3 = "uint3";
|
||||||
public const string UINT4 = "uint4";
|
public const string UINT4 = "uint4";
|
||||||
|
|
||||||
public const string BOOL = "bool";
|
public const string BOOL = "bool";
|
||||||
public const string BOOL2 = "bool2";
|
public const string BOOL2 = "bool2";
|
||||||
public const string BOOL3 = "bool3";
|
public const string BOOL3 = "bool3";
|
||||||
public const string BOOL4 = "bool4";
|
public const string BOOL4 = "bool4";
|
||||||
|
|
||||||
// Texture types
|
// Texture types
|
||||||
public const string TEXTURE2D = "texture2d";
|
public const string TEXTURE2D = "texture2d";
|
||||||
public const string TEXTURE2D_ARRAY = "texture2d_array";
|
public const string TEXTURE2D_ARRAY = "texture2d_array";
|
||||||
@@ -201,7 +201,7 @@ internal static class TokenLexicon
|
|||||||
|
|
||||||
private static readonly HashSet<string> s_functions = new()
|
private static readonly HashSet<string> s_functions = new()
|
||||||
{
|
{
|
||||||
KnownFunctions.VERTEX_SHADER,
|
KnownFunctions.TASK_SHADER,
|
||||||
KnownFunctions.PIXEL_SHADER,
|
KnownFunctions.PIXEL_SHADER,
|
||||||
KnownFunctions.MESH_SHADER,
|
KnownFunctions.MESH_SHADER,
|
||||||
KnownFunctions.COMPUTE_SHADER,
|
KnownFunctions.COMPUTE_SHADER,
|
||||||
@@ -229,9 +229,9 @@ internal static class TokenLexicon
|
|||||||
};
|
};
|
||||||
|
|
||||||
public static bool IsKeyword(string lexeme) => s_keywords.Contains(lexeme);
|
public static bool IsKeyword(string lexeme) => s_keywords.Contains(lexeme);
|
||||||
|
|
||||||
public static bool IsFunction(string lexeme) => s_functions.Contains(lexeme);
|
public static bool IsFunction(string lexeme) => s_functions.Contains(lexeme);
|
||||||
|
|
||||||
public static bool IsType(string lexeme) => s_types.Contains(lexeme);
|
public static bool IsType(string lexeme) => s_types.Contains(lexeme);
|
||||||
|
|
||||||
public static bool IsTextureDefaultValue(string lexeme) => s_textureDefaultValues.Contains(lexeme);
|
public static bool IsTextureDefaultValue(string lexeme) => s_textureDefaultValues.Contains(lexeme);
|
||||||
|
|||||||
@@ -4,259 +4,261 @@ namespace Ghost.Zeux.MeshOptimizer;
|
|||||||
|
|
||||||
public static unsafe partial class Api
|
public static unsafe partial class Api
|
||||||
{
|
{
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
private const string _DLL_NAME = "meshoptimizer";
|
||||||
|
|
||||||
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_generateVertexRemap([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size);
|
public static extern nuint meshopt_generateVertexRemap([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_generateVertexRemapMulti([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("const struct meshopt_Stream *")] meshopt_Stream* streams, [NativeTypeName("size_t")] nuint stream_count);
|
public static extern nuint meshopt_generateVertexRemapMulti([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("const struct meshopt_Stream *")] meshopt_Stream* streams, [NativeTypeName("size_t")] nuint stream_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_generateVertexRemapCustom([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("int (*)(void *, unsigned int, unsigned int)")] delegate* unmanaged[Cdecl]<void*, uint, uint, int> callback, void* context);
|
public static extern nuint meshopt_generateVertexRemapCustom([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("int (*)(void *, unsigned int, unsigned int)")] delegate* unmanaged[Cdecl]<void*, uint, uint, int> callback, void* context);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_remapVertexBuffer(void* destination, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size, [NativeTypeName("const unsigned int *")] uint* remap);
|
public static extern void meshopt_remapVertexBuffer(void* destination, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size, [NativeTypeName("const unsigned int *")] uint* remap);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_remapIndexBuffer([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const unsigned int *")] uint* remap);
|
public static extern void meshopt_remapIndexBuffer([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const unsigned int *")] uint* remap);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_generateShadowIndexBuffer([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size, [NativeTypeName("size_t")] nuint vertex_stride);
|
public static extern void meshopt_generateShadowIndexBuffer([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size, [NativeTypeName("size_t")] nuint vertex_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_generateShadowIndexBufferMulti([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("const struct meshopt_Stream *")] meshopt_Stream* streams, [NativeTypeName("size_t")] nuint stream_count);
|
public static extern void meshopt_generateShadowIndexBufferMulti([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("const struct meshopt_Stream *")] meshopt_Stream* streams, [NativeTypeName("size_t")] nuint stream_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_generatePositionRemap([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
public static extern void meshopt_generatePositionRemap([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_generateAdjacencyIndexBuffer([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
public static extern void meshopt_generateAdjacencyIndexBuffer([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_generateTessellationIndexBuffer([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
public static extern void meshopt_generateTessellationIndexBuffer([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_generateProvokingIndexBuffer([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("unsigned int *")] uint* reorder, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
public static extern nuint meshopt_generateProvokingIndexBuffer([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("unsigned int *")] uint* reorder, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_optimizeVertexCache([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
public static extern void meshopt_optimizeVertexCache([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_optimizeVertexCacheStrip([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
public static extern void meshopt_optimizeVertexCacheStrip([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_optimizeVertexCacheFifo([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("unsigned int")] uint cache_size);
|
public static extern void meshopt_optimizeVertexCacheFifo([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("unsigned int")] uint cache_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_optimizeOverdraw([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, float threshold);
|
public static extern void meshopt_optimizeOverdraw([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, float threshold);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_optimizeVertexFetch(void* destination, [NativeTypeName("unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size);
|
public static extern nuint meshopt_optimizeVertexFetch(void* destination, [NativeTypeName("unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_optimizeVertexFetchRemap([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
public static extern nuint meshopt_optimizeVertexFetchRemap([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_encodeIndexBuffer([NativeTypeName("unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count);
|
public static extern nuint meshopt_encodeIndexBuffer([NativeTypeName("unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_encodeIndexBufferBound([NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
public static extern nuint meshopt_encodeIndexBufferBound([NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_encodeIndexVersion(int version);
|
public static extern void meshopt_encodeIndexVersion(int version);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern int meshopt_decodeIndexBuffer(void* destination, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint index_size, [NativeTypeName("const unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size);
|
public static extern int meshopt_decodeIndexBuffer(void* destination, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint index_size, [NativeTypeName("const unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern int meshopt_decodeIndexVersion([NativeTypeName("const unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size);
|
public static extern int meshopt_decodeIndexVersion([NativeTypeName("const unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_encodeIndexSequence([NativeTypeName("unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count);
|
public static extern nuint meshopt_encodeIndexSequence([NativeTypeName("unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_encodeIndexSequenceBound([NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
public static extern nuint meshopt_encodeIndexSequenceBound([NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern int meshopt_decodeIndexSequence(void* destination, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint index_size, [NativeTypeName("const unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size);
|
public static extern int meshopt_decodeIndexSequence(void* destination, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint index_size, [NativeTypeName("const unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_encodeVertexBuffer([NativeTypeName("unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size);
|
public static extern nuint meshopt_encodeVertexBuffer([NativeTypeName("unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_encodeVertexBufferBound([NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size);
|
public static extern nuint meshopt_encodeVertexBufferBound([NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_encodeVertexBufferLevel([NativeTypeName("unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size, int level, int version);
|
public static extern nuint meshopt_encodeVertexBufferLevel([NativeTypeName("unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size, [NativeTypeName("const void *")] void* vertices, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size, int level, int version);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_encodeVertexVersion(int version);
|
public static extern void meshopt_encodeVertexVersion(int version);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern int meshopt_decodeVertexBuffer(void* destination, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size, [NativeTypeName("const unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size);
|
public static extern int meshopt_decodeVertexBuffer(void* destination, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size, [NativeTypeName("const unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern int meshopt_decodeVertexVersion([NativeTypeName("const unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size);
|
public static extern int meshopt_decodeVertexVersion([NativeTypeName("const unsigned char *")] byte* buffer, [NativeTypeName("size_t")] nuint buffer_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_decodeFilterOct(void* buffer, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride);
|
public static extern void meshopt_decodeFilterOct(void* buffer, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_decodeFilterQuat(void* buffer, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride);
|
public static extern void meshopt_decodeFilterQuat(void* buffer, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_decodeFilterExp(void* buffer, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride);
|
public static extern void meshopt_decodeFilterExp(void* buffer, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_decodeFilterColor(void* buffer, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride);
|
public static extern void meshopt_decodeFilterColor(void* buffer, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_encodeFilterOct(void* destination, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride, int bits, [NativeTypeName("const float *")] float* data);
|
public static extern void meshopt_encodeFilterOct(void* destination, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride, int bits, [NativeTypeName("const float *")] float* data);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_encodeFilterQuat(void* destination, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride, int bits, [NativeTypeName("const float *")] float* data);
|
public static extern void meshopt_encodeFilterQuat(void* destination, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride, int bits, [NativeTypeName("const float *")] float* data);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_encodeFilterExp(void* destination, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride, int bits, [NativeTypeName("const float *")] float* data, [NativeTypeName("enum meshopt_EncodeExpMode")] meshopt_EncodeExpMode mode);
|
public static extern void meshopt_encodeFilterExp(void* destination, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride, int bits, [NativeTypeName("const float *")] float* data, [NativeTypeName("enum meshopt_EncodeExpMode")] meshopt_EncodeExpMode mode);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_encodeFilterColor(void* destination, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride, int bits, [NativeTypeName("const float *")] float* data);
|
public static extern void meshopt_encodeFilterColor(void* destination, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint stride, int bits, [NativeTypeName("const float *")] float* data);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_simplify([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint target_index_count, float target_error, [NativeTypeName("unsigned int")] uint options, float* result_error);
|
public static extern nuint meshopt_simplify([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint target_index_count, float target_error, [NativeTypeName("unsigned int")] uint options, float* result_error);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_simplifyWithAttributes([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("const float *")] float* vertex_attributes, [NativeTypeName("size_t")] nuint vertex_attributes_stride, [NativeTypeName("const float *")] float* attribute_weights, [NativeTypeName("size_t")] nuint attribute_count, [NativeTypeName("const unsigned char *")] byte* vertex_lock, [NativeTypeName("size_t")] nuint target_index_count, float target_error, [NativeTypeName("unsigned int")] uint options, float* result_error);
|
public static extern nuint meshopt_simplifyWithAttributes([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("const float *")] float* vertex_attributes, [NativeTypeName("size_t")] nuint vertex_attributes_stride, [NativeTypeName("const float *")] float* attribute_weights, [NativeTypeName("size_t")] nuint attribute_count, [NativeTypeName("const unsigned char *")] byte* vertex_lock, [NativeTypeName("size_t")] nuint target_index_count, float target_error, [NativeTypeName("unsigned int")] uint options, float* result_error);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_simplifyWithUpdate([NativeTypeName("unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, float* vertex_attributes, [NativeTypeName("size_t")] nuint vertex_attributes_stride, [NativeTypeName("const float *")] float* attribute_weights, [NativeTypeName("size_t")] nuint attribute_count, [NativeTypeName("const unsigned char *")] byte* vertex_lock, [NativeTypeName("size_t")] nuint target_index_count, float target_error, [NativeTypeName("unsigned int")] uint options, float* result_error);
|
public static extern nuint meshopt_simplifyWithUpdate([NativeTypeName("unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, float* vertex_attributes, [NativeTypeName("size_t")] nuint vertex_attributes_stride, [NativeTypeName("const float *")] float* attribute_weights, [NativeTypeName("size_t")] nuint attribute_count, [NativeTypeName("const unsigned char *")] byte* vertex_lock, [NativeTypeName("size_t")] nuint target_index_count, float target_error, [NativeTypeName("unsigned int")] uint options, float* result_error);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_simplifySloppy([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("const unsigned char *")] byte* vertex_lock, [NativeTypeName("size_t")] nuint target_index_count, float target_error, float* result_error);
|
public static extern nuint meshopt_simplifySloppy([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("const unsigned char *")] byte* vertex_lock, [NativeTypeName("size_t")] nuint target_index_count, float target_error, float* result_error);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_simplifyPrune([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, float target_error);
|
public static extern nuint meshopt_simplifyPrune([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, float target_error);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_simplifyPoints([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("const float *")] float* vertex_colors, [NativeTypeName("size_t")] nuint vertex_colors_stride, float color_weight, [NativeTypeName("size_t")] nuint target_vertex_count);
|
public static extern nuint meshopt_simplifyPoints([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("const float *")] float* vertex_colors, [NativeTypeName("size_t")] nuint vertex_colors_stride, float color_weight, [NativeTypeName("size_t")] nuint target_vertex_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern float meshopt_simplifyScale([NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
public static extern float meshopt_simplifyScale([NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_stripify([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("unsigned int")] uint restart_index);
|
public static extern nuint meshopt_stripify([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("unsigned int")] uint restart_index);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_stripifyBound([NativeTypeName("size_t")] nuint index_count);
|
public static extern nuint meshopt_stripifyBound([NativeTypeName("size_t")] nuint index_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_unstripify([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("unsigned int")] uint restart_index);
|
public static extern nuint meshopt_unstripify([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("unsigned int")] uint restart_index);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_unstripifyBound([NativeTypeName("size_t")] nuint index_count);
|
public static extern nuint meshopt_unstripifyBound([NativeTypeName("size_t")] nuint index_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("struct meshopt_VertexCacheStatistics")]
|
[return: NativeTypeName("struct meshopt_VertexCacheStatistics")]
|
||||||
public static extern meshopt_VertexCacheStatistics meshopt_analyzeVertexCache([NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("unsigned int")] uint cache_size, [NativeTypeName("unsigned int")] uint warp_size, [NativeTypeName("unsigned int")] uint primgroup_size);
|
public static extern meshopt_VertexCacheStatistics meshopt_analyzeVertexCache([NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("unsigned int")] uint cache_size, [NativeTypeName("unsigned int")] uint warp_size, [NativeTypeName("unsigned int")] uint primgroup_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("struct meshopt_VertexFetchStatistics")]
|
[return: NativeTypeName("struct meshopt_VertexFetchStatistics")]
|
||||||
public static extern meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch([NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size);
|
public static extern meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch([NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("struct meshopt_OverdrawStatistics")]
|
[return: NativeTypeName("struct meshopt_OverdrawStatistics")]
|
||||||
public static extern meshopt_OverdrawStatistics meshopt_analyzeOverdraw([NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
public static extern meshopt_OverdrawStatistics meshopt_analyzeOverdraw([NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("struct meshopt_CoverageStatistics")]
|
[return: NativeTypeName("struct meshopt_CoverageStatistics")]
|
||||||
public static extern meshopt_CoverageStatistics meshopt_analyzeCoverage([NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
public static extern meshopt_CoverageStatistics meshopt_analyzeCoverage([NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_buildMeshlets([NativeTypeName("struct meshopt_Meshlet *")] meshopt_Meshlet* meshlets, [NativeTypeName("unsigned int *")] uint* meshlet_vertices, [NativeTypeName("unsigned char *")] byte* meshlet_triangles, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint max_vertices, [NativeTypeName("size_t")] nuint max_triangles, float cone_weight);
|
public static extern nuint meshopt_buildMeshlets([NativeTypeName("struct meshopt_Meshlet *")] meshopt_Meshlet* meshlets, [NativeTypeName("unsigned int *")] uint* meshlet_vertices, [NativeTypeName("unsigned char *")] byte* meshlet_triangles, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint max_vertices, [NativeTypeName("size_t")] nuint max_triangles, float cone_weight);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_buildMeshletsScan([NativeTypeName("struct meshopt_Meshlet *")] meshopt_Meshlet* meshlets, [NativeTypeName("unsigned int *")] uint* meshlet_vertices, [NativeTypeName("unsigned char *")] byte* meshlet_triangles, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint max_vertices, [NativeTypeName("size_t")] nuint max_triangles);
|
public static extern nuint meshopt_buildMeshletsScan([NativeTypeName("struct meshopt_Meshlet *")] meshopt_Meshlet* meshlets, [NativeTypeName("unsigned int *")] uint* meshlet_vertices, [NativeTypeName("unsigned char *")] byte* meshlet_triangles, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint max_vertices, [NativeTypeName("size_t")] nuint max_triangles);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_buildMeshletsBound([NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint max_vertices, [NativeTypeName("size_t")] nuint max_triangles);
|
public static extern nuint meshopt_buildMeshletsBound([NativeTypeName("size_t")] nuint index_count, [NativeTypeName("size_t")] nuint max_vertices, [NativeTypeName("size_t")] nuint max_triangles);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_buildMeshletsFlex([NativeTypeName("struct meshopt_Meshlet *")] meshopt_Meshlet* meshlets, [NativeTypeName("unsigned int *")] uint* meshlet_vertices, [NativeTypeName("unsigned char *")] byte* meshlet_triangles, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint max_vertices, [NativeTypeName("size_t")] nuint min_triangles, [NativeTypeName("size_t")] nuint max_triangles, float cone_weight, float split_factor);
|
public static extern nuint meshopt_buildMeshletsFlex([NativeTypeName("struct meshopt_Meshlet *")] meshopt_Meshlet* meshlets, [NativeTypeName("unsigned int *")] uint* meshlet_vertices, [NativeTypeName("unsigned char *")] byte* meshlet_triangles, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint max_vertices, [NativeTypeName("size_t")] nuint min_triangles, [NativeTypeName("size_t")] nuint max_triangles, float cone_weight, float split_factor);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_buildMeshletsSpatial([NativeTypeName("struct meshopt_Meshlet *")] meshopt_Meshlet* meshlets, [NativeTypeName("unsigned int *")] uint* meshlet_vertices, [NativeTypeName("unsigned char *")] byte* meshlet_triangles, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint max_vertices, [NativeTypeName("size_t")] nuint min_triangles, [NativeTypeName("size_t")] nuint max_triangles, float fill_weight);
|
public static extern nuint meshopt_buildMeshletsSpatial([NativeTypeName("struct meshopt_Meshlet *")] meshopt_Meshlet* meshlets, [NativeTypeName("unsigned int *")] uint* meshlet_vertices, [NativeTypeName("unsigned char *")] byte* meshlet_triangles, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint max_vertices, [NativeTypeName("size_t")] nuint min_triangles, [NativeTypeName("size_t")] nuint max_triangles, float fill_weight);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_optimizeMeshlet([NativeTypeName("unsigned int *")] uint* meshlet_vertices, [NativeTypeName("unsigned char *")] byte* meshlet_triangles, [NativeTypeName("size_t")] nuint triangle_count, [NativeTypeName("size_t")] nuint vertex_count);
|
public static extern void meshopt_optimizeMeshlet([NativeTypeName("unsigned int *")] uint* meshlet_vertices, [NativeTypeName("unsigned char *")] byte* meshlet_triangles, [NativeTypeName("size_t")] nuint triangle_count, [NativeTypeName("size_t")] nuint vertex_count);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("struct meshopt_Bounds")]
|
[return: NativeTypeName("struct meshopt_Bounds")]
|
||||||
public static extern meshopt_Bounds meshopt_computeClusterBounds([NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
public static extern meshopt_Bounds meshopt_computeClusterBounds([NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("struct meshopt_Bounds")]
|
[return: NativeTypeName("struct meshopt_Bounds")]
|
||||||
public static extern meshopt_Bounds meshopt_computeMeshletBounds([NativeTypeName("const unsigned int *")] uint* meshlet_vertices, [NativeTypeName("const unsigned char *")] byte* meshlet_triangles, [NativeTypeName("size_t")] nuint triangle_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
public static extern meshopt_Bounds meshopt_computeMeshletBounds([NativeTypeName("const unsigned int *")] uint* meshlet_vertices, [NativeTypeName("const unsigned char *")] byte* meshlet_triangles, [NativeTypeName("size_t")] nuint triangle_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("struct meshopt_Bounds")]
|
[return: NativeTypeName("struct meshopt_Bounds")]
|
||||||
public static extern meshopt_Bounds meshopt_computeSphereBounds([NativeTypeName("const float *")] float* positions, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint positions_stride, [NativeTypeName("const float *")] float* radii, [NativeTypeName("size_t")] nuint radii_stride);
|
public static extern meshopt_Bounds meshopt_computeSphereBounds([NativeTypeName("const float *")] float* positions, [NativeTypeName("size_t")] nuint count, [NativeTypeName("size_t")] nuint positions_stride, [NativeTypeName("const float *")] float* radii, [NativeTypeName("size_t")] nuint radii_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("size_t")]
|
[return: NativeTypeName("size_t")]
|
||||||
public static extern nuint meshopt_partitionClusters([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* cluster_indices, [NativeTypeName("size_t")] nuint total_index_count, [NativeTypeName("const unsigned int *")] uint* cluster_index_counts, [NativeTypeName("size_t")] nuint cluster_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint target_partition_size);
|
public static extern nuint meshopt_partitionClusters([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* cluster_indices, [NativeTypeName("size_t")] nuint total_index_count, [NativeTypeName("const unsigned int *")] uint* cluster_index_counts, [NativeTypeName("size_t")] nuint cluster_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint target_partition_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_spatialSortRemap([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
public static extern void meshopt_spatialSortRemap([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_spatialSortTriangles([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
public static extern void meshopt_spatialSortTriangles([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const unsigned int *")] uint* indices, [NativeTypeName("size_t")] nuint index_count, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_spatialClusterPoints([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint cluster_size);
|
public static extern void meshopt_spatialClusterPoints([NativeTypeName("unsigned int *")] uint* destination, [NativeTypeName("const float *")] float* vertex_positions, [NativeTypeName("size_t")] nuint vertex_count, [NativeTypeName("size_t")] nuint vertex_positions_stride, [NativeTypeName("size_t")] nuint cluster_size);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
[return: NativeTypeName("unsigned short")]
|
[return: NativeTypeName("unsigned short")]
|
||||||
public static extern ushort meshopt_quantizeHalf(float v);
|
public static extern ushort meshopt_quantizeHalf(float v);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern float meshopt_quantizeFloat(float v, int N);
|
public static extern float meshopt_quantizeFloat(float v, int N);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern float meshopt_dequantizeHalf([NativeTypeName("unsigned short")] ushort h);
|
public static extern float meshopt_dequantizeHalf([NativeTypeName("unsigned short")] ushort h);
|
||||||
|
|
||||||
[DllImport("meshoptimizer_native", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
[DllImport(_DLL_NAME, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
|
||||||
public static extern void meshopt_setAllocator([NativeTypeName("void *(*)(size_t) __attribute__((cdecl))")] delegate* unmanaged[Cdecl]<nuint, void*> allocate, [NativeTypeName("void (*)(void *) __attribute__((cdecl))")] delegate* unmanaged[Cdecl]<void*, void> deallocate);
|
public static extern void meshopt_setAllocator([NativeTypeName("void *(*)(size_t) __attribute__((cdecl))")] delegate* unmanaged[Cdecl]<nuint, void*> allocate, [NativeTypeName("void (*)(void *) __attribute__((cdecl))")] delegate* unmanaged[Cdecl]<void*, void> deallocate);
|
||||||
|
|
||||||
public static int meshopt_quantizeUnorm(float v, int N)
|
public static int meshopt_quantizeUnorm(float v, int N)
|
||||||
{
|
{
|
||||||
float scale = (float)((1 << N) - 1);
|
var scale = (float)((1 << N) - 1);
|
||||||
|
|
||||||
v = (v >= 0) ? v : 0;
|
v = (v >= 0) ? v : 0;
|
||||||
v = (v <= 1) ? v : 1;
|
v = (v <= 1) ? v : 1;
|
||||||
@@ -265,8 +267,8 @@ public static unsafe partial class Api
|
|||||||
|
|
||||||
public static int meshopt_quantizeSnorm(float v, int N)
|
public static int meshopt_quantizeSnorm(float v, int N)
|
||||||
{
|
{
|
||||||
float scale = (float)((1 << (N - 1)) - 1);
|
var scale = (float)((1 << (N - 1)) - 1);
|
||||||
float round = (v >= 0 ? 0.5f : -0.5f);
|
var round = (v >= 0 ? 0.5f : -0.5f);
|
||||||
|
|
||||||
v = (v >= -1) ? v : -1;
|
v = (v >= -1) ? v : -1;
|
||||||
v = (v <= +1) ? v : +1;
|
v = (v <= +1) ? v : +1;
|
||||||
@@ -278,4 +280,4 @@ public static unsafe partial class Api
|
|||||||
{
|
{
|
||||||
return meshopt_encodeVertexBufferLevel(buffer, buffer_size, vertices, vertex_count, vertex_size, level, unchecked(-1));
|
return meshopt_encodeVertexBufferLevel(buffer, buffer_size, vertices, vertex_count, vertex_size, level, unchecked(-1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
namespace Ghost.Zeux.MeshOptimizer;
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
/// <summary>Defines the type of a member as it was used in the native signature.</summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = true)]
|
|
||||||
[Conditional("DEBUG")]
|
|
||||||
internal sealed partial class NativeTypeNameAttribute : Attribute
|
|
||||||
{
|
|
||||||
private readonly string _name;
|
|
||||||
|
|
||||||
/// <summary>Initializes a new instance of the <see cref="NativeTypeNameAttribute" /> class.</summary>
|
|
||||||
/// <param name="name">The name of the type that was used in the native signature.</param>
|
|
||||||
public NativeTypeNameAttribute(string name)
|
|
||||||
{
|
|
||||||
_name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Gets the name of the type that was used in the native signature.</summary>
|
|
||||||
public string Name => _name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Defines the annotation found in a native declaration.</summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
|
|
||||||
[Conditional("DEBUG")]
|
|
||||||
internal sealed partial class NativeAnnotationAttribute : Attribute
|
|
||||||
{
|
|
||||||
private readonly string _annotation;
|
|
||||||
|
|
||||||
/// <summary>Initializes a new instance of the <see cref="NativeAnnotationAttribute" /> class.</summary>
|
|
||||||
/// <param name="annotation">The annotation that was used in the native declaration.</param>
|
|
||||||
public NativeAnnotationAttribute(string annotation)
|
|
||||||
{
|
|
||||||
_annotation = annotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Gets the annotation that was used in the native declaration.</summary>
|
|
||||||
public string Annotation => _annotation;
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="runtime\win-x64\native\meshoptimizer_native.dll">
|
<Content Include="runtime\win-x64\native\meshoptimizer.dll">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,261 +0,0 @@
|
|||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ghost.Zeux.MeshOptimizer;
|
|
||||||
|
|
||||||
public unsafe partial struct meshopt_Stream
|
|
||||||
{
|
|
||||||
[NativeTypeName("const void *")]
|
|
||||||
public void* data;
|
|
||||||
|
|
||||||
[NativeTypeName("size_t")]
|
|
||||||
public nuint size;
|
|
||||||
|
|
||||||
[NativeTypeName("size_t")]
|
|
||||||
public nuint stride;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum meshopt_EncodeExpMode
|
|
||||||
{
|
|
||||||
meshopt_EncodeExpSeparate,
|
|
||||||
meshopt_EncodeExpSharedVector,
|
|
||||||
meshopt_EncodeExpSharedComponent,
|
|
||||||
meshopt_EncodeExpClamped,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum meshopt_SimplifyOptions
|
|
||||||
{
|
|
||||||
meshopt_SimplifyLockBorder = 1 << 0,
|
|
||||||
meshopt_SimplifySparse = 1 << 1,
|
|
||||||
meshopt_SimplifyErrorAbsolute = 1 << 2,
|
|
||||||
meshopt_SimplifyPrune = 1 << 3,
|
|
||||||
meshopt_SimplifyRegularize = 1 << 4,
|
|
||||||
meshopt_SimplifyPermissive = 1 << 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum meshopt_SimplifyVertexFlags
|
|
||||||
{
|
|
||||||
meshopt_SimplifyVertex_Lock = 1 << 0,
|
|
||||||
meshopt_SimplifyVertex_Protect = 1 << 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial struct meshopt_VertexCacheStatistics
|
|
||||||
{
|
|
||||||
[NativeTypeName("unsigned int")]
|
|
||||||
public uint vertices_transformed;
|
|
||||||
|
|
||||||
[NativeTypeName("unsigned int")]
|
|
||||||
public uint warps_executed;
|
|
||||||
|
|
||||||
public float acmr;
|
|
||||||
|
|
||||||
public float atvr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial struct meshopt_VertexFetchStatistics
|
|
||||||
{
|
|
||||||
[NativeTypeName("unsigned int")]
|
|
||||||
public uint bytes_fetched;
|
|
||||||
|
|
||||||
public float overfetch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial struct meshopt_OverdrawStatistics
|
|
||||||
{
|
|
||||||
[NativeTypeName("unsigned int")]
|
|
||||||
public uint pixels_covered;
|
|
||||||
|
|
||||||
[NativeTypeName("unsigned int")]
|
|
||||||
public uint pixels_shaded;
|
|
||||||
|
|
||||||
public float overdraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial struct meshopt_CoverageStatistics
|
|
||||||
{
|
|
||||||
[NativeTypeName("float[3]")]
|
|
||||||
public _coverage_e__FixedBuffer coverage;
|
|
||||||
|
|
||||||
public float extent;
|
|
||||||
|
|
||||||
[InlineArray(3)]
|
|
||||||
public partial struct _coverage_e__FixedBuffer
|
|
||||||
{
|
|
||||||
public float e0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial struct meshopt_Meshlet
|
|
||||||
{
|
|
||||||
[NativeTypeName("unsigned int")]
|
|
||||||
public uint vertex_offset;
|
|
||||||
|
|
||||||
[NativeTypeName("unsigned int")]
|
|
||||||
public uint triangle_offset;
|
|
||||||
|
|
||||||
[NativeTypeName("unsigned int")]
|
|
||||||
public uint vertex_count;
|
|
||||||
|
|
||||||
[NativeTypeName("unsigned int")]
|
|
||||||
public uint triangle_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public partial struct meshopt_Bounds
|
|
||||||
{
|
|
||||||
[NativeTypeName("float[3]")]
|
|
||||||
public _center_e__FixedBuffer center;
|
|
||||||
|
|
||||||
public float radius;
|
|
||||||
|
|
||||||
[NativeTypeName("float[3]")]
|
|
||||||
public _cone_apex_e__FixedBuffer cone_apex;
|
|
||||||
|
|
||||||
[NativeTypeName("float[3]")]
|
|
||||||
public _cone_axis_e__FixedBuffer cone_axis;
|
|
||||||
|
|
||||||
public float cone_cutoff;
|
|
||||||
|
|
||||||
[NativeTypeName("signed char[3]")]
|
|
||||||
public _cone_axis_s8_e__FixedBuffer cone_axis_s8;
|
|
||||||
|
|
||||||
[NativeTypeName("signed char")]
|
|
||||||
public sbyte cone_cutoff_s8;
|
|
||||||
|
|
||||||
[InlineArray(3)]
|
|
||||||
public partial struct _center_e__FixedBuffer
|
|
||||||
{
|
|
||||||
public float e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[InlineArray(3)]
|
|
||||||
public partial struct _cone_apex_e__FixedBuffer
|
|
||||||
{
|
|
||||||
public float e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[InlineArray(3)]
|
|
||||||
public partial struct _cone_axis_e__FixedBuffer
|
|
||||||
{
|
|
||||||
public float e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[InlineArray(3)]
|
|
||||||
public partial struct _cone_axis_s8_e__FixedBuffer
|
|
||||||
{
|
|
||||||
public sbyte e0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe partial struct meshopt_Allocator
|
|
||||||
{
|
|
||||||
private static readonly Storage s_storage;
|
|
||||||
|
|
||||||
[NativeTypeName("void *[24]")]
|
|
||||||
private _blocks_e__FixedBuffer _blocks;
|
|
||||||
|
|
||||||
[NativeTypeName("size_t")]
|
|
||||||
private nuint _count;
|
|
||||||
|
|
||||||
static meshopt_Allocator()
|
|
||||||
{
|
|
||||||
s_storage = new Storage
|
|
||||||
{
|
|
||||||
// Use .NET's unmanaged memory functions.
|
|
||||||
allocate = &NativeMemory_Alloc,
|
|
||||||
deallocate = &NativeMemory_Free,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public meshopt_Allocator()
|
|
||||||
{
|
|
||||||
_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
|
|
||||||
private static void* NativeMemory_Alloc(nuint size)
|
|
||||||
{
|
|
||||||
return NativeMemory.Alloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
|
|
||||||
private static void NativeMemory_Free(void* ptr)
|
|
||||||
{
|
|
||||||
NativeMemory.Free(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T* allocate<T>(nuint size) where T : unmanaged
|
|
||||||
{
|
|
||||||
Debug.Assert(_count < 24, "Allocator block limit reached");
|
|
||||||
|
|
||||||
// Calculate total bytes needed
|
|
||||||
var bytes = size * (nuint)sizeof(T);
|
|
||||||
var result = (T*)s_storage.allocate(bytes);
|
|
||||||
|
|
||||||
_blocks[_count++] = result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deallocate(void* ptr)
|
|
||||||
{
|
|
||||||
Debug.Assert(_count > 0 && _blocks[_count - 1] == ptr, "Deallocation is not in LIFO order");
|
|
||||||
s_storage.deallocate(ptr);
|
|
||||||
_count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe partial struct Storage
|
|
||||||
{
|
|
||||||
[NativeTypeName("void *(*)(size_t) __attribute__((cdecl))")]
|
|
||||||
public delegate* unmanaged[Cdecl]<nuint, void*> allocate;
|
|
||||||
|
|
||||||
[NativeTypeName("void (*)(void *) __attribute__((cdecl))")]
|
|
||||||
public delegate* unmanaged[Cdecl]<void*, void> deallocate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
for (var i = _count; i > 0; --i)
|
|
||||||
{
|
|
||||||
s_storage.deallocate(_blocks[i - 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private unsafe partial struct _blocks_e__FixedBuffer
|
|
||||||
{
|
|
||||||
private void* e0;
|
|
||||||
private void* e1;
|
|
||||||
private void* e2;
|
|
||||||
private void* e3;
|
|
||||||
private void* e4;
|
|
||||||
private void* e5;
|
|
||||||
private void* e6;
|
|
||||||
private void* e7;
|
|
||||||
private void* e8;
|
|
||||||
private void* e9;
|
|
||||||
private void* e10;
|
|
||||||
private void* e11;
|
|
||||||
private void* e12;
|
|
||||||
private void* e13;
|
|
||||||
private void* e14;
|
|
||||||
private void* e15;
|
|
||||||
private void* e16;
|
|
||||||
private void* e17;
|
|
||||||
private void* e18;
|
|
||||||
private void* e19;
|
|
||||||
private void* e20;
|
|
||||||
private void* e21;
|
|
||||||
private void* e22;
|
|
||||||
private void* e23;
|
|
||||||
|
|
||||||
public ref void* this[nuint index]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
fixed (void** pThis = &e0)
|
|
||||||
{
|
|
||||||
return ref pThis[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
22
Ghost.Zeux.MeshOptimizer/NativeAnnotationAttribute.cs
Normal file
22
Ghost.Zeux.MeshOptimizer/NativeAnnotationAttribute.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
/// <summary>Defines the annotation found in a native declaration.</summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
|
||||||
|
[Conditional("DEBUG")]
|
||||||
|
internal sealed partial class NativeAnnotationAttribute : Attribute
|
||||||
|
{
|
||||||
|
private readonly string _annotation;
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="NativeAnnotationAttribute" /> class.</summary>
|
||||||
|
/// <param name="annotation">The annotation that was used in the native declaration.</param>
|
||||||
|
public NativeAnnotationAttribute(string annotation)
|
||||||
|
{
|
||||||
|
_annotation = annotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Gets the annotation that was used in the native declaration.</summary>
|
||||||
|
public string Annotation => _annotation;
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Ghost.Zeux.MeshOptimizer/NativeTypeNameAttribute.cs
Normal file
22
Ghost.Zeux.MeshOptimizer/NativeTypeNameAttribute.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
/// <summary>Defines the type of a member as it was used in the native signature.</summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = true)]
|
||||||
|
[Conditional("DEBUG")]
|
||||||
|
internal sealed partial class NativeTypeNameAttribute : Attribute
|
||||||
|
{
|
||||||
|
private readonly string _name;
|
||||||
|
|
||||||
|
/// <summary>Initializes a new instance of the <see cref="NativeTypeNameAttribute" /> class.</summary>
|
||||||
|
/// <param name="name">The name of the type that was used in the native signature.</param>
|
||||||
|
public NativeTypeNameAttribute(string name)
|
||||||
|
{
|
||||||
|
_name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Gets the name of the type that was used in the native signature.</summary>
|
||||||
|
public string Name => _name;
|
||||||
|
}
|
||||||
|
}
|
||||||
119
Ghost.Zeux.MeshOptimizer/meshopt_Allocator.cs
Normal file
119
Ghost.Zeux.MeshOptimizer/meshopt_Allocator.cs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
public unsafe partial struct meshopt_Allocator
|
||||||
|
{
|
||||||
|
private static readonly Storage s_storage;
|
||||||
|
|
||||||
|
[NativeTypeName("void *[24]")]
|
||||||
|
private _blocks_e__FixedBuffer _blocks;
|
||||||
|
|
||||||
|
[NativeTypeName("size_t")]
|
||||||
|
private nuint _count;
|
||||||
|
|
||||||
|
static meshopt_Allocator()
|
||||||
|
{
|
||||||
|
s_storage = new Storage
|
||||||
|
{
|
||||||
|
// Use .NET's unmanaged memory functions.
|
||||||
|
allocate = &NativeMemory_Alloc,
|
||||||
|
deallocate = &NativeMemory_Free,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public meshopt_Allocator()
|
||||||
|
{
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
|
||||||
|
private static void* NativeMemory_Alloc(nuint size)
|
||||||
|
{
|
||||||
|
return NativeMemory.Alloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
|
||||||
|
private static void NativeMemory_Free(void* ptr)
|
||||||
|
{
|
||||||
|
NativeMemory.Free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T* allocate<T>(nuint size) where T : unmanaged
|
||||||
|
{
|
||||||
|
Debug.Assert(_count < 24, "Allocator block limit reached");
|
||||||
|
|
||||||
|
// Calculate total bytes needed
|
||||||
|
var bytes = size * (nuint)sizeof(T);
|
||||||
|
var result = (T*)s_storage.allocate(bytes);
|
||||||
|
|
||||||
|
_blocks[_count++] = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deallocate(void* ptr)
|
||||||
|
{
|
||||||
|
Debug.Assert(_count > 0 && _blocks[_count - 1] == ptr, "Deallocation is not in LIFO order");
|
||||||
|
s_storage.deallocate(ptr);
|
||||||
|
_count--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe partial struct Storage
|
||||||
|
{
|
||||||
|
[NativeTypeName("void *(*)(size_t) __attribute__((cdecl))")]
|
||||||
|
public delegate* unmanaged[Cdecl]<nuint, void*> allocate;
|
||||||
|
|
||||||
|
[NativeTypeName("void (*)(void *) __attribute__((cdecl))")]
|
||||||
|
public delegate* unmanaged[Cdecl]<void*, void> deallocate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
for (var i = _count; i > 0; --i)
|
||||||
|
{
|
||||||
|
s_storage.deallocate(_blocks[i - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private unsafe partial struct _blocks_e__FixedBuffer
|
||||||
|
{
|
||||||
|
private void* e0;
|
||||||
|
private void* e1;
|
||||||
|
private void* e2;
|
||||||
|
private void* e3;
|
||||||
|
private void* e4;
|
||||||
|
private void* e5;
|
||||||
|
private void* e6;
|
||||||
|
private void* e7;
|
||||||
|
private void* e8;
|
||||||
|
private void* e9;
|
||||||
|
private void* e10;
|
||||||
|
private void* e11;
|
||||||
|
private void* e12;
|
||||||
|
private void* e13;
|
||||||
|
private void* e14;
|
||||||
|
private void* e15;
|
||||||
|
private void* e16;
|
||||||
|
private void* e17;
|
||||||
|
private void* e18;
|
||||||
|
private void* e19;
|
||||||
|
private void* e20;
|
||||||
|
private void* e21;
|
||||||
|
private void* e22;
|
||||||
|
private void* e23;
|
||||||
|
|
||||||
|
public ref void* this[nuint index]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
fixed (void** pThis = &e0)
|
||||||
|
{
|
||||||
|
return ref pThis[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
Ghost.Zeux.MeshOptimizer/meshopt_Bounds.cs
Normal file
50
Ghost.Zeux.MeshOptimizer/meshopt_Bounds.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
public partial struct meshopt_Bounds
|
||||||
|
{
|
||||||
|
[NativeTypeName("float[3]")]
|
||||||
|
public _center_e__FixedBuffer center;
|
||||||
|
|
||||||
|
public float radius;
|
||||||
|
|
||||||
|
[NativeTypeName("float[3]")]
|
||||||
|
public _cone_apex_e__FixedBuffer cone_apex;
|
||||||
|
|
||||||
|
[NativeTypeName("float[3]")]
|
||||||
|
public _cone_axis_e__FixedBuffer cone_axis;
|
||||||
|
|
||||||
|
public float cone_cutoff;
|
||||||
|
|
||||||
|
[NativeTypeName("signed char[3]")]
|
||||||
|
public _cone_axis_s8_e__FixedBuffer cone_axis_s8;
|
||||||
|
|
||||||
|
[NativeTypeName("signed char")]
|
||||||
|
public sbyte cone_cutoff_s8;
|
||||||
|
|
||||||
|
[InlineArray(3)]
|
||||||
|
public partial struct _center_e__FixedBuffer
|
||||||
|
{
|
||||||
|
public float e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[InlineArray(3)]
|
||||||
|
public partial struct _cone_apex_e__FixedBuffer
|
||||||
|
{
|
||||||
|
public float e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[InlineArray(3)]
|
||||||
|
public partial struct _cone_axis_e__FixedBuffer
|
||||||
|
{
|
||||||
|
public float e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[InlineArray(3)]
|
||||||
|
public partial struct _cone_axis_s8_e__FixedBuffer
|
||||||
|
{
|
||||||
|
public sbyte e0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Ghost.Zeux.MeshOptimizer/meshopt_CoverageStatistics.cs
Normal file
18
Ghost.Zeux.MeshOptimizer/meshopt_CoverageStatistics.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
public partial struct meshopt_CoverageStatistics
|
||||||
|
{
|
||||||
|
[NativeTypeName("float[3]")]
|
||||||
|
public _coverage_e__FixedBuffer coverage;
|
||||||
|
|
||||||
|
public float extent;
|
||||||
|
|
||||||
|
[InlineArray(3)]
|
||||||
|
public partial struct _coverage_e__FixedBuffer
|
||||||
|
{
|
||||||
|
public float e0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
Ghost.Zeux.MeshOptimizer/meshopt_EncodeExpMode.cs
Normal file
10
Ghost.Zeux.MeshOptimizer/meshopt_EncodeExpMode.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
public enum meshopt_EncodeExpMode
|
||||||
|
{
|
||||||
|
meshopt_EncodeExpSeparate,
|
||||||
|
meshopt_EncodeExpSharedVector,
|
||||||
|
meshopt_EncodeExpSharedComponent,
|
||||||
|
meshopt_EncodeExpClamped,
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Ghost.Zeux.MeshOptimizer/meshopt_Meshlet.cs
Normal file
17
Ghost.Zeux.MeshOptimizer/meshopt_Meshlet.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
public partial struct meshopt_Meshlet
|
||||||
|
{
|
||||||
|
[NativeTypeName("unsigned int")]
|
||||||
|
public uint vertex_offset;
|
||||||
|
|
||||||
|
[NativeTypeName("unsigned int")]
|
||||||
|
public uint triangle_offset;
|
||||||
|
|
||||||
|
[NativeTypeName("unsigned int")]
|
||||||
|
public uint vertex_count;
|
||||||
|
|
||||||
|
[NativeTypeName("unsigned int")]
|
||||||
|
public uint triangle_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Ghost.Zeux.MeshOptimizer/meshopt_OverdrawStatistics.cs
Normal file
13
Ghost.Zeux.MeshOptimizer/meshopt_OverdrawStatistics.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
public partial struct meshopt_OverdrawStatistics
|
||||||
|
{
|
||||||
|
[NativeTypeName("unsigned int")]
|
||||||
|
public uint pixels_covered;
|
||||||
|
|
||||||
|
[NativeTypeName("unsigned int")]
|
||||||
|
public uint pixels_shaded;
|
||||||
|
|
||||||
|
public float overdraw;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
Ghost.Zeux.MeshOptimizer/meshopt_SimplifyOptions.cs
Normal file
12
Ghost.Zeux.MeshOptimizer/meshopt_SimplifyOptions.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
public enum meshopt_SimplifyOptions
|
||||||
|
{
|
||||||
|
meshopt_SimplifyLockBorder = 1 << 0,
|
||||||
|
meshopt_SimplifySparse = 1 << 1,
|
||||||
|
meshopt_SimplifyErrorAbsolute = 1 << 2,
|
||||||
|
meshopt_SimplifyPrune = 1 << 3,
|
||||||
|
meshopt_SimplifyRegularize = 1 << 4,
|
||||||
|
meshopt_SimplifyPermissive = 1 << 5,
|
||||||
|
}
|
||||||
|
}
|
||||||
8
Ghost.Zeux.MeshOptimizer/meshopt_SimplifyVertexFlags.cs
Normal file
8
Ghost.Zeux.MeshOptimizer/meshopt_SimplifyVertexFlags.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
public enum meshopt_SimplifyVertexFlags
|
||||||
|
{
|
||||||
|
meshopt_SimplifyVertex_Lock = 1 << 0,
|
||||||
|
meshopt_SimplifyVertex_Protect = 1 << 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
14
Ghost.Zeux.MeshOptimizer/meshopt_Stream.cs
Normal file
14
Ghost.Zeux.MeshOptimizer/meshopt_Stream.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
public unsafe partial struct meshopt_Stream
|
||||||
|
{
|
||||||
|
[NativeTypeName("const void *")]
|
||||||
|
public void* data;
|
||||||
|
|
||||||
|
[NativeTypeName("size_t")]
|
||||||
|
public nuint size;
|
||||||
|
|
||||||
|
[NativeTypeName("size_t")]
|
||||||
|
public nuint stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Ghost.Zeux.MeshOptimizer/meshopt_VertexCacheStatistics.cs
Normal file
15
Ghost.Zeux.MeshOptimizer/meshopt_VertexCacheStatistics.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
public partial struct meshopt_VertexCacheStatistics
|
||||||
|
{
|
||||||
|
[NativeTypeName("unsigned int")]
|
||||||
|
public uint vertices_transformed;
|
||||||
|
|
||||||
|
[NativeTypeName("unsigned int")]
|
||||||
|
public uint warps_executed;
|
||||||
|
|
||||||
|
public float acmr;
|
||||||
|
|
||||||
|
public float atvr;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
Ghost.Zeux.MeshOptimizer/meshopt_VertexFetchStatistics.cs
Normal file
10
Ghost.Zeux.MeshOptimizer/meshopt_VertexFetchStatistics.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Ghost.Zeux.MeshOptimizer
|
||||||
|
{
|
||||||
|
public partial struct meshopt_VertexFetchStatistics
|
||||||
|
{
|
||||||
|
[NativeTypeName("unsigned int")]
|
||||||
|
public uint bytes_fetched;
|
||||||
|
|
||||||
|
public float overfetch;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user