Add sampler support and refactor resource handling
Enhanced shader and resource systems with `Sampler` support, including updates to `ShaderPropertyType`, HLSL code, and resource management. Refactored `Result` structs for better type safety and added new enums for texture and comparison settings. Improved `MeshRenderPass` to dynamically load textures and samplers. Updated SDL compiler and token lexicon for `Sampler` handling. Embedded debug info in project files and streamlined resource state tracking.
This commit is contained in:
@@ -16,6 +16,7 @@ public enum ShaderPropertyType
|
|||||||
Bool, Bool2, Bool3, Bool4,
|
Bool, Bool2, Bool3, Bool4,
|
||||||
Texture2D, Texture3D, TextureCube,
|
Texture2D, Texture3D, TextureCube,
|
||||||
Texture2DArray, TextureCubeArray,
|
Texture2DArray, TextureCubeArray,
|
||||||
|
Sampler
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ShaderEntryPoint
|
public struct ShaderEntryPoint
|
||||||
@@ -133,6 +134,7 @@ public static class ShaderDescriptorExtensions
|
|||||||
ShaderPropertyType.TextureCube => 4,
|
ShaderPropertyType.TextureCube => 4,
|
||||||
ShaderPropertyType.Texture2DArray => 4,
|
ShaderPropertyType.Texture2DArray => 4,
|
||||||
ShaderPropertyType.TextureCubeArray => 4,
|
ShaderPropertyType.TextureCubeArray => 4,
|
||||||
|
ShaderPropertyType.Sampler => 4,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Ghost.Core;
|
namespace Ghost.Core;
|
||||||
|
|
||||||
public readonly struct Result
|
public readonly struct Result
|
||||||
@@ -39,11 +37,13 @@ public readonly struct Result
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Result<T, S> Create<T, S>(T value, S status)
|
public static Result<T, S> Create<T, S>(T value, S status)
|
||||||
|
where S : Enum
|
||||||
{
|
{
|
||||||
return new Result<T, S>(value, status);
|
return new Result<T, S>(value, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RefResult<T, S> CreateRef<T, S>(ref T value, S status)
|
public static RefResult<T, S> CreateRef<T, S>(ref T value, S status)
|
||||||
|
where S : Enum
|
||||||
{
|
{
|
||||||
return new RefResult<T, S>(ref value, status);
|
return new RefResult<T, S>(ref value, status);
|
||||||
}
|
}
|
||||||
@@ -105,6 +105,7 @@ public enum ResultStatus : byte
|
|||||||
}
|
}
|
||||||
|
|
||||||
public readonly struct Result<T, S>
|
public readonly struct Result<T, S>
|
||||||
|
where S : Enum
|
||||||
{
|
{
|
||||||
private readonly T _value;
|
private readonly T _value;
|
||||||
private readonly S _status;
|
private readonly S _status;
|
||||||
@@ -127,6 +128,7 @@ public readonly struct Result<T, S>
|
|||||||
}
|
}
|
||||||
|
|
||||||
public readonly ref struct RefResult<T, S>
|
public readonly ref struct RefResult<T, S>
|
||||||
|
where S : Enum
|
||||||
{
|
{
|
||||||
private readonly ref T _value;
|
private readonly ref T _value;
|
||||||
private readonly S _status;
|
private readonly S _status;
|
||||||
@@ -173,6 +175,23 @@ public static class ResultExtensions
|
|||||||
return result.IsSuccess ? result.Value : defaultValue;
|
return result.IsSuccess ? result.Value : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static T GetValueOrThrow<T, S>(this Result<T, S> result, S expect)
|
||||||
|
where S : Enum
|
||||||
|
{
|
||||||
|
if (result.Status?.Equals(expect) ?? false)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Operation failed: expected status {expect}, but got {result.Status}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T? GetValueOrDefault<T, S>(this Result<T, S> result, S expect, T? defaultValue = default)
|
||||||
|
where S : Enum
|
||||||
|
{
|
||||||
|
return (result.Status?.Equals(expect) ?? false) ? defaultValue : result.Value;
|
||||||
|
}
|
||||||
|
|
||||||
public static Result OnSuccess(this Result result, Action action)
|
public static Result OnSuccess(this Result result, Action action)
|
||||||
{
|
{
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ public static partial class AssetDatabase
|
|||||||
var metaFileResult = GetMetaFilePath(assetPath);
|
var metaFileResult = GetMetaFilePath(assetPath);
|
||||||
if (!metaFileResult.IsSuccess)
|
if (!metaFileResult.IsSuccess)
|
||||||
{
|
{
|
||||||
return metaFileResult;
|
return Result.Failure(metaFileResult.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (File.Exists(metaFileResult.Value))
|
if (File.Exists(metaFileResult.Value))
|
||||||
|
|||||||
@@ -87,10 +87,22 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" />
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
|
<DebugType>embedded</DebugType>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" />
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" />
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
|
<DebugType>embedded</DebugType>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" />
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
</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>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"profiles": {
|
"profiles": {
|
||||||
"Ghost.Graphics.Test (Package)": {
|
"Ghost.Graphics.Test (Package)": {
|
||||||
"commandName": "MsixPackage",
|
"commandName": "MsixPackage",
|
||||||
"nativeDebugging": false
|
"nativeDebugging": true
|
||||||
},
|
},
|
||||||
"Ghost.Graphics.Test (Unpackaged)": {
|
"Ghost.Graphics.Test (Unpackaged)": {
|
||||||
"commandName": "Project"
|
"commandName": "Project"
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ public sealed partial class GraphicsTestWindow : Window
|
|||||||
{
|
{
|
||||||
Width = (uint)AppWindow.Size.Width,
|
Width = (uint)AppWindow.Size.Width,
|
||||||
Height = (uint)AppWindow.Size.Height,
|
Height = (uint)AppWindow.Size.Height,
|
||||||
|
BufferCount = 2,
|
||||||
|
Format = TextureFormat.B8G8R8A8_UNorm,
|
||||||
Target = SwapChainTarget.FromCompositionSurface(Panel)
|
Target = SwapChainTarget.FromCompositionSurface(Panel)
|
||||||
});
|
});
|
||||||
_renderer.SetSwapChain(_swapChain);
|
_renderer.SetSwapChain(_swapChain);
|
||||||
|
|||||||
@@ -106,34 +106,35 @@ public struct Material : IResourceReleasable, IHandleType
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly unsafe Result<ResultStatus> SetPropertyCache<T>(ref readonly T data)
|
public readonly unsafe ResultStatus SetPropertyCache<T>(ref readonly T data)
|
||||||
where T : unmanaged
|
where T : unmanaged
|
||||||
{
|
{
|
||||||
if (sizeof(T) != _cBufferCache.Size)
|
if (sizeof(T) != _cBufferCache.Size)
|
||||||
{
|
{
|
||||||
return new Result<ResultStatus>(false, ResultStatus.InvalidArgument);
|
return ResultStatus.InvalidArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
Unsafe.WriteUnaligned(_cBufferCache.CpuData.GetUnsafePtr(), data);
|
Unsafe.WriteUnaligned(_cBufferCache.CpuData.GetUnsafePtr(), data);
|
||||||
return Result.Success(ResultStatus.Success);
|
return ResultStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly unsafe Result<ResultStatus> SetRawPropertyCache(ReadOnlySpan<byte> data)
|
public readonly unsafe ResultStatus SetRawPropertyCache(ReadOnlySpan<byte> data)
|
||||||
{
|
{
|
||||||
if (data.Length != _cBufferCache.Size)
|
if (data.Length != _cBufferCache.Size)
|
||||||
{
|
{
|
||||||
return new Result<ResultStatus>(false, ResultStatus.InvalidArgument);
|
return ResultStatus.InvalidArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
Unsafe.WriteUnaligned(_cBufferCache.CpuData.GetUnsafePtr(), data);
|
Unsafe.WriteUnaligned(_cBufferCache.CpuData.GetUnsafePtr(), data);
|
||||||
return Result.Success(ResultStatus.Success);
|
return ResultStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public readonly void UploadData(ICommandBuffer cmb)
|
public readonly void UploadData(ICommandBuffer cmb)
|
||||||
{
|
{
|
||||||
cmb.UploadBuffer(_cBufferCache.GpuResource, _cBufferCache.CpuData.AsSpan());
|
cmb.UploadBuffer(_cBufferCache.GpuResource, _cBufferCache.CpuData.AsSpan());
|
||||||
|
cmb.ResourceBarrier(_cBufferCache.GpuResource.AsResource(), ResourceState.VertexAndConstantBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using Misaki.HighPerformance.Mathematics;
|
|||||||
|
|
||||||
namespace Ghost.Graphics.Core;
|
namespace Ghost.Graphics.Core;
|
||||||
|
|
||||||
public unsafe readonly ref struct RenderingContext
|
public readonly unsafe ref struct RenderingContext
|
||||||
{
|
{
|
||||||
private readonly IGraphicsEngine _engine;
|
private readonly IGraphicsEngine _engine;
|
||||||
private readonly ICommandBuffer _directCmd;
|
private readonly ICommandBuffer _directCmd;
|
||||||
@@ -144,8 +144,8 @@ public unsafe readonly ref struct RenderingContext
|
|||||||
localToWorld = localToWorld,
|
localToWorld = localToWorld,
|
||||||
worldBoundsMin = meshData.BoundingBox.Min,
|
worldBoundsMin = meshData.BoundingBox.Min,
|
||||||
worldBoundsMax = meshData.BoundingBox.Max,
|
worldBoundsMax = meshData.BoundingBox.Max,
|
||||||
vertexBuffer = (uint)_engine.ResourceDatabase.GetBindlessIndex(meshData.VertexBuffer.AsResource()),
|
vertexBuffer = _engine.ResourceDatabase.GetBindlessIndex(meshData.VertexBuffer.AsResource()).GetValueOrThrow(ResultStatus.Success),
|
||||||
indexBuffer = (uint)_engine.ResourceDatabase.GetBindlessIndex(meshData.IndexBuffer.AsResource()),
|
indexBuffer = _engine.ResourceDatabase.GetBindlessIndex(meshData.IndexBuffer.AsResource()).GetValueOrThrow(ResultStatus.Success),
|
||||||
};
|
};
|
||||||
|
|
||||||
var bufferHandle = meshData.ObjectDataBuffer.AsResource();
|
var bufferHandle = meshData.ObjectDataBuffer.AsResource();
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ public readonly struct GPUResource : IHandleType;
|
|||||||
public readonly struct Texture : IHandleType;
|
public readonly struct Texture : IHandleType;
|
||||||
public readonly struct GraphicsBuffer : IHandleType;
|
public readonly struct GraphicsBuffer : IHandleType;
|
||||||
|
|
||||||
|
public readonly struct Sampler : IIdentifierType;
|
||||||
|
|
||||||
public static class ResourceHandleExtensions
|
public static class ResourceHandleExtensions
|
||||||
{
|
{
|
||||||
public static Handle<GPUResource> AsResource(this Handle<Texture> texture)
|
public static Handle<GPUResource> AsResource(this Handle<Texture> texture)
|
||||||
|
|||||||
@@ -234,6 +234,12 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
resourceRecord.state = stateAfter;
|
resourceRecord.state = stateAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ResourceBarrier(Handle<GPUResource> resource, ResourceState stateAfter)
|
||||||
|
{
|
||||||
|
var stateBefore = _resourceDatabase.GetResourceState(resource);
|
||||||
|
ResourceBarrier(resource, stateBefore, stateAfter);
|
||||||
|
}
|
||||||
|
|
||||||
public void SetRenderTargets(ReadOnlySpan<Handle<Texture>> renderTargets, Handle<Texture> depthTarget)
|
public void SetRenderTargets(ReadOnlySpan<Handle<Texture>> renderTargets, Handle<Texture> depthTarget)
|
||||||
{
|
{
|
||||||
ThrowIfDisposed();
|
ThrowIfDisposed();
|
||||||
@@ -511,6 +517,8 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
|||||||
var pResource = _resourceDatabase.GetResource(buffer.AsResource());
|
var pResource = _resourceDatabase.GetResource(buffer.AsResource());
|
||||||
|
|
||||||
_commandList.Get()->CopyBufferRegion(pResource, 0, uploadResource, 0, sizeInBytes);
|
_commandList.Get()->CopyBufferRegion(pResource, 0, uploadResource, 0, sizeInBytes);
|
||||||
|
// D3D12 transition resource to COPY_DEST when copying
|
||||||
|
_resourceDatabase.SetResourceState(buffer.AsResource(), ResourceState.CopyDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UploadTexture(Handle<Texture> texture, ReadOnlySpan<SubResourceData> subresources)
|
public void UploadTexture(Handle<Texture> texture, ReadOnlySpan<SubResourceData> subresources)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Graphics.D3D12.Utilities;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using TerraFX.Interop.DirectX;
|
using TerraFX.Interop.DirectX;
|
||||||
|
|
||||||
@@ -34,7 +33,7 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
|
|
||||||
#region RTV Methods
|
#region RTV Methods
|
||||||
|
|
||||||
public Identifier<RTVDesc> AllocateRTV(bool dynamic = false)
|
public Identifier<RTVDescriptor> AllocateRTV(bool dynamic = false)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -44,10 +43,10 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
throw new InvalidOperationException("Failed to allocate RTV descriptor");
|
throw new InvalidOperationException("Failed to allocate RTV descriptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Identifier<RTVDesc>(index);
|
return new Identifier<RTVDescriptor>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier<RTVDesc>[] AllocateRTVs(int count, bool dynamic = false)
|
public Identifier<RTVDescriptor>[] AllocateRTVs(int count, bool dynamic = false)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -57,32 +56,32 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
throw new InvalidOperationException($"Failed to allocate {count} RTV descriptors");
|
throw new InvalidOperationException($"Failed to allocate {count} RTV descriptors");
|
||||||
}
|
}
|
||||||
|
|
||||||
var descriptors = new Identifier<RTVDesc>[count];
|
var descriptors = new Identifier<RTVDescriptor>[count];
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var index = baseIndex + i;
|
var index = baseIndex + i;
|
||||||
descriptors[i] = new Identifier<RTVDesc>(index);
|
descriptors[i] = new Identifier<RTVDescriptor>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptors;
|
return descriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<RTVDesc> descriptor)
|
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<RTVDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
return _rtvHeap.GetCpuHandle(descriptor.value);
|
return _rtvHeap.GetCpuHandle(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void Release(Identifier<RTVDesc> descriptor)
|
public void Release(Identifier<RTVDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
_rtvHeap.ReleaseDescriptor(descriptor.value);
|
_rtvHeap.ReleaseDescriptor(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void Release(ReadOnlySpan<Identifier<RTVDesc>> descriptors)
|
public void Release(ReadOnlySpan<Identifier<RTVDescriptor>> descriptors)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -93,14 +92,14 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void MakePersistent(Identifier<RTVDesc> descriptor)
|
public void MakePersistent(Identifier<RTVDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
_rtvHeap.CopyToPersistentHeap(descriptor.value);
|
_rtvHeap.CopyToPersistentHeap(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void MakePersistent(ReadOnlySpan<Identifier<RTVDesc>> descriptors)
|
public void MakePersistent(ReadOnlySpan<Identifier<RTVDescriptor>> descriptors)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
foreach (var descriptor in descriptors)
|
foreach (var descriptor in descriptors)
|
||||||
@@ -120,7 +119,7 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
|
|
||||||
#region DSV Methods
|
#region DSV Methods
|
||||||
|
|
||||||
public Identifier<DSVDesc> AllocateDSV(bool dynamic = false)
|
public Identifier<DSVDescriptor> AllocateDSV(bool dynamic = false)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -130,10 +129,10 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
throw new InvalidOperationException("Failed to allocate DSV descriptor");
|
throw new InvalidOperationException("Failed to allocate DSV descriptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Identifier<DSVDesc>(index);
|
return new Identifier<DSVDescriptor>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier<DSVDesc>[] AllocateDSVs(int count, bool dynamic = false)
|
public Identifier<DSVDescriptor>[] AllocateDSVs(int count, bool dynamic = false)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -143,29 +142,29 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
throw new InvalidOperationException($"Failed to allocate {count} DSV descriptors");
|
throw new InvalidOperationException($"Failed to allocate {count} DSV descriptors");
|
||||||
}
|
}
|
||||||
|
|
||||||
var descriptors = new Identifier<DSVDesc>[count];
|
var descriptors = new Identifier<DSVDescriptor>[count];
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var index = baseIndex + i;
|
var index = baseIndex + i;
|
||||||
descriptors[i] = new Identifier<DSVDesc>(index);
|
descriptors[i] = new Identifier<DSVDescriptor>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptors;
|
return descriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<DSVDesc> descriptor)
|
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<DSVDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
return _dsvHeap.GetCpuHandle(descriptor.value);
|
return _dsvHeap.GetCpuHandle(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Release(Identifier<DSVDesc> descriptor)
|
public void Release(Identifier<DSVDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
_dsvHeap.ReleaseDescriptor(descriptor.value);
|
_dsvHeap.ReleaseDescriptor(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Release(ReadOnlySpan<Identifier<DSVDesc>> descriptors)
|
public void Release(ReadOnlySpan<Identifier<DSVDescriptor>> descriptors)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -176,14 +175,14 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void MakePersistent(Identifier<DSVDesc> descriptor)
|
public void MakePersistent(Identifier<DSVDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
_dsvHeap.CopyToPersistentHeap(descriptor.value);
|
_dsvHeap.CopyToPersistentHeap(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void MakePersistent(ReadOnlySpan<Identifier<DSVDesc>> descriptors)
|
public void MakePersistent(ReadOnlySpan<Identifier<DSVDescriptor>> descriptors)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
foreach (var descriptor in descriptors)
|
foreach (var descriptor in descriptors)
|
||||||
@@ -203,7 +202,7 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
|
|
||||||
#region CBV_SRV_UAV Methods
|
#region CBV_SRV_UAV Methods
|
||||||
|
|
||||||
public Identifier<CbvSrvUavDesc> AllocateCbvSrvUav(bool dynamic = false)
|
public Identifier<CbvSrvUavDescriptor> AllocateCbvSrvUav(bool dynamic = false)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -214,10 +213,10 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_cbvSrvUavHeap.CopyToShaderVisibleHeap(index);
|
_cbvSrvUavHeap.CopyToShaderVisibleHeap(index);
|
||||||
return new Identifier<CbvSrvUavDesc>(index);
|
return new Identifier<CbvSrvUavDescriptor>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier<CbvSrvUavDesc>[] AllocateSRVs(int count, bool dynamic = false)
|
public Identifier<CbvSrvUavDescriptor>[] AllocateSRVs(int count, bool dynamic = false)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -227,42 +226,42 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
throw new InvalidOperationException($"Failed to allocate {count} CBV/SRV/UAV descriptors");
|
throw new InvalidOperationException($"Failed to allocate {count} CBV/SRV/UAV descriptors");
|
||||||
}
|
}
|
||||||
|
|
||||||
var descriptors = new Identifier<CbvSrvUavDesc>[count];
|
var descriptors = new Identifier<CbvSrvUavDescriptor>[count];
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var index = baseIndex + i;
|
var index = baseIndex + i;
|
||||||
descriptors[i] = new Identifier<CbvSrvUavDesc>(index);
|
descriptors[i] = new Identifier<CbvSrvUavDescriptor>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cbvSrvUavHeap.CopyToShaderVisibleHeap(baseIndex, count);
|
_cbvSrvUavHeap.CopyToShaderVisibleHeap(baseIndex, count);
|
||||||
return descriptors;
|
return descriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<CbvSrvUavDesc> descriptor)
|
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<CbvSrvUavDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
return _cbvSrvUavHeap.GetCpuHandle(descriptor.value);
|
return _cbvSrvUavHeap.GetCpuHandle(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandleShaderVisible(Identifier<CbvSrvUavDesc> descriptor)
|
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandleShaderVisible(Identifier<CbvSrvUavDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
return _cbvSrvUavHeap.GetCpuHandleShaderVisible(descriptor.value);
|
return _cbvSrvUavHeap.GetCpuHandleShaderVisible(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(Identifier<CbvSrvUavDesc> descriptor)
|
public D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(Identifier<CbvSrvUavDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
return _cbvSrvUavHeap.GetGpuHandle(descriptor.value);
|
return _cbvSrvUavHeap.GetGpuHandle(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Release(Identifier<CbvSrvUavDesc> descriptor)
|
public void Release(Identifier<CbvSrvUavDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
_cbvSrvUavHeap.ReleaseDescriptor(descriptor.value);
|
_cbvSrvUavHeap.ReleaseDescriptor(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Release(ReadOnlySpan<Identifier<CbvSrvUavDesc>> descriptors)
|
public void Release(ReadOnlySpan<Identifier<CbvSrvUavDescriptor>> descriptors)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -273,14 +272,14 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void MakePersistent(Identifier<CbvSrvUavDesc> descriptor)
|
public void MakePersistent(Identifier<CbvSrvUavDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
_cbvSrvUavHeap.CopyToPersistentHeap(descriptor.value);
|
_cbvSrvUavHeap.CopyToPersistentHeap(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void MakePersistent(ReadOnlySpan<Identifier<CbvSrvUavDesc>> descriptors)
|
public void MakePersistent(ReadOnlySpan<Identifier<CbvSrvUavDescriptor>> descriptors)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
foreach (var descriptor in descriptors)
|
foreach (var descriptor in descriptors)
|
||||||
@@ -300,7 +299,7 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
|
|
||||||
#region Sampler Methods
|
#region Sampler Methods
|
||||||
|
|
||||||
public Identifier<SamplerDesc> AllocateSampler()
|
public Identifier<SamplerDescriptor> AllocateSampler()
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -311,10 +310,10 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
_samplerHeap.CopyToShaderVisibleHeap(index);
|
_samplerHeap.CopyToShaderVisibleHeap(index);
|
||||||
return new Identifier<SamplerDesc>(index);
|
return new Identifier<SamplerDescriptor>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Identifier<SamplerDesc>[] AllocateSamplers(int count)
|
public Identifier<SamplerDescriptor>[] AllocateSamplers(int count)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
@@ -324,42 +323,42 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
|||||||
throw new InvalidOperationException($"Failed to allocate {count} Sampler descriptors");
|
throw new InvalidOperationException($"Failed to allocate {count} Sampler descriptors");
|
||||||
}
|
}
|
||||||
|
|
||||||
var descriptors = new Identifier<SamplerDesc>[count];
|
var descriptors = new Identifier<SamplerDescriptor>[count];
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var index = baseIndex + i;
|
var index = baseIndex + i;
|
||||||
descriptors[i] = new Identifier<SamplerDesc>(index);
|
descriptors[i] = new Identifier<SamplerDescriptor>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
_samplerHeap.CopyToShaderVisibleHeap(baseIndex, count);
|
_samplerHeap.CopyToShaderVisibleHeap(baseIndex, count);
|
||||||
return descriptors;
|
return descriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<SamplerDesc> descriptor)
|
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<SamplerDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
return _samplerHeap.GetCpuHandle(descriptor.value);
|
return _samplerHeap.GetCpuHandle(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandleShaderVisible(Identifier<SamplerDesc> descriptor)
|
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandleShaderVisible(Identifier<SamplerDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
return _samplerHeap.GetCpuHandleShaderVisible(descriptor.value);
|
return _samplerHeap.GetCpuHandleShaderVisible(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(Identifier<SamplerDesc> descriptor)
|
public D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(Identifier<SamplerDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
return _samplerHeap.GetGpuHandle(descriptor.value);
|
return _samplerHeap.GetGpuHandle(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Release(Identifier<SamplerDesc> descriptor)
|
public void Release(Identifier<SamplerDescriptor> descriptor)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
_samplerHeap.ReleaseDescriptor(descriptor.value);
|
_samplerHeap.ReleaseDescriptor(descriptor.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Release(ReadOnlySpan<Identifier<SamplerDesc>> descriptors)
|
public void Release(ReadOnlySpan<Identifier<SamplerDescriptor>> descriptors)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using TerraFX.Interop.DirectX;
|
|||||||
|
|
||||||
using static TerraFX.Aliases.D3D12_Alias;
|
using static TerraFX.Aliases.D3D12_Alias;
|
||||||
|
|
||||||
namespace Ghost.Graphics.D3D12.Utilities;
|
namespace Ghost.Graphics.D3D12;
|
||||||
|
|
||||||
internal unsafe struct D3D12DescriptorHeap : IDisposable
|
internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||||
{
|
{
|
||||||
@@ -2,6 +2,7 @@ using Ghost.Core;
|
|||||||
using Ghost.Core.Graphics;
|
using Ghost.Core.Graphics;
|
||||||
using Ghost.Core.Utilities;
|
using Ghost.Core.Utilities;
|
||||||
using Ghost.Graphics.Core;
|
using Ghost.Graphics.Core;
|
||||||
|
using Ghost.Graphics.D3D12.Utilities;
|
||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Misaki.HighPerformance.LowLevel;
|
using Misaki.HighPerformance.LowLevel;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
@@ -851,6 +852,35 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
|||||||
return CreateBuffer(in desc, isTemp);
|
return CreateBuffer(in desc, isTemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Identifier<Sampler> CreateSampler(ref readonly SamplerDesc desc)
|
||||||
|
{
|
||||||
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
if (_resourceDatabase.TryGetSampler(in desc, out var id))
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
var samplerDesc = new D3D12_SAMPLER_DESC
|
||||||
|
{
|
||||||
|
Filter = desc.FilterMode.ToD3D12Filter(),
|
||||||
|
AddressU = desc.AddressU.ToD3D12TextureAddressMode(),
|
||||||
|
AddressV = desc.AddressV.ToD3D12TextureAddressMode(),
|
||||||
|
AddressW = desc.AddressW.ToD3D12TextureAddressMode(),
|
||||||
|
MipLODBias = desc.MipLODBias,
|
||||||
|
MaxAnisotropy = desc.MaxAnisotropy,
|
||||||
|
ComparisonFunc = desc.ComparisonFunc.ToD3D12ComparisonFunc(),
|
||||||
|
MinLOD = desc.MinLOD,
|
||||||
|
MaxLOD = desc.MaxLOD,
|
||||||
|
};
|
||||||
|
|
||||||
|
var samplerDescriptor = _descriptorAllocator.AllocateSampler();
|
||||||
|
var cpuHandle = _descriptorAllocator.GetCpuHandleShaderVisible(samplerDescriptor);
|
||||||
|
_device.NativeDevice.Get()->CreateSampler(&samplerDesc, cpuHandle);
|
||||||
|
|
||||||
|
return _resourceDatabase.CreateSampler(in desc, samplerDescriptor.value);
|
||||||
|
}
|
||||||
|
|
||||||
public Handle<Mesh> CreateMesh(UnsafeList<Vertex> vertices, UnsafeList<uint> indices)
|
public Handle<Mesh> CreateMesh(UnsafeList<Vertex> vertices, UnsafeList<uint> indices)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|||||||
@@ -97,26 +97,30 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
|||||||
private readonly Dictionary<Handle<GPUResource>, string> _resourceName;
|
private readonly Dictionary<Handle<GPUResource>, string> _resourceName;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
private UnsafeHashMap<SamplerDesc, Identifier<Sampler>> _samplers;
|
||||||
private UnsafeSlotMap<Mesh> _meshes;
|
private UnsafeSlotMap<Mesh> _meshes;
|
||||||
private UnsafeSlotMap<Material> _materials;
|
private UnsafeSlotMap<Material> _materials;
|
||||||
private readonly DynamicArray<Shader?> _shaders; // NOTE: We use a simple list since shader is not frequently added/removed. This can save 4 bytes for each ecs component.
|
private readonly DynamicArray<Shader?> _shaders; // NOTE: We use a simple list since shader is not frequently added/removed. This can save 4 bytes for each ecs component.
|
||||||
private readonly Dictionary<ShaderPassKey, ShaderPass> _shaderPasses; // NOTE: The reason we use Dictionary here is that ShaderPassKey is a presistence identifier across multiple application sessions.
|
private readonly Dictionary<ShaderPassKey, ShaderPass> _shaderPasses; // NOTE: The reason we use Dictionary here is that ShaderPassKey is a presistence identifier across multiple application sessions.
|
||||||
|
|
||||||
|
private int _lastSamplerId;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
public D3D12ResourceDatabase(D3D12DescriptorAllocator descriptorAllocator)
|
public D3D12ResourceDatabase(D3D12DescriptorAllocator descriptorAllocator)
|
||||||
{
|
{
|
||||||
|
_descriptorAllocator = descriptorAllocator;
|
||||||
|
|
||||||
_resources = new UnsafeSlotMap<ResourceRecord>(64, Allocator.Persistent, AllocationOption.Clear);
|
_resources = new UnsafeSlotMap<ResourceRecord>(64, Allocator.Persistent, AllocationOption.Clear);
|
||||||
#if DEBUG || GHOST_EDITOR
|
#if DEBUG || GHOST_EDITOR
|
||||||
_resourceName = new Dictionary<Handle<GPUResource>, string>(64);
|
_resourceName = new Dictionary<Handle<GPUResource>, string>(64);
|
||||||
#endif
|
#endif
|
||||||
|
_samplers = new UnsafeHashMap<SamplerDesc, Identifier<Sampler>>(32, Allocator.Persistent);
|
||||||
_meshes = new UnsafeSlotMap<Mesh>(64, Allocator.Persistent, AllocationOption.Clear);
|
_meshes = new UnsafeSlotMap<Mesh>(64, Allocator.Persistent, AllocationOption.Clear);
|
||||||
_materials = new UnsafeSlotMap<Material>(16, Allocator.Persistent, AllocationOption.Clear);
|
_materials = new UnsafeSlotMap<Material>(16, Allocator.Persistent, AllocationOption.Clear);
|
||||||
_shaders = new DynamicArray<Shader?>(16);
|
_shaders = new DynamicArray<Shader?>(16);
|
||||||
_shaderPasses = new Dictionary<ShaderPassKey, ShaderPass>(16);
|
_shaderPasses = new Dictionary<ShaderPassKey, ShaderPass>(16);
|
||||||
|
|
||||||
_descriptorAllocator = descriptorAllocator;
|
_lastSamplerId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
~D3D12ResourceDatabase()
|
~D3D12ResourceDatabase()
|
||||||
@@ -224,17 +228,17 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
|||||||
return GetResourceRecord(handle).desc;
|
return GetResourceRecord(handle).desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetBindlessIndex(Handle<GPUResource> handle)
|
public Result<uint, ResultStatus> GetBindlessIndex(Handle<GPUResource> handle)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
ref var info = ref GetResourceRecord(handle, out var exist);
|
ref var info = ref GetResourceRecord(handle, out var exist);
|
||||||
if (!exist || !info.Allocated)
|
if (!exist || !info.Allocated)
|
||||||
{
|
{
|
||||||
return -1;
|
return Result.Create(0u, ResultStatus.NotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
return info.viewGroup.srv.value;
|
return Result.Create((uint)info.viewGroup.srv.value, ResultStatus.NotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string? GetResourceName(Handle<GPUResource> handle)
|
public string? GetResourceName(Handle<GPUResource> handle)
|
||||||
@@ -266,7 +270,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
|||||||
}
|
}
|
||||||
|
|
||||||
info.Release(_descriptorAllocator);
|
info.Release(_descriptorAllocator);
|
||||||
//Debug.Assert(info.Release(_descriptorAllocator) == 0);
|
//System.Diagnostics.Debug.Assert(info.Release(_descriptorAllocator) == 0);
|
||||||
#if DEBUG || GHOST_EDITOR
|
#if DEBUG || GHOST_EDITOR
|
||||||
_resourceName.Remove(handle, out var name);
|
_resourceName.Remove(handle, out var name);
|
||||||
#endif
|
#endif
|
||||||
@@ -274,6 +278,27 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
|||||||
_resources.Remove(handle.id, handle.generation);
|
_resources.Remove(handle.id, handle.generation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Identifier<Sampler> CreateSampler(ref readonly SamplerDesc desc, int id)
|
||||||
|
{
|
||||||
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
|
if (_samplers.ContainsKey(desc))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Sampler already exists.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var identifier = new Identifier<Sampler>(id);
|
||||||
|
_samplers.Add(desc, identifier);
|
||||||
|
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetSampler(ref readonly SamplerDesc desc, out Identifier<Sampler> id)
|
||||||
|
{
|
||||||
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
return _samplers.TryGetValue(desc, out id);
|
||||||
|
}
|
||||||
|
|
||||||
public Handle<Mesh> AddMesh(ref readonly Mesh mesh)
|
public Handle<Mesh> AddMesh(ref readonly Mesh mesh)
|
||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
@@ -444,6 +469,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
|||||||
}
|
}
|
||||||
|
|
||||||
_resources.Dispose();
|
_resources.Dispose();
|
||||||
|
_samplers.Dispose();
|
||||||
_meshes.Dispose();
|
_meshes.Dispose();
|
||||||
_materials.Dispose();
|
_materials.Dispose();
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
|||||||
Format = desc.Format.ToDXGIFormat(),
|
Format = desc.Format.ToDXGIFormat(),
|
||||||
SampleDesc = new DXGI_SAMPLE_DESC(1, 0),
|
SampleDesc = new DXGI_SAMPLE_DESC(1, 0),
|
||||||
BufferUsage = DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
BufferUsage = DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||||
BufferCount = D3D12PipelineResource.BACK_BUFFER_COUNT,
|
BufferCount = desc.BufferCount,
|
||||||
Scaling = DXGI_SCALING_STRETCH,
|
Scaling = DXGI_SCALING_STRETCH,
|
||||||
SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD,
|
SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD,
|
||||||
AlphaMode = DXGI_ALPHA_MODE_IGNORE,
|
AlphaMode = DXGI_ALPHA_MODE_IGNORE,
|
||||||
|
|||||||
@@ -2,27 +2,27 @@ using Ghost.Core;
|
|||||||
|
|
||||||
namespace Ghost.Graphics.D3D12;
|
namespace Ghost.Graphics.D3D12;
|
||||||
|
|
||||||
internal readonly struct RTVDesc : IIdentifierType;
|
internal readonly struct RTVDescriptor : IIdentifierType;
|
||||||
internal readonly struct DSVDesc : IIdentifierType;
|
internal readonly struct DSVDescriptor : IIdentifierType;
|
||||||
internal readonly struct CbvSrvUavDesc : IIdentifierType;
|
internal readonly struct CbvSrvUavDescriptor : IIdentifierType;
|
||||||
internal readonly struct SamplerDesc : IIdentifierType;
|
internal readonly struct SamplerDescriptor : IIdentifierType;
|
||||||
|
|
||||||
internal struct ResourceViewGroup
|
internal struct ResourceViewGroup
|
||||||
{
|
{
|
||||||
public Identifier<RTVDesc> rtv;
|
public Identifier<RTVDescriptor> rtv;
|
||||||
public Identifier<DSVDesc> dsv;
|
public Identifier<DSVDescriptor> dsv;
|
||||||
public Identifier<CbvSrvUavDesc> srv;
|
public Identifier<CbvSrvUavDescriptor> srv;
|
||||||
public Identifier<CbvSrvUavDesc> cbv;
|
public Identifier<CbvSrvUavDescriptor> cbv;
|
||||||
public Identifier<CbvSrvUavDesc> uav;
|
public Identifier<CbvSrvUavDescriptor> uav;
|
||||||
public Identifier<SamplerDesc> sampler;
|
public Identifier<SamplerDescriptor> sampler;
|
||||||
|
|
||||||
public static ResourceViewGroup Invalid => new()
|
public static ResourceViewGroup Invalid => new()
|
||||||
{
|
{
|
||||||
rtv = Identifier<RTVDesc>.Invalid,
|
rtv = Identifier<RTVDescriptor>.Invalid,
|
||||||
dsv = Identifier<DSVDesc>.Invalid,
|
dsv = Identifier<DSVDescriptor>.Invalid,
|
||||||
srv = Identifier<CbvSrvUavDesc>.Invalid,
|
srv = Identifier<CbvSrvUavDescriptor>.Invalid,
|
||||||
cbv = Identifier<CbvSrvUavDesc>.Invalid,
|
cbv = Identifier<CbvSrvUavDescriptor>.Invalid,
|
||||||
uav = Identifier<CbvSrvUavDesc>.Invalid,
|
uav = Identifier<CbvSrvUavDescriptor>.Invalid,
|
||||||
sampler = Identifier<SamplerDesc>.Invalid,
|
sampler = Identifier<SamplerDescriptor>.Invalid,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -88,6 +88,64 @@ internal unsafe static class D3D12Utility
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ResourceState ToResourceState(this D3D12_RESOURCE_STATES states)
|
||||||
|
{
|
||||||
|
return states switch
|
||||||
|
{
|
||||||
|
D3D12_RESOURCE_STATE_COMMON => ResourceState.Common,
|
||||||
|
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER => ResourceState.VertexAndConstantBuffer,
|
||||||
|
D3D12_RESOURCE_STATE_INDEX_BUFFER => ResourceState.IndexBuffer,
|
||||||
|
D3D12_RESOURCE_STATE_RENDER_TARGET => ResourceState.RenderTarget,
|
||||||
|
D3D12_RESOURCE_STATE_UNORDERED_ACCESS => ResourceState.UnorderedAccess,
|
||||||
|
D3D12_RESOURCE_STATE_DEPTH_WRITE => ResourceState.DepthWrite,
|
||||||
|
D3D12_RESOURCE_STATE_DEPTH_READ => ResourceState.DepthRead,
|
||||||
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE => ResourceState.PixelShaderResource,
|
||||||
|
D3D12_RESOURCE_STATE_COPY_DEST => ResourceState.CopyDest,
|
||||||
|
D3D12_RESOURCE_STATE_COPY_SOURCE => ResourceState.CopySource,
|
||||||
|
_ => throw new ArgumentException($"Unknown D3D12 resource state: {states}")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static D3D12_FILTER ToD3D12Filter(this TextureFilterMode filterMode)
|
||||||
|
{
|
||||||
|
return filterMode switch
|
||||||
|
{
|
||||||
|
TextureFilterMode.Point => D3D12_FILTER_MIN_MAG_MIP_POINT,
|
||||||
|
TextureFilterMode.Bilinear => D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT,
|
||||||
|
TextureFilterMode.Trilinear => D3D12_FILTER_MIN_MAG_MIP_LINEAR,
|
||||||
|
TextureFilterMode.Anisotropic => D3D12_FILTER_ANISOTROPIC,
|
||||||
|
_ => throw new ArgumentException($"Unknown texture filter mode: {filterMode}")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static D3D12_TEXTURE_ADDRESS_MODE ToD3D12TextureAddressMode(this TextureAddressMode addressMode)
|
||||||
|
{
|
||||||
|
return addressMode switch
|
||||||
|
{
|
||||||
|
TextureAddressMode.Repeat => D3D12_TEXTURE_ADDRESS_MODE_WRAP,
|
||||||
|
TextureAddressMode.Mirror => D3D12_TEXTURE_ADDRESS_MODE_MIRROR,
|
||||||
|
TextureAddressMode.Clamp => D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
|
||||||
|
TextureAddressMode.Border => D3D12_TEXTURE_ADDRESS_MODE_BORDER,
|
||||||
|
TextureAddressMode.MirrorOnce => D3D12_TEXTURE_ADDRESS_MODE_MIRROR_ONCE,
|
||||||
|
_ => throw new ArgumentException($"Unknown texture address mode: {addressMode}")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static D3D12_COMPARISON_FUNC ToD3D12ComparisonFunc(this ComparisonFunction func)
|
||||||
|
{
|
||||||
|
return func switch
|
||||||
|
{
|
||||||
|
ComparisonFunction.Never => D3D12_COMPARISON_FUNC_NEVER,
|
||||||
|
ComparisonFunction.Less => D3D12_COMPARISON_FUNC_LESS,
|
||||||
|
ComparisonFunction.Equal => D3D12_COMPARISON_FUNC_EQUAL,
|
||||||
|
ComparisonFunction.LessEqual => D3D12_COMPARISON_FUNC_LESS_EQUAL,
|
||||||
|
ComparisonFunction.Greater => D3D12_COMPARISON_FUNC_GREATER,
|
||||||
|
ComparisonFunction.NotEqual => D3D12_COMPARISON_FUNC_NOT_EQUAL,
|
||||||
|
ComparisonFunction.GreaterEqual => D3D12_COMPARISON_FUNC_GREATER_EQUAL,
|
||||||
|
ComparisonFunction.Always => D3D12_COMPARISON_FUNC_ALWAYS,
|
||||||
|
_ => throw new ArgumentException($"Unknown comparison function: {func}")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static D3D12_RASTERIZER_DESC D3D12_RASTERIZER_DESC_CREATE(
|
public static D3D12_RASTERIZER_DESC D3D12_RASTERIZER_DESC_CREATE(
|
||||||
|
|||||||
@@ -11,11 +11,13 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<IsAotCompatible>True</IsAotCompatible>
|
<IsAotCompatible>True</IsAotCompatible>
|
||||||
<IsTrimmable>True</IsTrimmable>
|
<IsTrimmable>True</IsTrimmable>
|
||||||
|
<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>
|
||||||
|
|||||||
@@ -10,14 +10,6 @@ using TerraFX.Interop.DirectX;
|
|||||||
|
|
||||||
namespace Ghost.Graphics.RHI;
|
namespace Ghost.Graphics.RHI;
|
||||||
|
|
||||||
public interface IRHIObject
|
|
||||||
{
|
|
||||||
string Name
|
|
||||||
{
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public readonly struct ShaderPassKey
|
public readonly struct ShaderPassKey
|
||||||
{
|
{
|
||||||
public readonly ulong value;
|
public readonly ulong value;
|
||||||
@@ -603,6 +595,57 @@ public struct TextureDesc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the parameters used to configure a texture sampler for graphics rendering operations.
|
||||||
|
/// </summary>
|
||||||
|
public record struct SamplerDesc
|
||||||
|
{
|
||||||
|
public TextureFilterMode FilterMode
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureAddressMode AddressU
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureAddressMode AddressV
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextureAddressMode AddressW
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComparisonFunction ComparisonFunc
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MipLODBias
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint MaxAnisotropy
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MinLOD
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float MaxLOD
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Buffer description
|
/// Buffer description
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -865,3 +908,32 @@ public enum PrimitiveTopology
|
|||||||
Line,
|
Line,
|
||||||
Triangle,
|
Triangle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum TextureFilterMode
|
||||||
|
{
|
||||||
|
Point,
|
||||||
|
Bilinear,
|
||||||
|
Trilinear,
|
||||||
|
Anisotropic
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TextureAddressMode
|
||||||
|
{
|
||||||
|
Repeat,
|
||||||
|
Mirror,
|
||||||
|
Clamp,
|
||||||
|
Border,
|
||||||
|
MirrorOnce
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ComparisonFunction
|
||||||
|
{
|
||||||
|
Never,
|
||||||
|
Less,
|
||||||
|
Equal,
|
||||||
|
LessEqual,
|
||||||
|
Greater,
|
||||||
|
NotEqual,
|
||||||
|
GreaterEqual,
|
||||||
|
Always
|
||||||
|
}
|
||||||
@@ -91,6 +91,13 @@ public interface ICommandBuffer : IDisposable
|
|||||||
/// <param name="stateAfter">The desired state of the resource after the transition.</param>
|
/// <param name="stateAfter">The desired state of the resource after the transition.</param>
|
||||||
void ResourceBarrier(Handle<GPUResource> resource, ResourceState stateBefore, ResourceState stateAfter);
|
void ResourceBarrier(Handle<GPUResource> resource, ResourceState stateBefore, ResourceState stateAfter);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts a resource barrier for state transitions. The current state is tracked internally.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="resource">A handle to the GPU resource to transition.</param>
|
||||||
|
/// <param name="stateAfter">The desired state of the resource after the transition.</param>
|
||||||
|
void ResourceBarrier(Handle<GPUResource> resource, ResourceState stateAfter);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the pipeline state object
|
/// Sets the pipeline state object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -11,22 +11,29 @@ public interface IResourceAllocator : IDisposable
|
|||||||
/// Creates a texture resource
|
/// Creates a texture resource
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="desc">Texture description</param>
|
/// <param name="desc">Texture description</param>
|
||||||
/// <returns>A new texture handle point to the resource</returns>
|
/// <returns>An <see cref="Handle{Texture}"/> point to the resource</returns>
|
||||||
public Handle<Texture> CreateTexture(ref readonly TextureDesc desc, bool tempResource = false);
|
Handle<Texture> CreateTexture(ref readonly TextureDesc desc, bool tempResource = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a render Target for off-screen rendering
|
/// Creates a render Target for off-screen rendering
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="desc">Render Target description</param>
|
/// <param name="desc">Render Target description</param>
|
||||||
/// <returns>A new texture handle point to the resource</returns>
|
/// <returns>An <see cref="Handle{Texture}"/> point to the resource</returns>
|
||||||
public Handle<Texture> CreateRenderTarget(ref readonly RenderTargetDesc desc, bool tempResource = false);
|
Handle<Texture> CreateRenderTarget(ref readonly RenderTargetDesc desc, bool tempResource = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a buffer resource
|
/// Creates a buffer resource
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="desc">Buffer description</param>
|
/// <param name="desc">Buffer description</param>
|
||||||
/// <returns>A new buffer handle point to the resource</returns>
|
/// <returns>An <see cref="Handle{GraphicsBuffer}"/> point to the resource</returns>
|
||||||
public Handle<GraphicsBuffer> CreateBuffer(ref readonly BufferDesc desc, bool tempResource = false);
|
Handle<GraphicsBuffer> CreateBuffer(ref readonly BufferDesc desc, bool tempResource = false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new sampler object using the specified sampler description.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="desc">A read-only reference to a <see cref="SamplerDesc"/> structure that defines the properties of the sampler to be created.</param>
|
||||||
|
/// <returns>An <see cref="Identifier{Sampler}"/> that uniquely identifies the created sampler object.</returns>
|
||||||
|
Identifier<Sampler> CreateSampler(ref readonly SamplerDesc desc);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new mesh from the specified vertex and index data.
|
/// Creates a new mesh from the specified vertex and index data.
|
||||||
@@ -34,19 +41,19 @@ public interface IResourceAllocator : IDisposable
|
|||||||
/// <param name="vertices">A UnsafeList containing the vertices that define the geometry of the mesh. Must contain at least one vertex.</param>
|
/// <param name="vertices">A UnsafeList containing the vertices that define the geometry of the mesh. Must contain at least one vertex.</param>
|
||||||
/// <param name="indices">A UnsafeList containing the indices that specify how vertices are connected to form primitives. Must contain at least one index.</param>
|
/// <param name="indices">A UnsafeList containing the indices that specify how vertices are connected to form primitives. Must contain at least one index.</param>
|
||||||
/// <returns>An <see cref="Identifier{Mesh}"/> representing the newly created mesh.</returns>
|
/// <returns>An <see cref="Identifier{Mesh}"/> representing the newly created mesh.</returns>
|
||||||
public Handle<Mesh> CreateMesh(UnsafeList<Vertex> vertices, UnsafeList<uint> indices);
|
Handle<Mesh> CreateMesh(UnsafeList<Vertex> vertices, UnsafeList<uint> indices);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new material instance using the specified shader.
|
/// Creates a new material instance using the specified shader.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="shader">The identifier of the shader to associate with the new material. Cannot be null.</param>
|
/// <param name="shader">The identifier of the shader to associate with the new material. Cannot be null.</param>
|
||||||
/// <returns>An <see cref="Identifier{Material}"/> representing the newly created material.</returns>
|
/// <returns>An <see cref="Identifier{Material}"/> representing the newly created material.</returns>
|
||||||
public Handle<Material> CreateMaterial(Identifier<Shader> shader);
|
Handle<Material> CreateMaterial(Identifier<Shader> shader);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new shader and returns its unique identifier.
|
/// Creates a new shader and returns its unique identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>An <see cref="Identifier{Shader}"/> representing the newly created shader.</returns>
|
/// <returns>An <see cref="Identifier{Shader}"/> representing the newly created shader.</returns>
|
||||||
/// <param name="descriptor">The viewGroup containing the shader's properties and passes.</param>
|
/// <param name="descriptor">The viewGroup containing the shader's properties and passes.</param>
|
||||||
public Identifier<Shader> CreateGraphicsShader(ShaderDescriptor descriptor);
|
Identifier<Shader> CreateGraphicsShader(ShaderDescriptor descriptor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public interface IResourceDatabase : IDisposable
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="handle">A handle to the GPU resource for which to obtain the bindless index. Must reference a valid, currently registered resource.</param>
|
/// <param name="handle">A handle to the GPU resource for which to obtain the bindless index. Must reference a valid, currently registered resource.</param>
|
||||||
/// <returns>The bindless index corresponding to the specified GPU resource handle. -1 if the resource does not support bindless access or is not found.</returns>
|
/// <returns>The bindless index corresponding to the specified GPU resource handle. -1 if the resource does not support bindless access or is not found.</returns>
|
||||||
int GetBindlessIndex(Handle<GPUResource> handle);
|
Result<uint, ResultStatus> GetBindlessIndex(Handle<GPUResource> handle);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves the name of the GPU resource associated with the specified handle.
|
/// Retrieves the name of the GPU resource associated with the specified handle.
|
||||||
@@ -78,6 +78,23 @@ public interface IResourceDatabase : IDisposable
|
|||||||
/// <param name="handle">The handle of the resource to be removed.</param>
|
/// <param name="handle">The handle of the resource to be removed.</param>
|
||||||
void ReleaseResource(Handle<GPUResource> handle);
|
void ReleaseResource(Handle<GPUResource> handle);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves an existing sampler identifier that matches the specified description, or creates a new one if none
|
||||||
|
/// exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="desc">A read-only reference to a <see cref="SamplerDesc"/> structure that defines the properties of the sampler to retrieve or create.</param>
|
||||||
|
/// <param name="id">An integer identifier to associate with the sampler.</param>
|
||||||
|
/// <returns>An <see cref="Identifier{Sampler}"/> representing the sampler that matches the specified description.
|
||||||
|
/// If a matching sampler does not exist, a new sampler is created and its identifier is returned.</returns>
|
||||||
|
Identifier<Sampler> CreateSampler(ref readonly SamplerDesc desc, int id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether a sampler with the specified identifier exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The identifier of the sampler to check for existence.</param>
|
||||||
|
/// <returns>true if a sampler with the given identifier exists; otherwise, false.</returns>
|
||||||
|
bool TryGetSampler(ref readonly SamplerDesc desc, out Identifier<Sampler> id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a mesh to the resource database and returns its handle.
|
/// Adds a mesh to the resource database and returns its handle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ using Ghost.Graphics.Core;
|
|||||||
using Ghost.Graphics.RHI;
|
using Ghost.Graphics.RHI;
|
||||||
using Ghost.Graphics.Utilities;
|
using Ghost.Graphics.Utilities;
|
||||||
using Ghost.SDL.Compiler;
|
using Ghost.SDL.Compiler;
|
||||||
|
using Misaki.HighPerformance.Image;
|
||||||
using Misaki.HighPerformance.Mathematics;
|
using Misaki.HighPerformance.Mathematics;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Ghost.Graphics.RenderPasses;
|
namespace Ghost.Graphics.RenderPasses;
|
||||||
@@ -23,6 +25,11 @@ internal class MeshRenderPass : IRenderPass
|
|||||||
public uint texture2;
|
public uint texture2;
|
||||||
public uint texture3;
|
public uint texture3;
|
||||||
public uint texture4;
|
public uint texture4;
|
||||||
|
public uint tex_sampler;
|
||||||
|
|
||||||
|
private uint _padding1;
|
||||||
|
private uint _padding2;
|
||||||
|
private uint _padding3;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Handle<Mesh> _mesh;
|
private Handle<Mesh> _mesh;
|
||||||
@@ -48,8 +55,8 @@ internal class MeshRenderPass : IRenderPass
|
|||||||
for (var i = 0; i < shaderDescriptor.passes.Count; i++)
|
for (var i = 0; i < shaderDescriptor.passes.Count; i++)
|
||||||
{
|
{
|
||||||
var pass = shaderDescriptor.passes[i];
|
var pass = shaderDescriptor.passes[i];
|
||||||
var compileResult = ctx.ShaderCompiler.CompilePass(pass, shaderDescriptor.generatedCodePath);
|
var compiled = ctx.ShaderCompiler.CompilePass(pass, shaderDescriptor.generatedCodePath).GetValueOrThrow();
|
||||||
if (compileResult.IsFailure || pass is not FullPassDescriptor fullPass)
|
if (pass is not FullPassDescriptor fullPass)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -67,7 +74,7 @@ internal class MeshRenderPass : IRenderPass
|
|||||||
DsvFormat = TextureFormat.Unknown,
|
DsvFormat = TextureFormat.Unknown,
|
||||||
};
|
};
|
||||||
|
|
||||||
_compileResults[i] = compileResult.Value;
|
_compileResults[i] = compiled;
|
||||||
ctx.PipelineLibrary.CompilePSO(in psoDes, in _compileResults[i]).GetValueOrThrow();
|
ctx.PipelineLibrary.CompilePSO(in psoDes, in _compileResults[i]).GetValueOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,38 +86,51 @@ internal class MeshRenderPass : IRenderPass
|
|||||||
_shader = ctx.ResourceAllocator.CreateGraphicsShader(shaderDescriptor);
|
_shader = ctx.ResourceAllocator.CreateGraphicsShader(shaderDescriptor);
|
||||||
_material = ctx.ResourceAllocator.CreateMaterial(_shader);
|
_material = ctx.ResourceAllocator.CreateMaterial(_shader);
|
||||||
|
|
||||||
|
_textures = new Handle<Texture>[_textureFiles.Length];
|
||||||
|
for (var i = 0; i < _textureFiles.Length; i++)
|
||||||
|
{
|
||||||
|
using var stream = File.OpenRead(_textureFiles[i]);
|
||||||
|
using var imageData = ImageResult.FromStream(stream, ColorComponents.RGBA);
|
||||||
|
|
||||||
|
var desc = new TextureDesc
|
||||||
|
{
|
||||||
|
Width = imageData.Width,
|
||||||
|
Height = imageData.Height,
|
||||||
|
Dimension = TextureDimension.Texture2D,
|
||||||
|
Format = TextureFormat.R8G8B8A8_UNorm,
|
||||||
|
MipLevels = 1,
|
||||||
|
Slice = 1,
|
||||||
|
Usage = TextureUsage.ShaderResource,
|
||||||
|
};
|
||||||
|
|
||||||
|
_textures[i] = ctx.CreateTexture(ref desc);
|
||||||
|
ctx.UploadTexture(_textures[i], imageData.AsSpan());
|
||||||
|
}
|
||||||
|
|
||||||
|
var samplerDesc = new SamplerDesc
|
||||||
|
{
|
||||||
|
AddressU = TextureAddressMode.Repeat,
|
||||||
|
AddressV = TextureAddressMode.Repeat,
|
||||||
|
AddressW = TextureAddressMode.Repeat,
|
||||||
|
FilterMode = TextureFilterMode.Bilinear,
|
||||||
|
MaxAnisotropy = 16,
|
||||||
|
};
|
||||||
|
|
||||||
|
var sampler = ctx.ResourceAllocator.CreateSampler(in samplerDesc);
|
||||||
|
|
||||||
ref var matRef = ref ctx.ResourceDatabase.GetMaterialReference(_material);
|
ref var matRef = ref ctx.ResourceDatabase.GetMaterialReference(_material);
|
||||||
var matProps = new ShaderProperties_MyShader_Standard
|
var matProps = new ShaderProperties_MyShader_Standard
|
||||||
{
|
{
|
||||||
color = new float4(1.0f, 1.0f, 1.0f, 1.0f),
|
color = new float4(1.0f, 1.0f, 1.0f, 1.0f),
|
||||||
texture1 = 0,
|
texture1 = ctx.ResourceDatabase.GetBindlessIndex(_textures[0].AsResource()).GetValueOrThrow(ResultStatus.Success),
|
||||||
texture2 = 1,
|
texture2 = ctx.ResourceDatabase.GetBindlessIndex(_textures[1].AsResource()).GetValueOrThrow(ResultStatus.Success),
|
||||||
texture3 = 2,
|
texture3 = ctx.ResourceDatabase.GetBindlessIndex(_textures[2].AsResource()).GetValueOrThrow(ResultStatus.Success),
|
||||||
texture4 = 3,
|
texture4 = ctx.ResourceDatabase.GetBindlessIndex(_textures[3].AsResource()).GetValueOrThrow(ResultStatus.Success),
|
||||||
|
tex_sampler = (uint)sampler.value,
|
||||||
};
|
};
|
||||||
|
|
||||||
matRef.SetPropertyCache(in matProps);
|
Debug.Assert(matRef.SetPropertyCache(in matProps) == ResultStatus.Success);
|
||||||
|
matRef.UploadData(ctx.DirectCommandBuffer);
|
||||||
//_textures = new Handle<Texture>[_textureFiles.Length];
|
|
||||||
//for (var i = 0; i < _textureFiles.Length; i++)
|
|
||||||
//{
|
|
||||||
// using var stream = File.OpenRead(_textureFiles[i]);
|
|
||||||
// using var imageData = ImageResult.FromStream(stream);
|
|
||||||
|
|
||||||
// var desc = new TextureDesc
|
|
||||||
// {
|
|
||||||
// Width = imageData.Width,
|
|
||||||
// Height = imageData.Height,
|
|
||||||
// Dimension = TextureDimension.Texture2D,
|
|
||||||
// Format = TextureFormat.R8G8B8A8_UNorm,
|
|
||||||
// MipLevels = 1,
|
|
||||||
// Slice = 1,
|
|
||||||
// Usage = TextureUsage.ShaderResource,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// _textures[i] = ctx.CreateTexture(ref desc);
|
|
||||||
// ctx.UploadTexture(_textures[i], new Span<byte>(imageData.Data, (int)imageData.Size));
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Execute(ref readonly RenderingContext ctx)
|
public void Execute(ref readonly RenderingContext ctx)
|
||||||
|
|||||||
@@ -38,12 +38,12 @@ void MSMain(
|
|||||||
|
|
||||||
float4 PSMain(PixelInput input) : SV_TARGET
|
float4 PSMain(PixelInput input) : SV_TARGET
|
||||||
{
|
{
|
||||||
//float4 color1 = SAMPLE_TEXTURE2D(g_PerMaterialData.texture1, 0, input.uv.xy);
|
float4 color1 = SAMPLE_TEXTURE2D(g_PerMaterialData.texture1, g_PerMaterialData.tex_sampler, input.uv.xy);
|
||||||
//float4 color2 = SAMPLE_TEXTURE2D(g_PerMaterialData.texture2, 0, input.uv.xy);
|
float4 color2 = SAMPLE_TEXTURE2D(g_PerMaterialData.texture2, g_PerMaterialData.tex_sampler, input.uv.xy);
|
||||||
//float4 color3 = SAMPLE_TEXTURE2D(g_PerMaterialData.texture3, 0, input.uv.xy);
|
float4 color3 = SAMPLE_TEXTURE2D(g_PerMaterialData.texture3, g_PerMaterialData.tex_sampler, input.uv.xy);
|
||||||
//float4 color4 = SAMPLE_TEXTURE2D(g_PerMaterialData.texture4, 0, input.uv.xy);
|
float4 color4 = SAMPLE_TEXTURE2D(g_PerMaterialData.texture4, g_PerMaterialData.tex_sampler, input.uv.xy);
|
||||||
|
|
||||||
//float4 blendedColor = (color1 + color2 + color3 + color4) * 0.25f;
|
float4 blendedColor = (color1 + color2 + color3 + color4) * 0.25f;
|
||||||
return g_PerMaterialData.color + input.color;
|
return g_PerMaterialData.color * blendedColor;
|
||||||
//return input.color;
|
//return input.color;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ shader "MyShader/Standard"
|
|||||||
tex2d texture2 = tex2d(white);
|
tex2d texture2 = tex2d(white);
|
||||||
tex2d texture3 = tex2d(grey);
|
tex2d texture3 = tex2d(grey);
|
||||||
tex2d texture4 = tex2d(normal);
|
tex2d texture4 = tex2d(normal);
|
||||||
|
sampler tex_sampler;
|
||||||
}
|
}
|
||||||
|
|
||||||
pass "Forward"
|
pass "Forward"
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ struct Vertex
|
|||||||
float4 color;
|
float4 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SIZEOF_VERTEX 80 // bytes
|
||||||
|
|
||||||
// Resource descriptor heap definitions
|
// Resource descriptor heap definitions
|
||||||
|
|
||||||
#define GLOBAL_TEXTURE2D_HEAP ResourceDescriptorHeap
|
#define GLOBAL_TEXTURE2D_HEAP ResourceDescriptorHeap
|
||||||
@@ -44,50 +46,52 @@ struct Vertex
|
|||||||
#define GET_BUFFER(id) GLOBAL_BUFFER_HEAP[id]
|
#define GET_BUFFER(id) GLOBAL_BUFFER_HEAP[id]
|
||||||
#define GET_SAMPLER(id) GLOBAL_SAMPLER_HEAP[id]
|
#define GET_SAMPLER(id) GLOBAL_SAMPLER_HEAP[id]
|
||||||
|
|
||||||
|
#define SAMPLE_TEXTURE2D(texId, sampId, uv) SampleTexture2D(texId, sampId, uv)
|
||||||
|
#define SAMPLE_TEXTURE2D_LEVEL(texId, sampId, uv, level) SampleTexture2DLevel(texId, sampId, uv, level)
|
||||||
|
#define SAMPLE_TEXTURE2D_ARRAY(texId, sampId, uvw) SampleTextureArray(texId, sampId, uvw)
|
||||||
|
|
||||||
#define MESH_SHADER_THREADS(x) [NumThreads(x, 1, 1)]
|
#define MESH_SHADER_THREADS(x) [NumThreads(x, 1, 1)]
|
||||||
|
|
||||||
|
|
||||||
inline float4 SampleTexture2D(uint texId, uint sampId, float2 uv)
|
static inline float4 SampleTexture2D(uint texId, uint sampId, float2 uv)
|
||||||
{
|
{
|
||||||
Texture2D tex = GET_TEXTURE2D(texId);
|
Texture2D tex = GET_TEXTURE2D(texId);
|
||||||
SamplerState samp = GET_SAMPLER(sampId);
|
SamplerState samp = GET_SAMPLER(sampId);
|
||||||
return tex.Sample(samp, uv);
|
return tex.Sample(samp, uv);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float4 SampleTexture2DLevel(uint texId, uint sampId, float2 uv, float level)
|
static inline float4 SampleTexture2DLevel(uint texId, uint sampId, float2 uv, float level)
|
||||||
{
|
{
|
||||||
Texture2D tex = GET_TEXTURE2D(texId);
|
Texture2D tex = GET_TEXTURE2D(texId);
|
||||||
SamplerState samp = GET_SAMPLER(sampId);
|
SamplerState samp = GET_SAMPLER(sampId);
|
||||||
return tex.SampleLevel(samp, uv, level);
|
return tex.SampleLevel(samp, uv, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float4 SampleTextureArray(uint texId, uint sampId, float3 uv)
|
static inline float4 SampleTextureArray(uint texId, uint sampId, float3 uvw)
|
||||||
{
|
{
|
||||||
Texture2DArray tex = GET_TEXTURE2D_ARRAY(texId);
|
Texture2DArray tex = GET_TEXTURE2D_ARRAY(texId);
|
||||||
SamplerState samp = GET_SAMPLER(sampId);
|
SamplerState samp = GET_SAMPLER(sampId);
|
||||||
return tex.Sample(samp, uvw.xyz);
|
return tex.Sample(samp, uvw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline Vertex LoadVertexData(uint vertexID, uint groupID, BYTE_ADDRESS_BUFFER vertexBuffer, BYTE_ADDRESS_BUFFER indexBuffer)
|
||||||
inline Vertex LoadVertexData(uint vertexID, uint groupID, BYTE_ADDRESS_BUFFER vertexBuffer, BYTE_ADDRESS_BUFFER indexBuffer)
|
|
||||||
{
|
{
|
||||||
// Fetch bindless buffers
|
// Fetch bindless buffers
|
||||||
ByteAddressBuffer vertexBuffer = GET_BUFFER(vertexBuffer);
|
ByteAddressBuffer vertices = GET_BUFFER(vertexBuffer);
|
||||||
ByteAddressBuffer indexBuffer = GET_BUFFER(indexBuffer);
|
ByteAddressBuffer indices = GET_BUFFER(indexBuffer);
|
||||||
|
|
||||||
// Compute the triangle’s vertex indices
|
// Compute the triangle’s vertex indices
|
||||||
uint indexOffset = (groupID * 3 + vertexID) * 4; // uint32 index
|
uint indexOffset = (groupID * 3 + vertexID) * 4; // uint32 index
|
||||||
uint vertexIndex = indexBuffer.Load(indexOffset);
|
uint vertexIndex = indices.Load(indexOffset);
|
||||||
|
|
||||||
// Load vertex attributes
|
// Load vertex attributes
|
||||||
uint vertexOffset = vertexIndex * 80; // 80 bytes per vertex
|
uint vertexOffset = vertexIndex * SIZEOF_VERTEX;
|
||||||
Vertex v;
|
Vertex v;
|
||||||
v.position = asfloat(vertexBuffer.Load4(vertexOffset + 0));
|
v.position = asfloat(vertices.Load4(vertexOffset + 0));
|
||||||
v.normal = asfloat(vertexBuffer.Load4(vertexOffset + 16));
|
v.normal = asfloat(vertices.Load4(vertexOffset + 16));
|
||||||
v.tangent = asfloat(vertexBuffer.Load4(vertexOffset + 32));
|
v.tangent = asfloat(vertices.Load4(vertexOffset + 32));
|
||||||
v.uv = asfloat(vertexBuffer.Load4(vertexOffset + 48));
|
v.uv = asfloat(vertices.Load4(vertexOffset + 48));
|
||||||
v.color = asfloat(vertexBuffer.Load4(vertexOffset + 64));
|
v.color = asfloat(vertices.Load4(vertexOffset + 64));
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ struct PerObjectData
|
|||||||
{
|
{
|
||||||
float4x4 localToWorld;
|
float4x4 localToWorld;
|
||||||
float3 worldBoundsMin;
|
float3 worldBoundsMin;
|
||||||
BYTE_ADDRESS_BUFFER_BINDLESS vertexBuffer;
|
BYTE_ADDRESS_BUFFER vertexBuffer;
|
||||||
float3 worldBoundsMax;
|
float3 worldBoundsMax;
|
||||||
BYTE_ADDRESS_BUFFER_BINDLESS indexBuffer;
|
BYTE_ADDRESS_BUFFER indexBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
cbuffer GlobalConstants : register(b0)
|
cbuffer GlobalConstants : register(b0)
|
||||||
|
|||||||
@@ -182,6 +182,9 @@ internal class PropertiesBlock : IBlockParser<PropertiesSyntax, List<PropertySem
|
|||||||
TokenLexicon.KnownTypes.TEXTURE2D => ShaderPropertyType.Texture2D,
|
TokenLexicon.KnownTypes.TEXTURE2D => ShaderPropertyType.Texture2D,
|
||||||
TokenLexicon.KnownTypes.TEXTURE3D => ShaderPropertyType.Texture3D,
|
TokenLexicon.KnownTypes.TEXTURE3D => ShaderPropertyType.Texture3D,
|
||||||
TokenLexicon.KnownTypes.TEXTURECUBE => ShaderPropertyType.TextureCube,
|
TokenLexicon.KnownTypes.TEXTURECUBE => ShaderPropertyType.TextureCube,
|
||||||
|
TokenLexicon.KnownTypes.TEXTURECUBE_ARRAY => ShaderPropertyType.TextureCubeArray,
|
||||||
|
TokenLexicon.KnownTypes.TEXTURE2D_ARRAY => ShaderPropertyType.Texture2DArray,
|
||||||
|
TokenLexicon.KnownTypes.SAMPLER => ShaderPropertyType.Sampler,
|
||||||
_ => ShaderPropertyType.None,
|
_ => ShaderPropertyType.None,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ internal static class SDLCompiler
|
|||||||
return Result.Failure("Failed to generate global properties: " + globalPropResult.Message);
|
return Result.Failure("Failed to generate global properties: " + globalPropResult.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
var generatedResult = GenerateShaderCode(desc, generatedOutputDirectory);
|
var generatedResult = GenerateShaderCode(desc, generatedOutputDirectory, globalPropResult.Value);
|
||||||
if (generatedResult.IsFailure)
|
if (generatedResult.IsFailure)
|
||||||
{
|
{
|
||||||
return Result.Failure("Failed to generate pass files: " + generatedResult.Message);
|
return Result.Failure("Failed to generate pass files: " + generatedResult.Message);
|
||||||
@@ -269,7 +269,7 @@ internal static class SDLCompiler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return Result.Failure("Failed to generate shader files: " + ex.Message);
|
return Result.Failure("Failed to compile shader: " + ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,16 +294,17 @@ internal static class SDLCompiler
|
|||||||
ShaderPropertyType.Bool3 => "bool3",
|
ShaderPropertyType.Bool3 => "bool3",
|
||||||
ShaderPropertyType.Bool4 => "bool4",
|
ShaderPropertyType.Bool4 => "bool4",
|
||||||
// NOTE: Textures here are bindless, represented as uint (descriptor index).
|
// NOTE: Textures here are bindless, represented as uint (descriptor index).
|
||||||
ShaderPropertyType.Texture2D => "TEXTURE2D_BINDLESS",
|
ShaderPropertyType.Texture2D => "TEXTURE2D",
|
||||||
ShaderPropertyType.Texture3D => "TEXTURE3D_BINDLESS",
|
ShaderPropertyType.Texture3D => "TEXTURE3D",
|
||||||
ShaderPropertyType.TextureCube => "TEXTURECUBE_BINDLESS",
|
ShaderPropertyType.TextureCube => "TEXTURECUBE",
|
||||||
ShaderPropertyType.Texture2DArray => "TEXTURE2D_ARRAY_BINDLESS",
|
ShaderPropertyType.Texture2DArray => "TEXTURE2D_ARRAY",
|
||||||
ShaderPropertyType.TextureCubeArray => "TEXTURECUBE_ARRAY_BINDLESS",
|
ShaderPropertyType.TextureCubeArray => "TEXTURECUBE_ARRAY",
|
||||||
|
ShaderPropertyType.Sampler => "SAMPLER",
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(type), $"Unsupported shader property type: {type}")
|
_ => throw new ArgumentOutOfRangeException(nameof(type), $"Unsupported shader property type: {type}")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Result<string> GenerateShaderCode(ShaderDescriptor descriptor, string targetDirectory)
|
public static Result<string> GenerateShaderCode(ShaderDescriptor descriptor, string targetDirectory, string globalDataPath)
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(targetDirectory))
|
if (!Directory.Exists(targetDirectory))
|
||||||
{
|
{
|
||||||
@@ -329,7 +330,8 @@ internal static class SDLCompiler
|
|||||||
#ifndef {fileDefine}
|
#ifndef {fileDefine}
|
||||||
#define {fileDefine}
|
#define {fileDefine}
|
||||||
|
|
||||||
#include ""F:/csharp/GhostEngine/Ghost.Shader/BuiltIn/Common.hlsl""");
|
#include ""F:/csharp/GhostEngine/Ghost.Shader/BuiltIn/Common.hlsl""
|
||||||
|
#include ""{globalDataPath}""");
|
||||||
|
|
||||||
sb.Append(@"
|
sb.Append(@"
|
||||||
struct PerMaterialData
|
struct PerMaterialData
|
||||||
|
|||||||
@@ -176,6 +176,8 @@ internal static class TokenLexicon
|
|||||||
public const string TEXTURE3D = "tex3d";
|
public const string TEXTURE3D = "tex3d";
|
||||||
public const string TEXTURECUBE = "texcube";
|
public const string TEXTURECUBE = "texcube";
|
||||||
public const string TEXTURECUBE_ARRAY = "texcube_arr";
|
public const string TEXTURECUBE_ARRAY = "texcube_arr";
|
||||||
|
|
||||||
|
public const string SAMPLER = "sampler";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class KnownTextureValue
|
public static class KnownTextureValue
|
||||||
@@ -218,6 +220,7 @@ internal static class TokenLexicon
|
|||||||
KnownTypes.BOOL, KnownTypes.BOOL2, KnownTypes.BOOL3, KnownTypes.BOOL4,
|
KnownTypes.BOOL, KnownTypes.BOOL2, KnownTypes.BOOL3, KnownTypes.BOOL4,
|
||||||
KnownTypes.TEXTURE2D, KnownTypes.TEXTURE2D_ARRAY, KnownTypes.TEXTURE3D,
|
KnownTypes.TEXTURE2D, KnownTypes.TEXTURE2D_ARRAY, KnownTypes.TEXTURE3D,
|
||||||
KnownTypes.TEXTURECUBE, KnownTypes.TEXTURECUBE_ARRAY,
|
KnownTypes.TEXTURECUBE, KnownTypes.TEXTURECUBE_ARRAY,
|
||||||
|
KnownTypes.SAMPLER,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly HashSet<string> s_textureDefaultValues = new()
|
private static readonly HashSet<string> s_textureDefaultValues = new()
|
||||||
|
|||||||
Reference in New Issue
Block a user