Refactor error handling: use Error enum, update APIs

Replaces ErrorStatus with Error across all systems for consistency.
Renames ResourceBarrierData fields to camelCase.
Adds BindlessAccess enum and updates GetBindlessIndex API.
Updates method signatures, result types, and error checks.
Modernizes HLSL mesh shader syntax and fixes naming.
Improves code style and updates comments for clarity.
This commit is contained in:
2026-01-25 16:34:28 +09:00
parent e11a9ebb52
commit 364fbf9208
28 changed files with 282 additions and 252 deletions

View File

@@ -28,7 +28,7 @@ public readonly struct Result
return new Result(false, message);
}
public static Result Failure(ErrorStatus status)
public static Result Failure(Error status)
{
return new Result(false, status.ToString());
}
@@ -43,7 +43,7 @@ public readonly struct Result
return Result<T>.Failure(message);
}
public static Result<T> Failure<T>(ErrorStatus status)
public static Result<T> Failure<T>(Error status)
{
return Result<T>.Failure(status.ToString());
}
@@ -117,7 +117,7 @@ public readonly struct Result<T>
public static implicit operator bool(Result<T> result) => result.IsSuccess;
}
public enum ErrorStatus : byte
public enum Error : byte
{
None,
NotFound,
@@ -249,9 +249,9 @@ public readonly ref struct RefResult<T, E>
public static class ResultExtensions
{
public static void ThrowIfFailed(this ErrorStatus result, [CallerArgumentExpression(nameof(result))] string? op = null)
public static void ThrowIfFailed(this Error result, [CallerArgumentExpression(nameof(result))] string? op = null)
{
if (result != ErrorStatus.None)
if (result != Error.None)
{
throw new InvalidOperationException($"{op} failed: {result}");
}

View File

@@ -31,16 +31,16 @@ public static partial class AssetDatabase
s_watcher.Renamed += OnAssetRenamed;
}
private static Result<string, ErrorStatus> GetMetaFilePath(string assetPath)
private static Result<string, Error> GetMetaFilePath(string assetPath)
{
if (Directory.Exists(assetPath))
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
if (Path.GetExtension(assetPath).Equals(".meta", StringComparison.OrdinalIgnoreCase))
{
return ErrorStatus.InvalidState;
return Error.InvalidState;
}
return assetPath + ".meta";

View File

@@ -392,10 +392,10 @@ internal unsafe struct Archetype : IDisposable
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly ErrorStatus SetComponentData(int chunkIndex, int rowIndex, Identifier<IComponent> componentID, void* pComponent)
public readonly Error SetComponentData(int chunkIndex, int rowIndex, Identifier<IComponent> componentID, void* pComponent)
{
var r = GetLayout(componentID);
if (r.Error != ErrorStatus.None)
if (r.Error != Error.None)
{
return r.Error;
}
@@ -412,14 +412,14 @@ internal unsafe struct Archetype : IDisposable
var world = World.GetWorldUncheck(_worldID);
MarkChanged(chunkIndex, componentID, world.Version);
return ErrorStatus.None;
return Error.None;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly void* GetComponentData(int chunkIndex, int rowIndex, Identifier<IComponent> componentID)
{
var r = GetLayout(componentID);
if (r.Error != ErrorStatus.None)
if (r.Error != Error.None)
{
return null;
}
@@ -439,24 +439,24 @@ internal unsafe struct Archetype : IDisposable
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Result<ComponentMemoryLayout, ErrorStatus> GetLayout(int componentID)
public readonly Result<ComponentMemoryLayout, Error> GetLayout(int componentID)
{
if (componentID >= _componentIDToLayoutIndex.Count)
{
return ErrorStatus.InvalidArgument;
return Error.InvalidArgument;
}
var layoutIndex = _componentIDToLayoutIndex[componentID];
if (layoutIndex == -1)
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
return _layouts[layoutIndex];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly ErrorStatus MarkChanged(int chunkIndex, int componentTypeId, int globalVersion)
public readonly Error MarkChanged(int chunkIndex, int componentTypeId, int globalVersion)
{
var layoutResult = GetLayout(componentTypeId);
if (layoutResult.IsFailure)
@@ -467,14 +467,14 @@ internal unsafe struct Archetype : IDisposable
ref var chunk = ref _chunks[chunkIndex];
chunk.GetVersionUnsafePtr()[layoutResult.Value.versionIndex] = globalVersion;
return ErrorStatus.None;
return Error.None;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Result<int, ErrorStatus> GetVersion(int chunkIndex, int componentTypeId)
public readonly Result<int, Error> GetVersion(int chunkIndex, int componentTypeId)
{
var layoutResult = GetLayout(componentTypeId);
if (layoutResult.Error != ErrorStatus.None)
if (layoutResult.Error != Error.None)
{
return layoutResult.Error;
}
@@ -483,11 +483,11 @@ internal unsafe struct Archetype : IDisposable
return chunk.GetVersionUnsafePtr()[layoutResult.Value.versionIndex];
}
public ErrorStatus RemoveEntity(int chunkIndex, int rowIndex)
public Error RemoveEntity(int chunkIndex, int rowIndex)
{
if (chunkIndex < 0 || chunkIndex >= _chunks.Count)
{
return ErrorStatus.InvalidArgument;
return Error.InvalidArgument;
}
var world = World.GetWorldUncheck(_worldID);
@@ -502,7 +502,7 @@ internal unsafe struct Archetype : IDisposable
var pRowEntity = chunkBase + _entityIdsOffset + (sizeof(Entity) * rowIndex);
var result = world.EntityManager.UpdateEntityLocation(*(Entity*)pLastEntity, _id, chunkIndex, rowIndex);
if (result != ErrorStatus.None)
if (result != Error.None)
{
return result;
}
@@ -524,19 +524,19 @@ internal unsafe struct Archetype : IDisposable
chunk._count--;
chunk._structuralVersion = world.Version;
return ErrorStatus.None;
return Error.None;
}
public ErrorStatus RemoveEntities(int chunkIndex, ReadOnlySpan<int> sortedIndicesToRemove)
public Error RemoveEntities(int chunkIndex, ReadOnlySpan<int> sortedIndicesToRemove)
{
if (chunkIndex < 0 || chunkIndex >= _chunks.Count)
{
return ErrorStatus.InvalidArgument;
return Error.InvalidArgument;
}
if (sortedIndicesToRemove.Length == 0)
{
return ErrorStatus.None;
return Error.None;
}
ref var chunk = ref _chunks[chunkIndex];
@@ -603,7 +603,7 @@ internal unsafe struct Archetype : IDisposable
// 1. Update the Map (Critical Step)
// We tell the world: "The entity that WAS at 'candidateIndex' is now at 'holeIndex'"
var result = world.EntityManager.UpdateEntityLocation(*(Entity*)pFillerEntity, _id, chunkIndex, holeIndex);
if (result != ErrorStatus.None)
if (result != Error.None)
{
return result;
}
@@ -628,7 +628,7 @@ internal unsafe struct Archetype : IDisposable
chunk._count = newCount;
chunk._structuralVersion = world.Version;
return ErrorStatus.None;
return Error.None;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -60,29 +60,29 @@ public unsafe partial class EntityManager : IDisposable
Dispose();
}
internal ErrorStatus UpdateEntityLocation(Entity entity, Identifier<Archetype> newArchetypeID, int newChunkIndex, int newRowIndex)
internal Error UpdateEntityLocation(Entity entity, Identifier<Archetype> newArchetypeID, int newChunkIndex, int newRowIndex)
{
ref var location = ref _entityLocations.GetElementReferenceAt(entity.ID, entity.Generation, out var exist);
if (!exist)
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
location.archetypeID = newArchetypeID;
location.chunkIndex = newChunkIndex;
location.rowIndex = newRowIndex;
return ErrorStatus.None;
return Error.None;
}
internal Result<EntityLocation, ErrorStatus> GetEntityLocation(Entity entity)
internal Result<EntityLocation, Error> GetEntityLocation(Entity entity)
{
if (_entityLocations.TryGetElementAt(entity.ID, entity.Generation, out var location))
{
return location;
}
return ErrorStatus.NotFound;
return Error.NotFound;
}
/// <summary>
@@ -240,28 +240,28 @@ public unsafe partial class EntityManager : IDisposable
/// Destroy the specified entity.
/// </summary>
/// <returns>The result status of the operation.</returns>
public ErrorStatus DestroyEntity(Entity entity)
public Error DestroyEntity(Entity entity)
{
if (!_entityLocations.TryGetElementAt(entity.ID, entity.Generation, out var location))
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
ref var archetype = ref _world.ComponentManager.GetArchetypeReference(location.archetypeID);
DestoryManagedEntityIfExists(in archetype, location);
var r = archetype.RemoveEntity(location.chunkIndex, location.rowIndex);
if (r != ErrorStatus.None)
if (r != Error.None)
{
return r;
}
if (!_entityLocations.Remove(entity.ID, entity.Generation))
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
return ErrorStatus.None;
return Error.None;
}
/// <summary>
@@ -383,11 +383,11 @@ public unsafe partial class EntityManager : IDisposable
/// <param name="componentID">The component space ID of the singleton.</param>
/// <param name="pComponent">Pointer to the component data.</param>
/// <returns>The result status of the operation.</returns>
public ErrorStatus CreateSingleton(Identifier<IComponent> componentID, void* pComponent)
public Error CreateSingleton(Identifier<IComponent> componentID, void* pComponent)
{
if (pComponent == null)
{
return ErrorStatus.InvalidArgument;
return Error.InvalidArgument;
}
// Check if singleton already exists
@@ -396,7 +396,7 @@ public unsafe partial class EntityManager : IDisposable
if (arcID.IsValid)
{
return ErrorStatus.InvalidArgument;
return Error.InvalidArgument;
}
arcID = _world.ComponentManager.CreateArchetype([componentID], signatureHash);
@@ -415,7 +415,7 @@ public unsafe partial class EntityManager : IDisposable
archetype.SetEntity(chunkIndex, rowIndex, entity);
archetype.SetComponentData(chunkIndex, rowIndex, componentID, pComponent);
return ErrorStatus.None;
return Error.None;
}
/// <summary>
@@ -424,7 +424,7 @@ public unsafe partial class EntityManager : IDisposable
/// <typeparam name="T">The component space.</typeparam>
/// <param name="component">The component data.</param>
/// <returns>The result status of the operation.</returns>
public ErrorStatus CreateSingleton<T>(T component = default)
public Error CreateSingleton<T>(T component = default)
where T : unmanaged, IComponent
{
return CreateSingleton(ComponentTypeID<T>.Value, &component);
@@ -447,7 +447,7 @@ public unsafe partial class EntityManager : IDisposable
ref var archetype = ref _world.ComponentManager.GetArchetypeReference(arcID);
var layoutResult = archetype.GetLayout(componentID);
if (layoutResult.Error != ErrorStatus.None)
if (layoutResult.Error != Error.None)
{
return null;
}
@@ -480,7 +480,7 @@ public unsafe partial class EntityManager : IDisposable
var src = oldArch._chunks[oldChunk].GetUnsafePtr() + layout.offset + (layout.size * oldRow);
var r = newArch.GetLayout(layout.componentID);
if (r.Error != ErrorStatus.None)
if (r.Error != Error.None)
{
// New archetype does not have this component, skip it.
// This can happen when removing components.
@@ -500,13 +500,13 @@ public unsafe partial class EntityManager : IDisposable
/// <param name="componentID">The component space ID to add.</param>
/// <param name="pComponent">Pointer to the component data.</param>
/// <returns>The result status of the operation.</returns>
public ErrorStatus AddComponent(Entity entity, Identifier<IComponent> componentID, void* pComponent)
public Error AddComponent(Entity entity, Identifier<IComponent> componentID, void* pComponent)
{
// Find current location
ref var location = ref _entityLocations.GetElementReferenceAt(entity.ID, entity.Generation, out var exist);
if (!exist)
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
// Build new archetype signature
@@ -516,7 +516,7 @@ public unsafe partial class EntityManager : IDisposable
if (oldSignature.IsSet(componentID))
{
// Component already exists
return ErrorStatus.InvalidArgument;
return Error.InvalidArgument;
}
var newArcID = oldArchetype.GetEdgeAdd(componentID);
@@ -572,8 +572,8 @@ public unsafe partial class EntityManager : IDisposable
newArchetype.SetComponentData(newChunkIndex, newRowIndex, componentID, pComponent);
var r = oldArchetype.RemoveEntity(location.chunkIndex, location.rowIndex);
Debug.Assert(r == ErrorStatus.None); // We assert it because the entity should exist if the whole system is consistent.
if (r != ErrorStatus.None)
Debug.Assert(r == Error.None); // We assert it because the entity should exist if the whole system is consistent.
if (r != Error.None)
{
return r;
}
@@ -583,7 +583,7 @@ public unsafe partial class EntityManager : IDisposable
location.chunkIndex = newChunkIndex;
location.rowIndex = newRowIndex;
return ErrorStatus.None;
return Error.None;
}
/// <summary>
@@ -593,7 +593,7 @@ public unsafe partial class EntityManager : IDisposable
/// <param name="entity">The entity to add the component to.</param>
/// <param name="component">The component data.</param>
/// <returns>The result status of the operation.</returns>
public ErrorStatus AddComponent<T>(Entity entity, T component = default)
public Error AddComponent<T>(Entity entity, T component = default)
where T : unmanaged, IComponent
{
return AddComponent(entity, ComponentTypeID<T>.Value, &component);
@@ -605,13 +605,13 @@ public unsafe partial class EntityManager : IDisposable
/// <param name="entity">The entity to remove the component from.</param>
/// <param name="componentID">The component space ID to remove.</param>
/// <returns>The result status of the operation.</returns>
public ErrorStatus RemoveComponent(Entity entity, Identifier<IComponent> componentID)
public Error RemoveComponent(Entity entity, Identifier<IComponent> componentID)
{
// Find current location
ref var location = ref _entityLocations.GetElementReferenceAt(entity.ID, entity.Generation, out var exist);
if (!exist)
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
// Build new archetype signature
@@ -670,8 +670,8 @@ public unsafe partial class EntityManager : IDisposable
newArchetype.SetEntity(newChunkIndex, newRowIndex, entity);
var r = oldArchetype.RemoveEntity(location.chunkIndex, location.rowIndex);
Debug.Assert(r == ErrorStatus.None); // We assert it because the entity should exist if the whole system is consistent.
if (r != ErrorStatus.None)
Debug.Assert(r == Error.None); // We assert it because the entity should exist if the whole system is consistent.
if (r != Error.None)
{
return r;
}
@@ -687,7 +687,7 @@ public unsafe partial class EntityManager : IDisposable
location.chunkIndex = newChunkIndex;
location.rowIndex = newRowIndex;
return ErrorStatus.None;
return Error.None;
}
/// <summary>
@@ -696,7 +696,7 @@ public unsafe partial class EntityManager : IDisposable
/// <typeparam name="T">The component space.</typeparam>
/// <param name="entity">The entity to remove the component from.</param>
/// <returns>The result status of the operation.</returns>
public ErrorStatus RemoveComponent<T>(Entity entity)
public Error RemoveComponent<T>(Entity entity)
where T : unmanaged, IComponent
{
return RemoveComponent(entity, ComponentTypeID<T>.Value);
@@ -709,17 +709,17 @@ public unsafe partial class EntityManager : IDisposable
/// <param name="componentID">The component space ID to set.</param>
/// <param name="pComponent">Pointer to the component data.</param>
/// <returns>The result status of the operation.</returns>
public ErrorStatus SetComponent(Entity entity, Identifier<IComponent> componentID, void* pComponent)
public Error SetComponent(Entity entity, Identifier<IComponent> componentID, void* pComponent)
{
if (!_entityLocations.TryGetElementAt(entity.ID, entity.Generation, out var location))
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
ref var archetype = ref _world.ComponentManager.GetArchetypeReference(location.archetypeID);
archetype.SetComponentData(location.chunkIndex, location.rowIndex, componentID, pComponent);
return ErrorStatus.None;
return Error.None;
}
/// <summary>
@@ -728,7 +728,7 @@ public unsafe partial class EntityManager : IDisposable
/// <typeparam name="T">The component space.</typeparam>
/// <param name="entity">The entity to set the component data for.</param>
/// <param name="component">The component data.</param>
public ErrorStatus SetComponent<T>(Entity entity, T component)
public Error SetComponent<T>(Entity entity, T component)
where T : unmanaged, IComponent
{
return SetComponent(entity, ComponentTypeID<T>.Value, &component);
@@ -800,11 +800,11 @@ public unsafe partial class EntityManager : IDisposable
/// <param name="componentID">The component space ID of the enableable component.</
/// <param name="enabled">True to enable the component, false to disable it.</param>
/// <returns>The result status of the operation.</returns>
public ErrorStatus SetEnabled(Entity entity, Identifier<IComponent> componentID, bool enabled)
public Error SetEnabled(Entity entity, Identifier<IComponent> componentID, bool enabled)
{
if (!_entityLocations.TryGetElementAt(entity.ID, entity.Generation, out var location))
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
ref var archetype = ref _world.ComponentManager.GetArchetypeReference(location.archetypeID);
@@ -812,7 +812,7 @@ public unsafe partial class EntityManager : IDisposable
var rowIndex = location.rowIndex;
var layoutResult = archetype.GetLayout(componentID);
if (layoutResult.Error != ErrorStatus.None)
if (layoutResult.Error != Error.None)
{
return layoutResult.Error;
}
@@ -833,7 +833,7 @@ public unsafe partial class EntityManager : IDisposable
maskBase[byteIndex] &= (byte)~(1 << bitIndex);
}
return ErrorStatus.None;
return Error.None;
}
/// <summary>
@@ -843,7 +843,7 @@ public unsafe partial class EntityManager : IDisposable
/// <param name="entity">The entity to set the enabled state for.</param>
/// <param name="enabled">True to enable the component, false to disable it.</
/// <returns>The result status of the operation.</returns>
public ErrorStatus SetEnabled<T>(Entity entity, bool enabled)
public Error SetEnabled<T>(Entity entity, bool enabled)
where T : unmanaged, IEnableableComponent
{
return SetEnabled(entity, ComponentTypeID<T>.Value, enabled);

View File

@@ -355,7 +355,7 @@ public unsafe partial struct EntityQuery : IDisposable
{
// Get the EnableBitmask for this component in this chunk
var layoutResult = archetype.GetLayout(id);
if (layoutResult.Error != ErrorStatus.None
if (layoutResult.Error != Error.None
// Not enableable, always true
|| layoutResult.Value.enableBitsOffset == -1)
{
@@ -374,7 +374,7 @@ public unsafe partial struct EntityQuery : IDisposable
while (it.Next(out var id))
{
var layoutResult = archetype.GetLayout(id);
if (layoutResult.Error != ErrorStatus.None)
if (layoutResult.Error != Error.None)
{
continue;
}
@@ -395,7 +395,7 @@ public unsafe partial struct EntityQuery : IDisposable
while (it.Next(out var id))
{
var layoutResult = archetype.GetLayout(id);
if (layoutResult.Error != ErrorStatus.None)
if (layoutResult.Error != Error.None)
{
continue;
}

View File

@@ -1,4 +1,4 @@
#if false // FIX: API update in Misaki.HighPerformance.LowLevel.Collections require me to disable this for now.
#if false
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
using Misaki.HighPerformance.LowLevel.Utilities;

View File

@@ -146,5 +146,5 @@ public interface IShaderCompiler : IDisposable
{
Result<ShaderCompileResult> Compile(ref readonly ShaderCompilationConfig config, Allocator allocator);
Result<GraphicsCompiledResult> CompilePass(ref readonly PassDescriptor descriptor, ref readonly ShaderCompilationConfig additionalConfig, Key64<ShaderVariant> key);
Result<GraphicsCompiledResult, ErrorStatus> LoadCompiledCache(Key64<ShaderVariant> key);
Result<GraphicsCompiledResult, Error> LoadCompiledCache(Key64<ShaderVariant> key);
}

View File

@@ -89,14 +89,14 @@ internal sealed partial class DxcShaderCompiler
return argsArray;
}
private static Result<string, ErrorStatus> GetFinalShaderCode(string shaderPath, ReadOnlySpan<string> includes, string? injectedCode)
private static Result<string, Error> GetFinalShaderCode(string shaderPath, ReadOnlySpan<string> includes, string? injectedCode)
{
string shaderCode;
if (shaderPath == "hlsl_block")
{
if (string.IsNullOrEmpty(injectedCode))
{
return ErrorStatus.InvalidArgument;
return Error.InvalidArgument;
}
shaderCode = string.Empty;
@@ -105,7 +105,7 @@ internal sealed partial class DxcShaderCompiler
{
if (!File.Exists(shaderPath))
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
shaderCode = File.ReadAllText(shaderPath);
@@ -487,7 +487,7 @@ internal sealed unsafe partial class DxcShaderCompiler : IShaderCompiler
return compiled;
}
public Result<GraphicsCompiledResult, ErrorStatus> LoadCompiledCache(Key64<ShaderVariant> key)
public Result<GraphicsCompiledResult, Error> LoadCompiledCache(Key64<ShaderVariant> key)
{
ObjectDisposedException.ThrowIf(_disposed, this);
@@ -496,7 +496,7 @@ internal sealed unsafe partial class DxcShaderCompiler : IShaderCompiler
return compiledResult;
}
return ErrorStatus.NotFound;
return Error.NotFound;
}
public void Dispose()

View File

@@ -3,7 +3,9 @@ using Ghost.Core.Graphics;
using Ghost.Graphics.RHI;
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
using Misaki.HighPerformance.LowLevel.Utilities;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ghost.Graphics.Core;
@@ -66,17 +68,11 @@ public struct Material : IResourceReleasable
get; set;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void SetDirty()
{
_isDirty = true;
}
public ErrorStatus SetShader(Identifier<Shader> shaderId, IResourceAllocator allocator, IResourceDatabase database)
public Error SetShader(Identifier<Shader> shaderId, IResourceAllocator allocator, IResourceDatabase database)
{
if (!shaderId.IsValid)
{
return ErrorStatus.InvalidArgument;
return Error.InvalidArgument;
}
_cBufferCache.ReleaseResource(database);
@@ -125,16 +121,16 @@ public struct Material : IResourceReleasable
_cBufferCache = new CBufferCache(buffer, shader.CBufferSize);
}
return ErrorStatus.None;
return Error.None;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly unsafe Result<T, ErrorStatus> GetPropertyCache<T>()
public readonly unsafe Result<T, Error> GetPropertyCache<T>()
where T : unmanaged
{
if (sizeof(T) != _cBufferCache.Size)
{
return ErrorStatus.InvalidArgument;
return Error.InvalidArgument;
}
return *(T*)_cBufferCache.CpuData.GetUnsafePtr();
@@ -152,32 +148,45 @@ public struct Material : IResourceReleasable
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe ErrorStatus SetPropertyCache<T>(ref readonly T data)
public unsafe Error SetPropertyCache<T>(ref readonly T data)
where T : unmanaged
{
if (sizeof(T) != _cBufferCache.Size)
{
return ErrorStatus.InvalidArgument;
return Error.InvalidArgument;
}
Unsafe.WriteUnaligned(_cBufferCache.CpuData.GetUnsafePtr(), data);
SetDirty();
var dataSpan = MemoryMarshal.AsBytes(new ReadOnlySpan<T>(in data));
var cacheSpan = _cBufferCache.CpuData.AsSpan();
if (cacheSpan.SequenceEqual(dataSpan))
{
return Error.None;
}
return ErrorStatus.None;
dataSpan.CopyTo(cacheSpan);
_isDirty = true;
return Error.None;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe ErrorStatus SetRawPropertyCache(ReadOnlySpan<byte> data)
public Error SetRawPropertyCache(ReadOnlySpan<byte> data)
{
if (data.Length != _cBufferCache.Size)
{
return ErrorStatus.InvalidArgument;
return Error.InvalidArgument;
}
Unsafe.WriteUnaligned(_cBufferCache.CpuData.GetUnsafePtr(), data);
SetDirty();
var cacheSpan = _cBufferCache.CpuData.AsSpan();
if (cacheSpan.SequenceEqual(data))
{
return Error.None;
}
return ErrorStatus.None;
data.CopyTo(cacheSpan);
_isDirty = true;
return Error.None;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -191,11 +200,11 @@ public struct Material : IResourceReleasable
{
ref var pipelineOverride = ref _passPipelineOverride[passIndex];
pipelineOverride.options = options;
SetDirty();
_isDirty = true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ErrorStatus SetKeyword(IResourceDatabase resourceDatabase, int keywordId, bool enabled)
public Error SetKeyword(IResourceDatabase resourceDatabase, int keywordId, bool enabled)
{
var r = resourceDatabase.GetShaderReference(_shader);
if (r.IsFailure)
@@ -207,13 +216,13 @@ public struct Material : IResourceReleasable
var localIndex = shader.GetLocalKeywordIndex(keywordId);
if (localIndex == -1)
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
_keywordMask.SetKeyword(localIndex, enabled);
SetDirty();
_isDirty = true;
return ErrorStatus.None;
return Error.None;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -252,9 +261,9 @@ public struct Material : IResourceReleasable
var barrierData = r.Value;
var desc = BarrierDesc.Buffer(
cbufferResource,
barrierData.Sync,
barrierData.sync,
BarrierSync.Copy,
barrierData.Access,
barrierData.access,
BarrierAccess.CopyDest);
cmd.ResourceBarrier(desc);

View File

@@ -55,23 +55,27 @@ public readonly unsafe ref struct RenderingContext
}
var data = r.Value;
if (data.Layout == newLayout && data.Access == newAccess && data.Sync == newSync)
if (data.layout == newLayout && data.access == newAccess && data.sync == newSync)
{
return;
}
// For buffers, layout is usually Undefined/Common and doesn't change, but Access/Sync do.
// For textures, layout changes matter.
var desc = isTexture ?
BarrierDesc.Texture(
BarrierDesc desc;
if (isTexture)
{
desc = BarrierDesc.Texture(
resource,
data.Sync, newSync,
data.Access, newAccess,
data.Layout, newLayout)
: BarrierDesc.Buffer(
data.sync, newSync,
data.access, newAccess,
data.layout, newLayout);
}
else
{
desc = BarrierDesc.Buffer(
resource,
data.Sync, newSync,
data.Access, newAccess);
data.sync, newSync,
data.access, newAccess);
}
_directCmd.ResourceBarrier(new ReadOnlySpan<BarrierDesc>(in desc));
ResourceDatabase.SetResourceBarrierData(resource, new ResourceBarrierData(newLayout, newAccess, newSync));
@@ -188,13 +192,13 @@ public readonly unsafe ref struct RenderingContext
public void UploadTexture<T>(Handle<Texture> texture, ReadOnlySpan<T> data)
where T : unmanaged
{
var desc = ResourceDatabase.GetResourceDescription(texture.AsResource())
.GetValueOrThrow();
var desc = ResourceDatabase.GetResourceDescription(texture.AsResource()).GetValueOrThrow();
if (data.Length * sizeof(T) != desc.TextureDescription.GetTotalBytes())
{
throw new ArgumentException("Data size does not match texture size.");
}
//var size = ResourceAllocator.GetSizeInfo(desc).Size;
//if ((ulong)(data.Length * sizeof(T)) != ResourceAllocator.GetSizeInfo(desc).Size)
//{
// throw new ArgumentException("Data size does not match texture size.");
//}
desc.TextureDescription.Format.GetSurfaceInfo(desc.TextureDescription.Width, desc.TextureDescription.Height, out var rowPitch, out var slicePitch, out _);
@@ -209,7 +213,7 @@ public readonly unsafe ref struct RenderingContext
slicePitch = slicePitch
};
_directCmd.UploadTexture(texture, [subresourceData]);
_directCmd.UploadTexture(texture, subresourceData);
}
}
}

View File

@@ -186,12 +186,12 @@ public partial struct Shader : IResourceReleasable
return ref _shaderPasses[index];
}
public readonly Result<ShaderPass, ErrorStatus> TryGetPass(Identifier<ShaderPass> passID, out int passIndex)
public readonly Result<ShaderPass, Error> TryGetPass(Identifier<ShaderPass> passID, out int passIndex)
{
if (_passIDToLocal.TryGetValue(passID.Value, out var index))
{
passIndex = -1;
return ErrorStatus.NotFound;
return Error.NotFound;
}
passIndex = index;

View File

@@ -115,9 +115,9 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#if DEBUG
[System.Diagnostics.CodeAnalysis.DoesNotReturn]
private static void RecordError(string cmdName, ErrorStatus status)
private static void RecordError(string cmdName, Error status)
#else
private void RecordError(string cmdName, ErrorStatus status)
private void RecordError(string cmdName, Error status)
#endif
{
#if DEBUG
@@ -168,7 +168,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
_isRecording = false;
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return Result.Failure($"Command buffer ended with errors at {_lastError.CommandIndex}, command '{_lastError.CommandName}': {_lastError.Status}");
}
@@ -182,7 +182,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -198,7 +198,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -351,7 +351,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -365,12 +365,12 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
var handle = renderTargets[i];
if (!handle.IsValid)
{
RecordError(nameof(SetRenderTargets), ErrorStatus.InvalidArgument);
RecordError(nameof(SetRenderTargets), Error.InvalidArgument);
continue;
}
var recordResult = _resourceDatabase.GetResourceRecord(handle.AsResource());
if (recordResult.Error != ErrorStatus.None)
if (recordResult.Error != Error.None)
{
RecordError(nameof(SetRenderTargets), recordResult.Error);
continue;
@@ -386,7 +386,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
if (pDsvHandle != null)
{
var recordResult = _resourceDatabase.GetResourceRecord(depthTarget.AsResource());
if (recordResult.Error != ErrorStatus.None)
if (recordResult.Error != Error.None)
{
RecordError(nameof(SetRenderTargets), recordResult.Error);
return;
@@ -404,7 +404,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -412,7 +412,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
IncrementCommandCount();
var recordResult = _resourceDatabase.GetResourceRecord(renderTarget.AsResource());
if (recordResult.Error != ErrorStatus.None)
if (recordResult.Error != Error.None)
{
RecordError(nameof(ClearRenderTargetView), recordResult.Error);
return;
@@ -436,7 +436,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -444,7 +444,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
IncrementCommandCount();
var recordResult = _resourceDatabase.GetResourceRecord(depthStencil.AsResource());
if (recordResult.Error != ErrorStatus.None)
if (recordResult.Error != Error.None)
{
RecordError(nameof(ClearDepthStencilView), recordResult.Error);
return;
@@ -467,7 +467,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -480,12 +480,12 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
var rtDesc = rtDescs[i];
if (rtDesc.Texture.IsInvalid)
{
RecordError(nameof(BeginRenderPass), ErrorStatus.InvalidArgument);
RecordError(nameof(BeginRenderPass), Error.InvalidArgument);
continue;
}
var recordResult = _resourceDatabase.GetResourceRecord(rtDesc.Texture.AsResource());
if (recordResult.Error != ErrorStatus.None)
if (recordResult.Error != Error.None)
{
RecordError(nameof(BeginRenderPass), recordResult.Error);
continue;
@@ -539,7 +539,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
if (pDsvDesc != null)
{
var recordResult = _resourceDatabase.GetResourceRecord(depthDesc.Texture.AsResource());
if (recordResult.Error != ErrorStatus.None)
if (recordResult.Error != Error.None)
{
RecordError(nameof(BeginRenderPass), recordResult.Error);
return;
@@ -628,7 +628,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -643,7 +643,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -659,7 +659,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -667,7 +667,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
IncrementCommandCount();
var psor = _pipelineLibrary.GetGraphicsPSO(pipelineKey);
if (psor.Error != ErrorStatus.None)
if (psor.Error != Error.None)
{
RecordError(nameof(SetPipelineState), psor.Error);
return;
@@ -682,7 +682,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -698,7 +698,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -706,7 +706,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
IncrementCommandCount();
var recordResult = _resourceDatabase.GetResourceRecord(buffer.AsResource());
if (recordResult.Error != ErrorStatus.None)
if (recordResult.Error != Error.None)
{
RecordError(nameof(BeginRenderPass), recordResult.Error);
return;
@@ -728,7 +728,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -751,7 +751,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -774,7 +774,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -792,7 +792,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -807,7 +807,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -822,7 +822,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -837,7 +837,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -870,7 +870,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -890,7 +890,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -919,7 +919,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -960,7 +960,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
ThrowIfDisposed();
ThrowIfNotRecording();
#if !DEBUG
if (_lastError.Status != ErrorStatus.None)
if (_lastError.Status != Error.None)
{
return;
}
@@ -971,7 +971,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
var pSrcResource = _resourceDatabase.GetResource(src.AsResource());
if (pSrcResource == null || pDestResource == null)
{
RecordError(nameof(CopyBuffer), ErrorStatus.InvalidArgument);
RecordError(nameof(CopyBuffer), Error.InvalidArgument);
return;
}

View File

@@ -331,14 +331,14 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary
return _pipelineCache.ContainsKey(key);
}
public Result<SharedPtr<ID3D12PipelineState>, ErrorStatus> GetGraphicsPSO(Key128<GraphicsPipeline> key)
public Result<SharedPtr<ID3D12PipelineState>, Error> GetGraphicsPSO(Key128<GraphicsPipeline> key)
{
if (_pipelineCache.TryGetValue(key, out var cacheEntry))
{
return cacheEntry.pso.Share();
}
return ErrorStatus.NotFound;
return Error.NotFound;
}
public void Dispose()

View File

@@ -68,7 +68,7 @@ internal class D3D12Renderer : IRenderer
// HACK: This is hard coded for testing purposes only.
var error = RenderScene(target, RenderOutput.Viewport, RenderOutput.Scissor);
if (error != ErrorStatus.None)
if (error != Error.None)
{
_commandBuffer.End();
return Result.Failure(error);
@@ -88,7 +88,7 @@ internal class D3D12Renderer : IRenderer
}
// TODO: A proper render graph integration.
private ErrorStatus RenderScene(Handle<Texture> target, ViewportDesc viewport, RectDesc rect)
private Error RenderScene(Handle<Texture> target, ViewportDesc viewport, RectDesc rect)
{
// NOTE: Testing only.
var ctx = new RenderingContext(_graphicsEngine, _commandBuffer);
@@ -116,7 +116,7 @@ internal class D3D12Renderer : IRenderer
//_commandBuffer.EndRenderPass();
_frameIndex++;
return ErrorStatus.None;
return Error.None;
}
public void Dispose()

View File

@@ -605,9 +605,9 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
var barrierData = new ResourceBarrierData
{
Access = BarrierAccess.NoAccess,
Layout = BarrierLayout.Common,
Sync = BarrierSync.None
access = BarrierAccess.NoAccess,
layout = BarrierLayout.Common,
sync = BarrierSync.None
};
return TrackAllocation(alloc, barrierData, ResourceViewGroup.Invalid, default, name, false);
@@ -693,9 +693,9 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
var barrierData = new ResourceBarrierData
{
Access = BarrierAccess.NoAccess,
Layout = BarrierLayout.Common,
Sync = BarrierSync.None
access = BarrierAccess.NoAccess,
layout = BarrierLayout.Common,
sync = BarrierSync.None
};
Handle<GPUResource> resource;
@@ -715,7 +715,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
{
ObjectDisposedException.ThrowIf(_disposed, this);
var textureDesc = desc.ToTextureDescripton();
var textureDesc = desc.ToTextureDescription();
return CreateTexture(in textureDesc, name, options);
}
@@ -803,9 +803,9 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
var barrierData = new ResourceBarrierData
{
Access = BarrierAccess.NoAccess,
Layout = BarrierLayout.Undefined,
Sync = BarrierSync.None
access = BarrierAccess.NoAccess,
layout = BarrierLayout.Undefined,
sync = BarrierSync.None
};
Handle<GPUResource> resource;
@@ -927,7 +927,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
ObjectDisposedException.ThrowIf(_disposed, this);
var material = new Material();
if (material.SetShader(shader, this, _resourceDatabase) != ErrorStatus.None)
if (material.SetShader(shader, this, _resourceDatabase) != Error.None)
{
return Handle<Material>.Invalid;
}

View File

@@ -6,11 +6,14 @@ using Misaki.HighPerformance.Collections;
using Misaki.HighPerformance.LowLevel;
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using TerraFX.Interop.DirectX;
namespace Ghost.Graphics.D3D12;
// TODO: Thread safety
internal class D3D12ResourceDatabase : IResourceDatabase
{
internal unsafe record struct ResourceRecord
@@ -38,9 +41,6 @@ internal class D3D12ResourceDatabase : IResourceDatabase
public ResourceViewGroup viewGroup;
public ResourceUnion resource;
//public BarrierLayout layout;
//public BarrierAccess access;
//public BarrierSync sync;
public ResourceBarrierData barrierData;
public uint cpuFenceValue;
@@ -71,7 +71,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
this.desc = resource->GetDesc().ToResourceDesc();
}
public uint Release(D3D12DescriptorAllocator descriptorAllocator)
public readonly uint Release(D3D12DescriptorAllocator descriptorAllocator)
{
var refCount = 0u;
if (Allocated)
@@ -87,10 +87,6 @@ internal class D3D12ResourceDatabase : IResourceDatabase
}
descriptorAllocator.Release(viewGroup);
resource = default;
viewGroup = default;
return refCount;
}
}
@@ -138,6 +134,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
public unsafe Handle<GPUResource> ImportExternalResource(ID3D12Resource* pResource, ResourceBarrierData initialBarrierData, ResourceViewGroup viewGroup, string? name = null)
{
ObjectDisposedException.ThrowIf(_disposed, this);
if (pResource == null)
{
#if DEBUG
@@ -196,17 +193,17 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return _resources.Contains(handle.ID, handle.Generation);
}
public RefResult<ResourceRecord, ErrorStatus> GetResourceRecord(Handle<GPUResource> handle)
public RefResult<ResourceRecord, Error> GetResourceRecord(Handle<GPUResource> handle)
{
ObjectDisposedException.ThrowIf(_disposed, this);
ref var info = ref _resources.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
if (!exist)
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
return RefResult<ResourceRecord, ErrorStatus>.Success(ref info);
return RefResult<ResourceRecord, Error>.Success(ref info);
}
public SharedPtr<ID3D12Resource> GetResource(Handle<GPUResource> handle)
@@ -220,7 +217,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return r.Value.ResourcePtr;
}
public Result<ResourceBarrierData, ErrorStatus> GetResourceBarrierData(Handle<GPUResource> handle)
public Result<ResourceBarrierData, Error> GetResourceBarrierData(Handle<GPUResource> handle)
{
var r = GetResourceRecord(handle);
if (r.IsFailure)
@@ -231,7 +228,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return r.Value.barrierData;
}
public ErrorStatus SetResourceBarrierData(Handle<GPUResource> handle, ResourceBarrierData data)
public Error SetResourceBarrierData(Handle<GPUResource> handle, ResourceBarrierData data)
{
var r = GetResourceRecord(handle);
if (r.IsFailure)
@@ -240,10 +237,10 @@ internal class D3D12ResourceDatabase : IResourceDatabase
}
r.Value.barrierData = data;
return ErrorStatus.None;
return Error.None;
}
public Result<ResourceDesc, ErrorStatus> GetResourceDescription(Handle<GPUResource> handle)
public Result<ResourceDesc, Error> GetResourceDescription(Handle<GPUResource> handle)
{
var r = GetResourceRecord(handle);
if (r.IsFailure)
@@ -254,7 +251,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return r.Value.desc;
}
public uint GetBindlessIndex(Handle<GPUResource> handle)
public uint GetBindlessIndex(Handle<GPUResource> handle, BindlessAccess access = BindlessAccess.ShaderResource)
{
var r = GetResourceRecord(handle);
if (r.IsFailure || !r.Value.Allocated)
@@ -262,7 +259,13 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return ~0u;
}
return (uint)r.Value.viewGroup.srv.Value;
return access switch
{
BindlessAccess.ShaderResource => (uint)r.Value.viewGroup.srv.Value,
BindlessAccess.ConstantBuffer => (uint)r.Value.viewGroup.cbv.Value,
BindlessAccess.UnorderedAccess => (uint)r.Value.viewGroup.uav.Value,
_ => ~0u,
};
}
public string? GetResourceName(Handle<GPUResource> handle)
@@ -345,15 +348,15 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return _meshes.Contains(handle.ID, handle.Generation);
}
public RefResult<Mesh, ErrorStatus> GetMeshReference(Handle<Mesh> handle)
public RefResult<Mesh, Error> GetMeshReference(Handle<Mesh> handle)
{
ref var mesh = ref _meshes.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
if (!exist)
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
return RefResult<Mesh, ErrorStatus>.Success(ref mesh);
return RefResult<Mesh, Error>.Success(ref mesh);
}
public void ReleaseMesh(Handle<Mesh> handle)
@@ -384,15 +387,15 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return _materials.Contains(handle.ID, handle.Generation);
}
public RefResult<Material, ErrorStatus> GetMaterialReference(Handle<Material> handle)
public RefResult<Material, Error> GetMaterialReference(Handle<Material> handle)
{
ref var material = ref _materials.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
if (!exist)
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
return RefResult<Material, ErrorStatus>.Success(ref material);
return RefResult<Material, Error>.Success(ref material);
}
public void ReleaseMaterial(Handle<Material> handle)
@@ -424,14 +427,14 @@ internal class D3D12ResourceDatabase : IResourceDatabase
return id.Value >= 0 && id.Value < _shaders.Count;
}
public RefResult<Shader, ErrorStatus> GetShaderReference(Identifier<Shader> id)
public RefResult<Shader, Error> GetShaderReference(Identifier<Shader> id)
{
if (!HasShader(id))
{
return ErrorStatus.NotFound;
return Error.NotFound;
}
return RefResult<Shader, ErrorStatus>.Success(ref _shaders[id.Value]);
return RefResult<Shader, Error>.Success(ref _shaders[id.Value]);
}
public void ReleaseShader(Identifier<Shader> id)
@@ -449,6 +452,8 @@ internal class D3D12ResourceDatabase : IResourceDatabase
public void Dispose()
{
[DoesNotReturn]
[Conditional("DEBUG")]
static void ThrowMemoryLeakException(string resourceType, int count)
{
throw new MemoryLeakException($"ResourceAllocator is being disposed with {count} {resourceType} still registered. Ensure all resources are released before disposing.");

View File

@@ -159,9 +159,9 @@ internal unsafe class D3D12SwapChain : ISwapChain
var barrierData = new ResourceBarrierData
{
Access = BarrierAccess.NoAccess,
Layout = BarrierLayout.Present,
Sync = BarrierSync.None,
access = BarrierAccess.NoAccess,
layout = BarrierLayout.Present,
sync = BarrierSync.None,
};
var handle = _resourceDatabase.ImportExternalResource(pBackBuffer, barrierData, view);

View File

@@ -601,7 +601,7 @@ public struct RenderTargetDesc
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TextureDesc ToTextureDescripton()
public TextureDesc ToTextureDescription()
{
var usage = Type == RenderTargetType.Color ? TextureUsage.RenderTarget : TextureUsage.DepthStencil;
if (CreationFlags.HasFlag(RenderTargetCreationFlags.AllowUAV))
@@ -768,7 +768,7 @@ public struct CommandError
get; set;
}
public ErrorStatus Status
public Error Status
{
get; set;
}

View File

@@ -13,18 +13,25 @@ public interface IResourceReleasable
public struct ResourceBarrierData
{
public BarrierLayout Layout;
public BarrierAccess Access;
public BarrierSync Sync;
public BarrierLayout layout;
public BarrierAccess access;
public BarrierSync sync;
public ResourceBarrierData(BarrierLayout layout, BarrierAccess access, BarrierSync sync)
{
Layout = layout;
Access = access;
Sync = sync;
this.layout = layout;
this.access = access;
this.sync = sync;
}
}
public enum BindlessAccess
{
ShaderResource,
ConstantBuffer,
UnorderedAccess,
}
// TODO: Consider adding methods for resource enumeration, statistics, and bulk operations.
// TODO: Consider adding async resource loading and streaming support.
// TODO: Mesh, Material, Shader management could be separated into their own interfaces for better modularity because they are not bound to specific graphics API.
@@ -53,29 +60,30 @@ public interface IResourceDatabase : IDisposable
/// </summary>
/// <param name="handle">The handle that uniquely identifies the resource.</param>
/// <returns>A ResourceBarrierData value representing the current barrier state.</returns>
Result<ResourceBarrierData, ErrorStatus> GetResourceBarrierData(Handle<GPUResource> handle);
Result<ResourceBarrierData, Error> GetResourceBarrierData(Handle<GPUResource> handle);
/// <summary>
/// Sets the barrier data of the specified resource handle.
/// </summary>
/// <param name="handle">The handle that identifies the resource.</param>
/// <param name="data">The new barrier data.</param>
/// <returns>An ErrorStatus indicating the success or failure of the operation.</returns>
ErrorStatus SetResourceBarrierData(Handle<GPUResource> handle, ResourceBarrierData data);
/// <returns>An Error indicating the success or failure of the operation.</returns>
Error SetResourceBarrierData(Handle<GPUResource> handle, ResourceBarrierData data);
/// <summary>
/// Retrieves the description of a GPU resource associated with the specified handle.
/// </summary>
/// <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>
Result<ResourceDesc, ErrorStatus> GetResourceDescription(Handle<GPUResource> handle);
Result<ResourceDesc, Error> GetResourceDescription(Handle<GPUResource> handle);
/// <summary>
/// Retrieves the bindless index associated with the specified GPU resource handle.
/// </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="access">The type of bindless access for which to obtain the index.</param>
/// <returns>The bindless index corresponding to the specified GPU resource handle. ~0 if the resource does not support bindless access or is not found.</returns>
uint GetBindlessIndex(Handle<GPUResource> handle);
uint GetBindlessIndex(Handle<GPUResource> handle, BindlessAccess access = BindlessAccess.ShaderResource);
/// <summary>
/// Retrieves the name of the GPU resource associated with the specified handle.
@@ -135,7 +143,7 @@ public interface IResourceDatabase : IDisposable
/// </summary>
/// <param name="handle">The handle of the mesh to retrieve. Must refer to a valid mesh; otherwise, the behavior is undefined.</param>
/// <returns>A result containing a reference to the mesh corresponding to the specified handle, or an error status if the handle is invalid.</returns>
RefResult<Mesh, ErrorStatus> GetMeshReference(Handle<Mesh> handle);
RefResult<Mesh, Error> GetMeshReference(Handle<Mesh> handle);
/// <summary>
/// Releases the mesh resource associated with the specified handle, freeing any resources held by it. Includes both CPU and GPU resources.
@@ -162,7 +170,7 @@ public interface IResourceDatabase : IDisposable
/// </summary>
/// <param name="handle">The handle of the material to retrieve. Must refer to a valid material.</param>
/// <returns>A result containing a reference to the material corresponding to the specified handle, or an error status if the handle is invalid.</returns>
RefResult<Material, ErrorStatus> GetMaterialReference(Handle<Material> handle);
RefResult<Material, Error> GetMaterialReference(Handle<Material> handle);
/// <summary>
/// Releases the material associated with the specified handle, making it available for reuse or disposal.
@@ -189,7 +197,7 @@ public interface IResourceDatabase : IDisposable
/// </summary>
/// <param name="id">The identifier of the shader to retrieve. Must refer to a valid shader.</param>
/// <returns>A result containing a reference to the shader corresponding to the specified identifier, or an error status if the identifier is invalid.</returns>
RefResult<Shader, ErrorStatus> GetShaderReference(Identifier<Shader> id);
RefResult<Shader, Error> GetShaderReference(Identifier<Shader> id);
/// <summary>
/// Releases the shader associated with the specified identifier, freeing any resources allocated to it.

View File

@@ -68,7 +68,6 @@ public sealed class RenderGraph : IDisposable
Blackboard = new RenderGraphBlackboard();
}
/// <summary>
/// Resets the render graph for a new frame.
/// Reuses existing allocations to minimize GC.
@@ -224,7 +223,7 @@ public sealed class RenderGraph : IDisposable
{
_compiler.Dispose();
// We need to reset the whole graph to return resources to the pool
// HACK: Ideally, we should have a Dispose method. But for now, we just reset to release resources.
Reset();
}
}

View File

@@ -50,8 +50,8 @@ internal struct ResourceBarrier
public override readonly string ToString()
{
return AliasingPredecessor.IsValid
? $"[Pass {PassIndex}] Aliasing Barrier: {AliasingPredecessor.Value}->{Resource.Value} Target: {TargetState.Layout}"
: $"[Pass {PassIndex}] Barrier: {Resource.Value} Target: {TargetState.Layout}";
? $"[Pass {PassIndex}] Aliasing Barrier: {AliasingPredecessor.Value}->{Resource.Value} Target: {TargetState.layout}"
: $"[Pass {PassIndex}] Barrier: {Resource.Value} Target: {TargetState.layout}";
}
}
@@ -88,8 +88,8 @@ internal struct CompiledBarrier
public override readonly string ToString()
{
return AliasingPredecessor.IsValid
? $"[Pass {PassIndex}] Aliasing: {AliasingPredecessor.Value}->{Resource.Value} -> {TargetState.Layout}"
: $"[Pass {PassIndex}] Transition: {Resource.Value} -> {TargetState.Layout}";
? $"[Pass {PassIndex}] Aliasing: {AliasingPredecessor.Value}->{Resource.Value} -> {TargetState.layout}"
: $"[Pass {PassIndex}] Transition: {Resource.Value} -> {TargetState.layout}";
}
}
@@ -254,7 +254,7 @@ internal static class RenderGraphBarriers
if (pass.colorAccess[i].id.IsValid)
{
var usage = pass.colorAccess[i].usage;
var targetState = new ResourceBarrierData(usage.Layout, usage.Access, usage.Sync);
var targetState = new ResourceBarrierData(usage.layout, usage.access, usage.sync);
AddTransition(pass.colorAccess[i].id.AsResource(), targetState);
}
}
@@ -263,7 +263,7 @@ internal static class RenderGraphBarriers
if (pass.depthAccess.id.IsValid)
{
var usage = pass.depthAccess.usage;
var targetState = new ResourceBarrierData(usage.Layout, usage.Access, usage.Sync);
var targetState = new ResourceBarrierData(usage.layout, usage.access, usage.sync);
AddTransition(pass.depthAccess.id.AsResource(), targetState);
}

View File

@@ -47,6 +47,7 @@ internal sealed class RenderGraphContext : IRasterRenderContext, IComputeRenderC
private readonly TextureFormat[] _rtvFormats;
private TextureFormat _dsvFormat;
private int _rtvCount;
private Handle<GraphicsBuffer> _activePerMaterialData;
private Handle<GraphicsBuffer> _activePerMeshData;
@@ -82,6 +83,7 @@ internal sealed class RenderGraphContext : IRasterRenderContext, IComputeRenderC
}
_dsvFormat = dsvFormat;
_rtvCount = rtvFormats.Length;
}
public Handle<GPUResource> GetActualResource(Identifier<RGResource> resource)
@@ -145,7 +147,7 @@ internal sealed class RenderGraphContext : IRasterRenderContext, IComputeRenderC
VariantKey = shaderVariantKey,
PipelineOption = materialPipeline,
RtvFormats = _rtvFormats,
RtvFormats = _rtvFormats.AsSpan(0, _rtvCount),
DsvFormat = _dsvFormat,
};

View File

@@ -173,22 +173,22 @@ internal sealed class RenderGraphExecutor
layoutBefore = BarrierLayout.Undefined;
accessBefore = BarrierAccess.NoAccess;
syncBefore = predState.Sync;
syncBefore = predState.sync;
}
else
{
layoutBefore = currentState.Layout;
accessBefore = currentState.Access;
syncBefore = currentState.Sync;
layoutBefore = currentState.layout;
accessBefore = currentState.access;
syncBefore = currentState.sync;
}
var target = compiledBarrier.TargetState;
// Skip if already in target state (optimization)
if (!compiledBarrier.AliasingPredecessor.IsValid &&
layoutBefore == target.Layout &&
accessBefore == target.Access &&
syncBefore == target.Sync)
layoutBefore == target.layout &&
accessBefore == target.access &&
syncBefore == target.sync)
{
continue;
}
@@ -198,16 +198,16 @@ internal sealed class RenderGraphExecutor
if (compiledBarrier.ResourceType == RenderGraphResourceType.Texture)
{
desc = BarrierDesc.Texture(resourceHandle,
syncBefore, target.Sync,
accessBefore, target.Access,
layoutBefore, target.Layout,
syncBefore, target.sync,
accessBefore, target.access,
layoutBefore, target.layout,
discard: compiledBarrier.Flags.HasFlag(BarrierFlags.Discard));
}
else
{
desc = BarrierDesc.Buffer(resourceHandle,
syncBefore, target.Sync,
accessBefore, target.Access);
syncBefore, target.sync,
accessBefore, target.access);
}
if (barrierCount >= MaxBatch)

View File

@@ -1,4 +1,5 @@
using Ghost.Core;
using Ghost.Graphics.RHI;
using System.Runtime.CompilerServices;
namespace Ghost.Graphics.RenderGraphModule;
@@ -27,7 +28,7 @@ internal abstract class RenderGraphPassBase
public bool asyncCompute;
public TextureAccess depthAccess;
public TextureAccess[] colorAccess = new TextureAccess[8];
public TextureAccess[] colorAccess = new TextureAccess[RHIUtility.MAX_RENDER_TARGETS];
public int maxColorIndex = -1;
public List<Identifier<RGResource>> randomAccess = new(8);

View File

@@ -8,7 +8,7 @@ struct PixelInput
float4 uv : TEXCOORD0;
};
[NumThreads(3, 1, 1)] // 3 threads per triangle
[numthreads(3, 1, 1)] // 3 threads per triangle
[OUTPUT_TRIANGLE_TOPOLOGY]
void MSMain(
uint3 groupThreadID : SV_GroupThreadID,
@@ -22,7 +22,6 @@ void MSMain(
Vertex v = LoadVertexData(vertexId, groupID.x, perObjectData.vertexBuffer, perObjectData.indexBuffer);
SetMeshOutputCounts(3, 1);
//v.position = mul(g_PerViewData.cameraMatrix, mul(g_PerObjectData.localToWorld, v.position));
// Write vertex output
outVerts[vertexId].position = v.position;

View File

@@ -32,7 +32,7 @@ shader "Hidden/Blit"
float4 uv : TEXCOORD0;
};
[NumThreads(4, 1, 1)]
[numthreads(4, 1, 1)]
[OUTPUT_TRIANGLE_TOPOLOGY]
void MSMain(
uint gtid : SV_GroupThreadID,

View File

@@ -49,8 +49,11 @@ struct Vertex
#define SAMPLE_TEXTURE2D_ARRAY(texId, sampId, uvw) SampleTextureArray(texId, sampId, uvw)
#define OUTPUT_TRIANGLE_TOPOLOGY OutputTopology("triangle")
#define OUTPUT_LINE_TOPOLOGY OutputTopology("line")
#define OUTPUT_TRIANGLE_TOPOLOGY outputtopology("triangle")
#define OUTPUT_LINE_TOPOLOGY outputtopology("line")
#define ZERO_INIT(T) (T)0
static inline float4 SampleTexture2D(uint texId, uint sampId, float2 uv)