Refactor error handling and improve type safety
Refactored error handling across the codebase by replacing exceptions with `Result`-based error handling for better robustness and consistency. - Updated `ResultExtensions` to use `EqualityComparer` for comparisons. - Enhanced `RenderingContext` with `GetValueOrThrow` for resource validation and added type constraints for texture methods. - Introduced `CommandError` and `RecordError` in `D3D12CommandBuffer` for improved error tracking. - Refactored `D3D12ResourceDatabase` to use `Result` objects for resource queries. - Updated `ICommandBuffer` and `IResourceDatabase` interfaces to return `Result` objects. - Improved type safety by replacing `int` with `uint` where appropriate. - Simplified texture handling in `MeshRenderPass` with new `CreateTexture` logic. - Cleaned up project files by removing unused and redundant entries. These changes enhance code maintainability, improve error reporting, and ensure type safety throughout the project.
This commit is contained in:
@@ -178,7 +178,7 @@ public static class ResultExtensions
|
|||||||
public static T GetValueOrThrow<T, S>(this Result<T, S> result, S expect)
|
public static T GetValueOrThrow<T, S>(this Result<T, S> result, S expect)
|
||||||
where S : Enum
|
where S : Enum
|
||||||
{
|
{
|
||||||
if (result.Status?.Equals(expect) ?? false)
|
if (!EqualityComparer<S>.Default.Equals(result.Status, expect))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Operation failed: expected status {expect}, but got {result.Status}");
|
throw new InvalidOperationException($"Operation failed: expected status {expect}, but got {result.Status}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,18 +58,6 @@
|
|||||||
<ProjectReference Include="..\Ghost.Test.Core\Ghost.Test.Core.csproj" />
|
<ProjectReference Include="..\Ghost.Test.Core\Ghost.Test.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Page Update="Windows\DebugOutputWindow.xaml">
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Page Update="Controls\DebugConsole.xaml">
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
|
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
|
||||||
Explorer "Package and Publish" context menu entry to be enabled for this project even if
|
Explorer "Package and Publish" context menu entry to be enabled for this project even if
|
||||||
@@ -96,13 +84,4 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
|
|
||||||
<DebugType>embedded</DebugType>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<DebugType>embedded</DebugType>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
|
||||||
<DebugType>embedded</DebugType>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -102,8 +102,11 @@ public readonly unsafe ref struct RenderingContext
|
|||||||
public void UploadMesh(Handle<Mesh> mesh, bool markMeshStatic)
|
public void UploadMesh(Handle<Mesh> mesh, bool markMeshStatic)
|
||||||
{
|
{
|
||||||
ref var meshData = ref ResourceDatabase.GetMeshReference(mesh);
|
ref var meshData = ref ResourceDatabase.GetMeshReference(mesh);
|
||||||
var vertexState = ResourceDatabase.GetResourceState(meshData.VertexBuffer.AsResource());
|
var vertexState = ResourceDatabase.GetResourceState(meshData.VertexBuffer.AsResource())
|
||||||
var indexState = ResourceDatabase.GetResourceState(meshData.IndexBuffer.AsResource());
|
.GetValueOrThrow(ResultStatus.Success);
|
||||||
|
var indexState = ResourceDatabase.GetResourceState(meshData.IndexBuffer.AsResource())
|
||||||
|
.GetValueOrThrow(ResultStatus.Success);
|
||||||
|
|
||||||
var needVertexTransition = vertexState != ResourceState.CopyDest;
|
var needVertexTransition = vertexState != ResourceState.CopyDest;
|
||||||
var needIndexTransition = indexState != ResourceState.CopyDest;
|
var needIndexTransition = indexState != ResourceState.CopyDest;
|
||||||
|
|
||||||
@@ -149,7 +152,9 @@ public readonly unsafe ref struct RenderingContext
|
|||||||
};
|
};
|
||||||
|
|
||||||
var bufferHandle = meshData.ObjectDataBuffer.AsResource();
|
var bufferHandle = meshData.ObjectDataBuffer.AsResource();
|
||||||
var state = ResourceDatabase.GetResourceState(bufferHandle);
|
var state = ResourceDatabase.GetResourceState(bufferHandle)
|
||||||
|
.GetValueOrThrow(ResultStatus.Success);
|
||||||
|
|
||||||
var needTransition = state != ResourceState.CopyDest;
|
var needTransition = state != ResourceState.CopyDest;
|
||||||
if (needTransition)
|
if (needTransition)
|
||||||
{
|
{
|
||||||
@@ -164,17 +169,31 @@ public readonly unsafe ref struct RenderingContext
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Handle<Texture> CreateTexture(ref readonly TextureDesc desc, bool tempResource = false)
|
public Handle<Texture> CreateTexture<T>(ref readonly TextureDesc desc, ReadOnlySpan<T> data, bool tempResource = false)
|
||||||
|
where T : unmanaged
|
||||||
{
|
{
|
||||||
return ResourceAllocator.CreateTexture(in desc, tempResource);
|
var handle = ResourceAllocator.CreateTexture(in desc, tempResource);
|
||||||
|
UploadTexture(handle, data);
|
||||||
|
|
||||||
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UploadTexture(Handle<Texture> texture, ReadOnlySpan<byte> data)
|
public void UploadTexture<T>(Handle<Texture> texture, ReadOnlySpan<T> data)
|
||||||
|
where T : unmanaged
|
||||||
{
|
{
|
||||||
var desc = ResourceDatabase.GetResourceDescription(texture.AsResource());
|
var desc = ResourceDatabase.GetResourceDescription(texture.AsResource())
|
||||||
desc.TextureDescription.Format.GetSurfaceInfo((int)desc.TextureDescription.Width, (int)desc.TextureDescription.Height, out var rowPitch, out var slicePitch, out _);
|
.GetValueOrThrow(ResultStatus.Success);
|
||||||
|
|
||||||
|
if (data.Length * sizeof(T) != desc.TextureDescription.GetTotalBytes())
|
||||||
|
{
|
||||||
|
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 _);
|
||||||
|
|
||||||
|
var sateBefore = ResourceDatabase.GetResourceState(texture.AsResource())
|
||||||
|
.GetValueOrThrow(ResultStatus.Success);
|
||||||
|
|
||||||
var sateBefore = ResourceDatabase.GetResourceState(texture.AsResource());
|
|
||||||
var needTransition = sateBefore != ResourceState.CopyDest;
|
var needTransition = sateBefore != ResourceState.CopyDest;
|
||||||
|
|
||||||
if (needTransition)
|
if (needTransition)
|
||||||
@@ -182,7 +201,7 @@ public readonly unsafe ref struct RenderingContext
|
|||||||
_directCmd.ResourceBarrier(texture.AsResource(), sateBefore, ResourceState.CopyDest);
|
_directCmd.ResourceBarrier(texture.AsResource(), sateBefore, ResourceState.CopyDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
fixed (byte* pData = data)
|
fixed (T* pData = data)
|
||||||
{
|
{
|
||||||
var subresourceData = new SubResourceData
|
var subresourceData = new SubResourceData
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Ghost.Graphics.D3D12.Utilities;
|
|||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.LowLevel;
|
using Misaki.HighPerformance.LowLevel;
|
||||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
@@ -26,6 +27,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
private readonly D3D12DescriptorAllocator _descriptorAllocator;
|
private readonly D3D12DescriptorAllocator _descriptorAllocator;
|
||||||
private readonly CommandBufferType _type;
|
private readonly CommandBufferType _type;
|
||||||
|
|
||||||
|
private CommandError _lastError;
|
||||||
private ushort _commandCount;
|
private ushort _commandCount;
|
||||||
private bool _isRecording;
|
private bool _isRecording;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
@@ -124,6 +126,25 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
_commandCount++;
|
_commandCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
#if DEBUG
|
||||||
|
[DoesNotReturn]
|
||||||
|
#endif
|
||||||
|
private void RecordError(string cmdName, ResultStatus status)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
throw new InvalidOperationException($"Error at {cmdName} with {status}");
|
||||||
|
#else
|
||||||
|
|
||||||
|
_lastError = new CommandError
|
||||||
|
{
|
||||||
|
CommandName = cmdName,
|
||||||
|
CommandIndex = _commandCount,
|
||||||
|
Status = status
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
public void Begin()
|
public void Begin()
|
||||||
{
|
{
|
||||||
void ResetCommandList()
|
void ResetCommandList()
|
||||||
@@ -154,13 +175,20 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
_isRecording = true;
|
_isRecording = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void End()
|
public Result End()
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
ThrowIfNotRecording();
|
ThrowIfNotRecording();
|
||||||
|
|
||||||
_commandList.Get()->Close();
|
_commandList.Get()->Close();
|
||||||
_isRecording = false;
|
_isRecording = false;
|
||||||
|
|
||||||
|
if (_lastError.Status != ResultStatus.Success)
|
||||||
|
{
|
||||||
|
return Result.Failure($"Command buffer ended with errors at {_lastError.CommandIndex}, command '{_lastError.CommandName}': {_lastError.Status}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetScissorRect(RectDesc rect)
|
public void SetScissorRect(RectDesc rect)
|
||||||
@@ -182,7 +210,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
var count = 0u;
|
var count = 0u;
|
||||||
var pBarriers = stackalloc D3D12_RESOURCE_BARRIER[barrierDescs.Length];
|
var pBarriers = stackalloc D3D12_RESOURCE_BARRIER[barrierDescs.Length];
|
||||||
|
|
||||||
for (int i = 0; i < barrierDescs.Length; i++)
|
for (var i = 0; i < barrierDescs.Length; i++)
|
||||||
{
|
{
|
||||||
var desc = barrierDescs[i];
|
var desc = barrierDescs[i];
|
||||||
if (desc.StateBefore == desc.StateAfter)
|
if (desc.StateBefore == desc.StateAfter)
|
||||||
@@ -192,23 +220,32 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
|
|
||||||
if (!desc.Resource.IsValid)
|
if (!desc.Resource.IsValid)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Barrier resource at index {i} is not a valid resource handle");
|
RecordError(nameof(ResourceBarrier), ResultStatus.InvalidArgument);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref var resourceRecord = ref _resourceDatabase.GetResourceRecord(desc.Resource.AsResource());
|
var recordResult = _resourceDatabase.GetResourceRecord(desc.Resource);
|
||||||
if (resourceRecord.state != desc.StateBefore)
|
if (recordResult.Status != ResultStatus.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Resource state mismatch: expected {desc.StateBefore}, actual {resourceRecord.state}");
|
RecordError(nameof(ResourceBarrier), recordResult.Status);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var barrier = D3D12_RESOURCE_BARRIER.InitTransition(resourceRecord.ResourcePtr,
|
ref var record = ref recordResult.Value;
|
||||||
|
if (record.state != desc.StateBefore)
|
||||||
|
{
|
||||||
|
RecordError(nameof(ResourceBarrier), ResultStatus.InvalidState);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var barrier = D3D12_RESOURCE_BARRIER.InitTransition(record.ResourcePtr,
|
||||||
desc.StateBefore.ToD3D12States(), desc.StateAfter.ToD3D12States());
|
desc.StateBefore.ToD3D12States(), desc.StateAfter.ToD3D12States());
|
||||||
|
|
||||||
pBarriers[count] = barrier;
|
pBarriers[count] = barrier;
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
// Update the resource state in the database
|
// Update the resource state in the database
|
||||||
resourceRecord.state = desc.StateAfter;
|
record.state = desc.StateAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
_commandList.Get()->ResourceBarrier(count, pBarriers);
|
_commandList.Get()->ResourceBarrier(count, pBarriers);
|
||||||
@@ -216,28 +253,49 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
|
|
||||||
public void ResourceBarrier(Handle<GPUResource> resource, ResourceState stateBefore, ResourceState stateAfter)
|
public void ResourceBarrier(Handle<GPUResource> resource, ResourceState stateBefore, ResourceState stateAfter)
|
||||||
{
|
{
|
||||||
|
ThrowIfDisposed();
|
||||||
|
ThrowIfNotRecording();
|
||||||
|
IncrementCommandCount();
|
||||||
|
|
||||||
if (stateBefore == stateAfter)
|
if (stateBefore == stateAfter)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ref var resourceRecord = ref _resourceDatabase.GetResourceRecord(resource);
|
var recordResult = _resourceDatabase.GetResourceRecord(resource);
|
||||||
if (resourceRecord.state != stateBefore)
|
if (recordResult.Status != ResultStatus.Success)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Resource state mismatch: expected {stateBefore}, actual {resourceRecord.state}");
|
RecordError(nameof(ResourceBarrier), recordResult.Status);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var barrier = D3D12_RESOURCE_BARRIER.InitTransition(resourceRecord.ResourcePtr,
|
ref var record = ref recordResult.Value;
|
||||||
|
var barrier = D3D12_RESOURCE_BARRIER.InitTransition(record.ResourcePtr,
|
||||||
stateBefore.ToD3D12States(), stateAfter.ToD3D12States());
|
stateBefore.ToD3D12States(), stateAfter.ToD3D12States());
|
||||||
|
|
||||||
_commandList.Get()->ResourceBarrier(1, &barrier);
|
_commandList.Get()->ResourceBarrier(1, &barrier);
|
||||||
resourceRecord.state = stateAfter;
|
record.state = stateAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResourceBarrier(Handle<GPUResource> resource, ResourceState stateAfter)
|
public void ResourceBarrier(Handle<GPUResource> resource, ResourceState stateAfter)
|
||||||
{
|
{
|
||||||
var stateBefore = _resourceDatabase.GetResourceState(resource);
|
ThrowIfDisposed();
|
||||||
ResourceBarrier(resource, stateBefore, stateAfter);
|
ThrowIfNotRecording();
|
||||||
|
IncrementCommandCount();
|
||||||
|
|
||||||
|
var recordResult = _resourceDatabase.GetResourceRecord(resource);
|
||||||
|
if (recordResult.Status != ResultStatus.Success)
|
||||||
|
{
|
||||||
|
RecordError(nameof(ResourceBarrier), recordResult.Status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref var record = ref recordResult.Value;
|
||||||
|
var barrier = D3D12_RESOURCE_BARRIER.InitTransition(record.ResourcePtr,
|
||||||
|
record.state.ToD3D12States(), stateAfter.ToD3D12States());
|
||||||
|
|
||||||
|
_commandList.Get()->ResourceBarrier(1, &barrier);
|
||||||
|
record.state = stateAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetRenderTargets(ReadOnlySpan<Handle<Texture>> renderTargets, Handle<Texture> depthTarget)
|
public void SetRenderTargets(ReadOnlySpan<Handle<Texture>> renderTargets, Handle<Texture> depthTarget)
|
||||||
@@ -247,25 +305,44 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
IncrementCommandCount();
|
IncrementCommandCount();
|
||||||
|
|
||||||
var pRtvHandles = stackalloc D3D12_CPU_DESCRIPTOR_HANDLE[renderTargets.Length];
|
var pRtvHandles = stackalloc D3D12_CPU_DESCRIPTOR_HANDLE[renderTargets.Length];
|
||||||
|
var rtvCount = 0u;
|
||||||
for (var i = 0; i < renderTargets.Length; i++)
|
for (var i = 0; i < renderTargets.Length; i++)
|
||||||
{
|
{
|
||||||
var handle = renderTargets[i];
|
var handle = renderTargets[i];
|
||||||
if (!handle.IsValid)
|
if (!handle.IsValid)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Render target at index {i} is not a valid texture handle");
|
RecordError(nameof(SetRenderTargets), ResultStatus.InvalidArgument);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var descriptor = _resourceDatabase.GetResourceRecord(handle.AsResource()).viewGroup;
|
var recordResult = _resourceDatabase.GetResourceRecord(handle.AsResource());
|
||||||
pRtvHandles[i] = _descriptorAllocator.GetCpuHandle(descriptor.rtv);
|
if (recordResult.Status != ResultStatus.Success)
|
||||||
|
{
|
||||||
|
RecordError(nameof(SetRenderTargets), recordResult.Status);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var viewGroup = recordResult.Value.viewGroup;
|
||||||
|
pRtvHandles[i] = _descriptorAllocator.GetCpuHandle(viewGroup.rtv);
|
||||||
|
|
||||||
|
rtvCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pDsvHandle = stackalloc D3D12_CPU_DESCRIPTOR_HANDLE[depthTarget.IsValid ? 1 : 0];
|
var pDsvHandle = stackalloc D3D12_CPU_DESCRIPTOR_HANDLE[depthTarget.IsValid ? 1 : 0];
|
||||||
if (pDsvHandle != null)
|
if (pDsvHandle != null)
|
||||||
{
|
{
|
||||||
pDsvHandle[0] = _descriptorAllocator.GetCpuHandle(_resourceDatabase.GetResourceRecord(depthTarget.AsResource()).viewGroup.dsv);
|
var recordResult = _resourceDatabase.GetResourceRecord(depthTarget.AsResource());
|
||||||
|
if (recordResult.Status != ResultStatus.Success)
|
||||||
|
{
|
||||||
|
RecordError(nameof(SetRenderTargets), recordResult.Status);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_commandList.Get()->OMSetRenderTargets((uint)renderTargets.Length, pRtvHandles, FALSE, pDsvHandle);
|
var viewGroup = recordResult.Value.viewGroup;
|
||||||
|
pDsvHandle[0] = _descriptorAllocator.GetCpuHandle(viewGroup.dsv);
|
||||||
|
}
|
||||||
|
|
||||||
|
_commandList.Get()->OMSetRenderTargets(rtvCount, pRtvHandles, FALSE, pDsvHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginRenderPass(ReadOnlySpan<PassRenderTargetDesc> rtDescs, PassDepthStencilDesc depthDesc, bool allowUAVWrites = false)
|
public void BeginRenderPass(ReadOnlySpan<PassRenderTargetDesc> rtDescs, PassDepthStencilDesc depthDesc, bool allowUAVWrites = false)
|
||||||
@@ -280,11 +357,21 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
var rtDesc = rtDescs[i];
|
var rtDesc = rtDescs[i];
|
||||||
if (!rtDesc.Texture.IsValid)
|
if (!rtDesc.Texture.IsValid)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Render target at index {i} is not a valid texture handle");
|
RecordError(nameof(BeginRenderPass), ResultStatus.InvalidArgument);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var resourceInfo = _resourceDatabase.GetResourceRecord(rtDesc.Texture.AsResource());
|
var recordResult = _resourceDatabase.GetResourceRecord(rtDesc.Texture.AsResource());
|
||||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceInfo.viewGroup.rtv);
|
if (recordResult.Status != ResultStatus.Success)
|
||||||
|
{
|
||||||
|
RecordError(nameof(BeginRenderPass), recordResult.Status);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var record = recordResult.Value;
|
||||||
|
var cpuHandle = _descriptorAllocator.GetCpuHandle(record.viewGroup.rtv);
|
||||||
|
var format = record.desc.TextureDescription.Format.ToDXGIFormat();
|
||||||
|
var clearColor = rtDesc.ClearColor;
|
||||||
|
|
||||||
var desc = new D3D12_RENDER_PASS_RENDER_TARGET_DESC
|
var desc = new D3D12_RENDER_PASS_RENDER_TARGET_DESC
|
||||||
{
|
{
|
||||||
@@ -294,10 +381,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR,
|
Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR,
|
||||||
Clear = new D3D12_RENDER_PASS_BEGINNING_ACCESS_CLEAR_PARAMETERS
|
Clear = new D3D12_RENDER_PASS_BEGINNING_ACCESS_CLEAR_PARAMETERS
|
||||||
{
|
{
|
||||||
ClearValue = new D3D12_CLEAR_VALUE
|
ClearValue = new D3D12_CLEAR_VALUE(format, (float*)&clearColor)
|
||||||
{
|
|
||||||
Format = resourceInfo.desc.TextureDescription.Format.ToDXGIFormat(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
EndingAccess = new D3D12_RENDER_PASS_ENDING_ACCESS
|
EndingAccess = new D3D12_RENDER_PASS_ENDING_ACCESS
|
||||||
@@ -306,19 +390,22 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
desc.BeginningAccess.Clear.ClearValue.Color[0] = rtDesc.ClearColor.r;
|
|
||||||
desc.BeginningAccess.Clear.ClearValue.Color[1] = rtDesc.ClearColor.g;
|
|
||||||
desc.BeginningAccess.Clear.ClearValue.Color[2] = rtDesc.ClearColor.b;
|
|
||||||
desc.BeginningAccess.Clear.ClearValue.Color[3] = rtDesc.ClearColor.a;
|
|
||||||
|
|
||||||
pRtvDescs[i] = desc;
|
pRtvDescs[i] = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pDsvDesc = stackalloc D3D12_RENDER_PASS_DEPTH_STENCIL_DESC[depthDesc.Texture.IsValid ? 1 : 0];
|
var pDsvDesc = stackalloc D3D12_RENDER_PASS_DEPTH_STENCIL_DESC[depthDesc.Texture.IsValid ? 1 : 0];
|
||||||
if (pDsvDesc != null)
|
if (pDsvDesc != null)
|
||||||
{
|
{
|
||||||
var resourceInfo = _resourceDatabase.GetResourceRecord(depthDesc.Texture.AsResource());
|
var recordResult = _resourceDatabase.GetResourceRecord(depthDesc.Texture.AsResource());
|
||||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceInfo.viewGroup.dsv);
|
if (recordResult.Status != ResultStatus.Success)
|
||||||
|
{
|
||||||
|
RecordError(nameof(BeginRenderPass), recordResult.Status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var record = recordResult.Value;
|
||||||
|
var cpuHandle = _descriptorAllocator.GetCpuHandle(record.viewGroup.dsv);
|
||||||
|
var format = record.desc.TextureDescription.Format.ToDXGIFormat();
|
||||||
|
|
||||||
var desc = new D3D12_RENDER_PASS_DEPTH_STENCIL_DESC
|
var desc = new D3D12_RENDER_PASS_DEPTH_STENCIL_DESC
|
||||||
{
|
{
|
||||||
@@ -328,15 +415,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR,
|
Type = D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR,
|
||||||
Clear = new D3D12_RENDER_PASS_BEGINNING_ACCESS_CLEAR_PARAMETERS
|
Clear = new D3D12_RENDER_PASS_BEGINNING_ACCESS_CLEAR_PARAMETERS
|
||||||
{
|
{
|
||||||
ClearValue = new D3D12_CLEAR_VALUE
|
ClearValue = new D3D12_CLEAR_VALUE(format, depthDesc.ClearDepth, depthDesc.ClearStencil)
|
||||||
{
|
|
||||||
Format = resourceInfo.desc.TextureDescription.Format.ToDXGIFormat(),
|
|
||||||
DepthStencil = new D3D12_DEPTH_STENCIL_VALUE
|
|
||||||
{
|
|
||||||
Depth = depthDesc.ClearDepth,
|
|
||||||
Stencil = depthDesc.ClearStencil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -402,12 +481,19 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
ThrowIfNotRecording();
|
ThrowIfNotRecording();
|
||||||
IncrementCommandCount();
|
IncrementCommandCount();
|
||||||
|
|
||||||
var resource = _resourceDatabase.GetResource(buffer.AsResource());
|
var recordResult = _resourceDatabase.GetResourceRecord(buffer.AsResource());
|
||||||
|
if (recordResult.Status != ResultStatus.Success)
|
||||||
|
{
|
||||||
|
RecordError(nameof(BeginRenderPass), recordResult.Status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var record = recordResult.Value;
|
||||||
var vbView = new D3D12_VERTEX_BUFFER_VIEW
|
var vbView = new D3D12_VERTEX_BUFFER_VIEW
|
||||||
{
|
{
|
||||||
BufferLocation = resource.Get()->GetGPUVirtualAddress() + offset,
|
BufferLocation = record.ResourcePtr.Get()->GetGPUVirtualAddress() + offset,
|
||||||
SizeInBytes = (uint)(resource.Get()->GetDesc().Width - offset),
|
SizeInBytes = (uint)(record.ResourcePtr.Get()->GetDesc().Width - offset),
|
||||||
StrideInBytes = _resourceDatabase.GetResourceDescription(buffer.AsResource()).BufferDescription.Stride
|
StrideInBytes = record.desc.BufferDescription.Stride
|
||||||
};
|
};
|
||||||
|
|
||||||
_commandList.Get()->IASetVertexBuffers(slot, 1, &vbView);
|
_commandList.Get()->IASetVertexBuffers(slot, 1, &vbView);
|
||||||
@@ -541,8 +627,8 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
d3d12Subresources[i] = new D3D12_SUBRESOURCE_DATA
|
d3d12Subresources[i] = new D3D12_SUBRESOURCE_DATA
|
||||||
{
|
{
|
||||||
pData = subresources[i].pData,
|
pData = subresources[i].pData,
|
||||||
RowPitch = subresources[i].rowPitch,
|
RowPitch = (nint)subresources[i].rowPitch,
|
||||||
SlicePitch = subresources[i].slicePitch
|
SlicePitch = (nint)subresources[i].slicePitch
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,7 +652,8 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
var pSrcResource = _resourceDatabase.GetResource(src.AsResource());
|
var pSrcResource = _resourceDatabase.GetResource(src.AsResource());
|
||||||
if (pSrcResource == null || pDestResource == null)
|
if (pSrcResource == null || pDestResource == null)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Source or destination buffer is not valid");
|
RecordError(nameof(CopyBuffer), ResultStatus.InvalidArgument);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numBytes == 0)
|
if (numBytes == 0)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Ghost.Core;
|
||||||
using Ghost.Graphics.Contracts;
|
using Ghost.Graphics.Contracts;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Ghost.Graphics.Utilities;
|
using Ghost.Graphics.Utilities;
|
||||||
@@ -134,7 +135,7 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
|||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
|
|
||||||
_copyCommandBuffer.End();
|
_copyCommandBuffer.End().ThrowIfFailed();
|
||||||
_resourceAllocator.ReleaseTempResources();
|
_resourceAllocator.ReleaseTempResources();
|
||||||
_descriptorAllocator.ResetCbvSrvUavDynamicHeap();
|
_descriptorAllocator.ResetCbvSrvUavDynamicHeap();
|
||||||
_descriptorAllocator.ResetDSVDynamicHeap();
|
_descriptorAllocator.ResetDSVDynamicHeap();
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ internal class D3D12Renderer : IRenderer
|
|||||||
// BlitToDestination(_renderTarget, backBufferRT, frame.commandBuffer);
|
// BlitToDestination(_renderTarget, backBufferRT, frame.commandBuffer);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
frame.commandBuffer.End();
|
frame.commandBuffer.End().ThrowIfFailed();
|
||||||
|
|
||||||
_graphicsEngine.Device.GraphicsQueue.Submit(frame.commandBuffer);
|
_graphicsEngine.Device.GraphicsQueue.Submit(frame.commandBuffer);
|
||||||
_swapChain?.Present();
|
_swapChain?.Present();
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using System.Diagnostics;
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
using TerraFX.Interop.Windows;
|
using TerraFX.Interop.Windows;
|
||||||
|
|
||||||
using static TerraFX.Aliases.D3D12_Alias;
|
using static TerraFX.Aliases.D3D12_Alias;
|
||||||
using static TerraFX.Aliases.D3D12MA_Alias;
|
using static TerraFX.Aliases.D3D12MA_Alias;
|
||||||
using static TerraFX.Aliases.DXGI_Alias;
|
using static TerraFX.Aliases.DXGI_Alias;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Misaki.HighPerformance.Collections;
|
|||||||
using Misaki.HighPerformance.LowLevel;
|
using Misaki.HighPerformance.LowLevel;
|
||||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ namespace Ghost.Graphics.D3D12;
|
|||||||
|
|
||||||
internal class D3D12ResourceDatabase : IResourceDatabase
|
internal class D3D12ResourceDatabase : IResourceDatabase
|
||||||
{
|
{
|
||||||
internal unsafe struct ResourceRecord
|
internal unsafe record struct ResourceRecord
|
||||||
{
|
{
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
public struct ResourceUnion
|
public struct ResourceUnion
|
||||||
@@ -171,17 +172,17 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
|||||||
return _resources.Contains(handle.id, handle.generation);
|
return _resources.Contains(handle.id, handle.generation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref ResourceRecord GetResourceRecord(Handle<GPUResource> handle)
|
public RefResult<ResourceRecord, ResultStatus> GetResourceRecord(Handle<GPUResource> handle)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
ref var info = ref _resources.GetElementReferenceAt(handle.id, handle.generation, out var exist);
|
ref var info = ref _resources.GetElementReferenceAt(handle.id, handle.generation, out var exist);
|
||||||
if (!exist)
|
if (!exist)
|
||||||
{
|
{
|
||||||
throw new KeyNotFoundException($"Resource with handle {handle} not found.");
|
return Result.CreateRef(ref Unsafe.NullRef<ResourceRecord>(), ResultStatus.NotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ref info;
|
return Result.CreateRef(ref info, ResultStatus.Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref ResourceRecord GetResourceRecord(Handle<GPUResource> handle, out bool exist)
|
public ref ResourceRecord GetResourceRecord(Handle<GPUResource> handle, out bool exist)
|
||||||
@@ -190,23 +191,30 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
|||||||
return ref _resources.GetElementReferenceAt(handle.id, handle.generation, out exist);
|
return ref _resources.GetElementReferenceAt(handle.id, handle.generation, out exist);
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe SharedPtr<ID3D12Resource> GetResource(Handle<GPUResource> handle)
|
public SharedPtr<ID3D12Resource> GetResource(Handle<GPUResource> handle)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
ref var info = ref GetResourceRecord(handle);
|
var r = GetResourceRecord(handle);
|
||||||
if (!info.Allocated)
|
if (r.Status != ResultStatus.Success)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return info.ResourcePtr;
|
return r.Value.ResourcePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceState GetResourceState(Handle<GPUResource> handle)
|
public Result<ResourceState, ResultStatus> GetResourceState(Handle<GPUResource> handle)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
return GetResourceRecord(handle).state;
|
|
||||||
|
var r = GetResourceRecord(handle);
|
||||||
|
if (r.Status != ResultStatus.Success)
|
||||||
|
{
|
||||||
|
return Result.Create(ResourceState.Common, r.Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Create(r.Value.state, ResultStatus.Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetResourceState(Handle<GPUResource> handle, ResourceState state)
|
public void SetResourceState(Handle<GPUResource> handle, ResourceState state)
|
||||||
@@ -222,10 +230,18 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
|||||||
info.state = state;
|
info.state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceDesc GetResourceDescription(Handle<GPUResource> handle)
|
public Result<ResourceDesc, ResultStatus> GetResourceDescription(Handle<GPUResource> handle)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
return GetResourceRecord(handle).desc;
|
|
||||||
|
var r = GetResourceRecord(handle);
|
||||||
|
|
||||||
|
if (r.Status != ResultStatus.Success)
|
||||||
|
{
|
||||||
|
return Result.Create(default(ResourceDesc), r.Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Create(r.Value.desc, ResultStatus.Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result<uint, ResultStatus> GetBindlessIndex(Handle<GPUResource> handle)
|
public Result<uint, ResultStatus> GetBindlessIndex(Handle<GPUResource> handle)
|
||||||
@@ -238,7 +254,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
|||||||
return Result.Create(0u, ResultStatus.NotFound);
|
return Result.Create(0u, ResultStatus.NotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.Create((uint)info.viewGroup.srv.value, ResultStatus.NotFound);
|
return Result.Create((uint)info.viewGroup.srv.value, ResultStatus.Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? GetResourceName(Handle<GPUResource> handle)
|
public string? GetResourceName(Handle<GPUResource> handle)
|
||||||
|
|||||||
@@ -186,16 +186,11 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
|||||||
_resourceDatabase.ReleaseResource(_backBuffers[i].AsResource());
|
_resourceDatabase.ReleaseResource(_backBuffers[i].AsResource());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize the swap chain
|
ThrowIfFailed(_swapChain.Get()->ResizeBuffers(BufferCount, width, height, DXGI_FORMAT_B8G8R8A8_UNORM, (uint)DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING));
|
||||||
if (_swapChain.Get()->ResizeBuffers(BufferCount, width, height, DXGI_FORMAT_B8G8R8A8_UNORM, (uint)DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING).FAILED)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Failed to resize swap chain buffers.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Width = width;
|
Width = width;
|
||||||
Height = height;
|
Height = height;
|
||||||
|
|
||||||
// Recreate back buffers
|
|
||||||
CreateBackBuffers();
|
CreateBackBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,19 +5,15 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
<LangVersion>preview</LangVersion>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<IsAotCompatible>True</IsAotCompatible>
|
|
||||||
<IsTrimmable>True</IsTrimmable>
|
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<IsAotCompatible>True</IsAotCompatible>
|
<IsAotCompatible>True</IsAotCompatible>
|
||||||
<IsTrimmable>True</IsTrimmable>
|
<IsTrimmable>True</IsTrimmable>
|
||||||
<DebugType>embedded</DebugType>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -263,8 +263,8 @@ public struct RectDesc
|
|||||||
public struct SubResourceData
|
public struct SubResourceData
|
||||||
{
|
{
|
||||||
public unsafe void* pData;
|
public unsafe void* pData;
|
||||||
public nint rowPitch;
|
public uint rowPitch;
|
||||||
public nint slicePitch;
|
public uint slicePitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct PassRenderTargetDesc
|
public struct PassRenderTargetDesc
|
||||||
@@ -303,7 +303,7 @@ public struct PassDepthStencilDesc
|
|||||||
|
|
||||||
public struct BarrierDesc
|
public struct BarrierDesc
|
||||||
{
|
{
|
||||||
public Handle<GraphicsBuffer> Resource
|
public Handle<GPUResource> Resource
|
||||||
{
|
{
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
@@ -681,6 +681,24 @@ public struct BufferDesc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct CommandError
|
||||||
|
{
|
||||||
|
public int CommandIndex
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CommandName
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResultStatus Status
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Swap chain description
|
/// Swap chain description
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public interface ICommandBuffer : IDisposable
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ends recording commands and prepares for submission
|
/// Ends recording commands and prepares for submission
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void End();
|
Result End();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the viewport for rendering
|
/// Sets the viewport for rendering
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public interface IResourceDatabase : IDisposable
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">The handle that uniquely identifies the resource whose state is to be retrieved.</param>
|
/// <param name="handle">The handle that uniquely identifies the resource whose state is to be retrieved.</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>
|
||||||
ResourceState GetResourceState(Handle<GPUResource> handle);
|
Result<ResourceState, ResultStatus> 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.
|
||||||
@@ -53,7 +53,7 @@ public interface IResourceDatabase : IDisposable
|
|||||||
/// </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>
|
||||||
ResourceDesc GetResourceDescription(Handle<GPUResource> handle);
|
Result<ResourceDesc, ResultStatus> 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.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ namespace Ghost.Graphics.RHI;
|
|||||||
|
|
||||||
internal static class RHIUtility
|
internal static class RHIUtility
|
||||||
{
|
{
|
||||||
public static int GetBytesPerPixel(this TextureFormat format)
|
public static uint GetBytesPerPixel(this TextureFormat format)
|
||||||
{
|
{
|
||||||
return format switch
|
return format switch
|
||||||
{
|
{
|
||||||
@@ -16,12 +16,17 @@ internal static class RHIUtility
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void GetSurfaceInfo(this TextureFormat format, int width, int height, out int rowPitch, out int slicePitch, out int rowCount)
|
public static uint GetTotalBytes(this TextureDesc desc)
|
||||||
|
{
|
||||||
|
return desc.Format.GetBytesPerPixel() * desc.Width * desc.Height * desc.Slice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void GetSurfaceInfo(this TextureFormat format, uint width, uint height, out uint rowPitch, out uint slicePitch, out uint rowCount)
|
||||||
{
|
{
|
||||||
var bc = false;
|
var bc = false;
|
||||||
var packed = false;
|
var packed = false;
|
||||||
var planar = false;
|
var planar = false;
|
||||||
var bpe = 0;
|
var bpe = 0u;
|
||||||
|
|
||||||
//switch (Format)
|
//switch (Format)
|
||||||
//{
|
//{
|
||||||
@@ -86,31 +91,33 @@ internal static class RHIUtility
|
|||||||
|
|
||||||
if (bc)
|
if (bc)
|
||||||
{
|
{
|
||||||
var numBlocksWide = 0;
|
var numBlocksWide = 0u;
|
||||||
if (width > 0)
|
if (width > 0)
|
||||||
{
|
{
|
||||||
numBlocksWide = Math.Max(1, (width + 3) / 4);
|
numBlocksWide = Math.Max(1u, (width + 3) / 4u);
|
||||||
}
|
}
|
||||||
var numBlocksHigh = 0;
|
|
||||||
|
var numBlocksHigh = 0u;
|
||||||
if (height > 0)
|
if (height > 0)
|
||||||
{
|
{
|
||||||
numBlocksHigh = Math.Max(1, (height + 3) / 4);
|
numBlocksHigh = Math.Max(1u, (height + 3) / 4u);
|
||||||
}
|
}
|
||||||
|
|
||||||
rowPitch = numBlocksWide * bpe;
|
rowPitch = numBlocksWide * bpe;
|
||||||
rowCount = numBlocksHigh;
|
rowCount = numBlocksHigh;
|
||||||
slicePitch = rowPitch * numBlocksHigh;
|
slicePitch = rowPitch * numBlocksHigh;
|
||||||
}
|
}
|
||||||
else if (packed)
|
else if (packed)
|
||||||
{
|
{
|
||||||
rowPitch = ((width + 1) >> 1) * bpe;
|
rowPitch = ((width + 1u) >> 1) * bpe;
|
||||||
rowCount = height;
|
rowCount = height;
|
||||||
slicePitch = rowPitch * height;
|
slicePitch = rowPitch * height;
|
||||||
}
|
}
|
||||||
else if (planar)
|
else if (planar)
|
||||||
{
|
{
|
||||||
rowPitch = ((width + 1) >> 1) * bpe;
|
rowPitch = ((width + 1u) >> 1) * bpe;
|
||||||
slicePitch = (rowPitch * height) + ((rowPitch * height + 1) >> 1);
|
slicePitch = (rowPitch * height) + ((rowPitch * height + 1) >> 1);
|
||||||
rowCount = (int)(height + ((height + 1u) >> 1));
|
rowCount = height + ((height + 1u) >> 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -103,8 +103,7 @@ internal class MeshRenderPass : IRenderPass
|
|||||||
Usage = TextureUsage.ShaderResource,
|
Usage = TextureUsage.ShaderResource,
|
||||||
};
|
};
|
||||||
|
|
||||||
_textures[i] = ctx.CreateTexture(ref desc);
|
_textures[i] = ctx.CreateTexture(ref desc, imageData.AsSpan());
|
||||||
ctx.UploadTexture(_textures[i], imageData.AsSpan());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var samplerDesc = new SamplerDesc
|
var samplerDesc = new SamplerDesc
|
||||||
|
|||||||
Reference in New Issue
Block a user