forked from Misaki/GhostEngine
Refactor and enhance graphics and audio systems
Updated target frameworks to .NET 10.0 across multiple projects for compatibility with the latest features. Refactored namespaces and introduced new classes for shader descriptors, FMOD integration, and DirectX 12 utilities using TerraFX. Replaced `Win32` bindings with TerraFX equivalents for DirectX 12. Added a C# wrapper for FMOD Studio API, including DSP and error handling. Enhanced entity queries, component storage, and query filters for better performance and type safety. Introduced new test projects and updated the solution structure. Added `meshoptimizer` bindings and integrated `meshoptimizer_native.dll`. Improved code readability, maintainability, and performance.
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Core.Graphics;
|
||||
using Ghost.Graphics.Data;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Win32.Graphics.D3D12MemoryAllocator;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using Win32.Graphics.Dxgi;
|
||||
using Win32.Graphics.Dxgi.Common;
|
||||
using static Win32.Graphics.D3D12MemoryAllocator.Apis;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
using static TerraFX.Aliases.D3D12_Alias;
|
||||
using static TerraFX.Aliases.D3D12MA_Alias;
|
||||
using static TerraFX.Aliases.DXGI_Alias;
|
||||
using static TerraFX.Interop.DirectX.D3D12MemAlloc;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -17,9 +19,9 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
private const uint _MAX_TEXTURE2D_DIMENSION = 16384u;
|
||||
private const uint _MAX_TEXTURE3D_DIMENSION = 2048u;
|
||||
|
||||
private readonly ID3D12Device14* _device;
|
||||
private ComPtr<D3D12MA_Allocator> _allocator;
|
||||
|
||||
private readonly Allocator _allocator;
|
||||
private readonly D3D12RenderDevice _device;
|
||||
private readonly RenderSystem _renderSystem;
|
||||
private readonly D3D12DescriptorAllocator _descriptorAllocator;
|
||||
private readonly D3D12ResourceDatabase _resourceDatabase;
|
||||
@@ -39,16 +41,16 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
|
||||
public D3D12ResourceAllocator(RenderSystem renderSystem, D3D12RenderDevice device, D3D12DescriptorAllocator descriptorAllocator, D3D12ResourceDatabase resourceDatabase)
|
||||
{
|
||||
var desc = new AllocatorDesc
|
||||
var desc = new D3D12MA_ALLOCATOR_DESC
|
||||
{
|
||||
pAdapter = (IDXGIAdapter*)device.Adapter,
|
||||
pDevice = (ID3D12Device*)device.NativeDevice,
|
||||
Flags = AllocatorFlags.DefaultPoolsNotZeroed | AllocatorFlags.MSAATexturesAlwaysCommitted
|
||||
Flags = D3D12MA_ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED | D3D12MA_ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED,
|
||||
};
|
||||
|
||||
CreateAllocator(in desc, out _allocator);
|
||||
D3D12MA_CreateAllocator(&desc, _allocator.GetAddressOf());
|
||||
|
||||
_device = device.NativeDevice;
|
||||
_device = device;
|
||||
_renderSystem = renderSystem;
|
||||
_descriptorAllocator = descriptorAllocator;
|
||||
_resourceDatabase = resourceDatabase;
|
||||
@@ -78,9 +80,9 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private Handle<GPUResource> TrackResource(ref readonly Allocation allocation, ResourceStates state, D3D12ResourceDescriptor resourceDescriptor, ResourceDesc desc, bool isTemp)
|
||||
private Handle<GPUResource> TrackResource(ComPtr<D3D12MA_Allocation> allocation, D3D12_RESOURCE_STATES state, ResourceViewGroup resourceDescriptor, ResourceDesc desc, bool isTemp)
|
||||
{
|
||||
var handle = _resourceDatabase.AddResource(in allocation, _renderSystem.CPUFenceValue, D3D12StatesToRHIState(state), resourceDescriptor, desc);
|
||||
var handle = _resourceDatabase.AddResource(allocation, _renderSystem.CPUFenceValue, D3D12StatesToRHIState(state), resourceDescriptor, desc);
|
||||
|
||||
if (isTemp)
|
||||
{
|
||||
@@ -90,58 +92,266 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
return handle;
|
||||
}
|
||||
|
||||
private void CreateSRV(ID3D12Resource* pResource, CpuDescriptorHandle descriptorHandle, Format format, TextureDimension dimension, uint mipLevels, uint arraySize)
|
||||
private D3D12_SHADER_RESOURCE_VIEW_DESC CreateSrvDesc(ID3D12Resource* pResource, bool isCubeMap, uint mipLevels, uint arraySize)
|
||||
{
|
||||
var srvDesc = new ShaderResourceViewDescription
|
||||
var resourceDesc = pResource->GetDesc();
|
||||
var srvDesc = new D3D12_SHADER_RESOURCE_VIEW_DESC
|
||||
{
|
||||
Format = format,
|
||||
Format = resourceDesc.Format,
|
||||
Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING
|
||||
};
|
||||
|
||||
switch (dimension)
|
||||
switch (resourceDesc.Dimension)
|
||||
{
|
||||
case TextureDimension.Texture2D:
|
||||
srvDesc.ViewDimension = SrvDimension.Texture2D;
|
||||
srvDesc.Texture2D = new Texture2DSrv
|
||||
case D3D12_RESOURCE_DIMENSION_BUFFER:
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
|
||||
srvDesc.Buffer = new D3D12_BUFFER_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
FirstElement = 0,
|
||||
NumElements = (uint)(resourceDesc.Width / 4),
|
||||
StructureByteStride = 0,
|
||||
Flags = D3D12_BUFFER_SRV_FLAG_RAW,
|
||||
};
|
||||
break;
|
||||
case TextureDimension.Texture3D:
|
||||
srvDesc.ViewDimension = SrvDimension.Texture3D;
|
||||
srvDesc.Texture3D = new Texture3DSrv
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
||||
if (resourceDesc.DepthOrArraySize > 1)
|
||||
{
|
||||
MipLevels = 0,
|
||||
};
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
|
||||
srvDesc.Texture1DArray = new D3D12_TEX1D_ARRAY_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
ArraySize = arraySize,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
|
||||
srvDesc.Texture1D = new D3D12_TEX1D_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case TextureDimension.Texture2DArray:
|
||||
srvDesc.ViewDimension = SrvDimension.Texture2DArray;
|
||||
srvDesc.Texture2DArray = new Texture2DArraySrv
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
||||
if (resourceDesc.DepthOrArraySize > 1)
|
||||
{
|
||||
if (isCubeMap)
|
||||
{
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
|
||||
srvDesc.TextureCubeArray = new D3D12_TEXCUBE_ARRAY_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
NumCubes = arraySize / 6,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
srvDesc.ViewDimension = resourceDesc.SampleDesc.Count > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY : D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
|
||||
srvDesc.Texture2DArray = new D3D12_TEX2D_ARRAY_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
ArraySize = arraySize,
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isCubeMap)
|
||||
{
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
|
||||
srvDesc.TextureCube = new D3D12_TEXCUBE_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
srvDesc.ViewDimension = resourceDesc.SampleDesc.Count > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMS : D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D = new D3D12_TEX2D_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
||||
srvDesc.Texture3D = new D3D12_TEX3D_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
ArraySize = arraySize,
|
||||
};
|
||||
break;
|
||||
case TextureDimension.TextureCube:
|
||||
srvDesc.ViewDimension = SrvDimension.TextureCube;
|
||||
srvDesc.TextureCube = new TexureCubeSrv
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
};
|
||||
break;
|
||||
case TextureDimension.TextureCubeArray:
|
||||
srvDesc.ViewDimension = SrvDimension.TextureCubeArray;
|
||||
srvDesc.TextureCubeArray = new TexureCubeArraySrv
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
NumCubes = arraySize / 6,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unsupported texture dimension for SRV: {dimension}");
|
||||
throw new ArgumentException($"Unsupported texture dimension for SRV: {resourceDesc.Dimension}");
|
||||
}
|
||||
|
||||
_device->CreateShaderResourceView(pResource, &srvDesc, descriptorHandle);
|
||||
return srvDesc;
|
||||
}
|
||||
|
||||
private D3D12_RENDER_TARGET_VIEW_DESC CreateRtvDesc(ID3D12Resource* pResource, uint mipSlice = 0, uint firstArraySlice = 0, uint planeSlice = 0)
|
||||
{
|
||||
var resourceDesc = pResource->GetDesc();
|
||||
var rtvDesc = new D3D12_RENDER_TARGET_VIEW_DESC();
|
||||
|
||||
switch (resourceDesc.Dimension)
|
||||
{
|
||||
case D3D12_RESOURCE_DIMENSION_BUFFER:
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_BUFFER;
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
||||
rtvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_RTV_DIMENSION_TEXTURE1DARRAY : D3D12_RTV_DIMENSION_TEXTURE1D;
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
||||
if (resourceDesc.SampleDesc.Count > 1)
|
||||
{
|
||||
rtvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY : D3D12_RTV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DARRAY : D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Unsupported texture dimension for SRV: {resourceDesc.Dimension}");
|
||||
}
|
||||
|
||||
rtvDesc.Format = resourceDesc.Format;
|
||||
|
||||
var isArray =
|
||||
rtvDesc.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE2DARRAY ||
|
||||
rtvDesc.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
|
||||
var arraySize = 1u;
|
||||
if (isArray)
|
||||
{
|
||||
arraySize = resourceDesc.ArraySize() - firstArraySlice;
|
||||
}
|
||||
|
||||
switch (rtvDesc.ViewDimension)
|
||||
{
|
||||
case D3D12_RTV_DIMENSION_BUFFER:
|
||||
rtvDesc.Buffer.FirstElement = firstArraySlice;
|
||||
rtvDesc.Buffer.NumElements = arraySize;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE1D:
|
||||
rtvDesc.Texture1D.MipSlice = mipSlice;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE1DARRAY:
|
||||
rtvDesc.Texture1DArray.MipSlice = mipSlice;
|
||||
rtvDesc.Texture1DArray.FirstArraySlice = firstArraySlice;
|
||||
rtvDesc.Texture1DArray.ArraySize = arraySize;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE2D:
|
||||
rtvDesc.Texture2D.MipSlice = mipSlice;
|
||||
rtvDesc.Texture2D.PlaneSlice = planeSlice;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE2DARRAY:
|
||||
rtvDesc.Texture2DArray.MipSlice = mipSlice;
|
||||
rtvDesc.Texture2DArray.FirstArraySlice = firstArraySlice;
|
||||
rtvDesc.Texture2DArray.ArraySize = arraySize;
|
||||
rtvDesc.Texture2DArray.PlaneSlice = planeSlice;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE2DMS:
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY:
|
||||
rtvDesc.Texture2DMSArray.FirstArraySlice = firstArraySlice;
|
||||
rtvDesc.Texture2DMSArray.ArraySize = arraySize;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE3D:
|
||||
rtvDesc.Texture3D.MipSlice = mipSlice;
|
||||
rtvDesc.Texture3D.FirstWSlice = firstArraySlice;
|
||||
rtvDesc.Texture3D.WSize = arraySize;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Unsupported RTV dimension: {rtvDesc.ViewDimension}");
|
||||
}
|
||||
|
||||
return rtvDesc;
|
||||
}
|
||||
|
||||
private D3D12_DEPTH_STENCIL_VIEW_DESC CreateDsvDesc(ID3D12Resource* pResource, uint mipSlice = 0, uint firstArraySlice = 0, D3D12_DSV_FLAGS flags = D3D12_DSV_FLAG_NONE)
|
||||
{
|
||||
var resourceDesc = pResource->GetDesc();
|
||||
var dsvDesc = new D3D12_DEPTH_STENCIL_VIEW_DESC
|
||||
{
|
||||
Flags = flags,
|
||||
};
|
||||
|
||||
switch (resourceDesc.Dimension)
|
||||
{
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
||||
dsvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_DSV_DIMENSION_TEXTURE1DARRAY : D3D12_DSV_DIMENSION_TEXTURE1D;
|
||||
break;
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
||||
if (resourceDesc.SampleDesc.Count > 1)
|
||||
{
|
||||
dsvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY : D3D12_DSV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
dsvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DARRAY : D3D12_DSV_DIMENSION_TEXTURE2D;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dsvDesc.Format = resourceDesc.Format;
|
||||
|
||||
var isArray =
|
||||
dsvDesc.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DARRAY ||
|
||||
dsvDesc.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
|
||||
var arraySize = 1u;
|
||||
if (isArray)
|
||||
{
|
||||
arraySize = resourceDesc.ArraySize() - firstArraySlice;
|
||||
}
|
||||
|
||||
switch (dsvDesc.ViewDimension)
|
||||
{
|
||||
case D3D12_DSV_DIMENSION_TEXTURE1D:
|
||||
dsvDesc.Texture1D.MipSlice = mipSlice;
|
||||
break;
|
||||
case D3D12_DSV_DIMENSION_TEXTURE1DARRAY:
|
||||
dsvDesc.Texture1DArray.MipSlice = mipSlice;
|
||||
dsvDesc.Texture1DArray.FirstArraySlice = firstArraySlice;
|
||||
dsvDesc.Texture1DArray.ArraySize = arraySize;
|
||||
break;
|
||||
case D3D12_DSV_DIMENSION_TEXTURE2D:
|
||||
dsvDesc.Texture2D.MipSlice = mipSlice;
|
||||
break;
|
||||
case D3D12_DSV_DIMENSION_TEXTURE2DARRAY:
|
||||
dsvDesc.Texture2DArray.MipSlice = mipSlice;
|
||||
dsvDesc.Texture2DArray.FirstArraySlice = firstArraySlice;
|
||||
dsvDesc.Texture2DArray.ArraySize = arraySize;
|
||||
break;
|
||||
case D3D12_DSV_DIMENSION_TEXTURE2DMS:
|
||||
break;
|
||||
case D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY:
|
||||
dsvDesc.Texture2DMSArray.FirstArraySlice = firstArraySlice;
|
||||
dsvDesc.Texture2DMSArray.ArraySize = arraySize;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return dsvDesc;
|
||||
}
|
||||
|
||||
public Handle<Texture> CreateTexture(ref readonly TextureDesc desc, bool isTemp = false)
|
||||
@@ -154,33 +364,33 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
var resourceFlags = ConvertTextureUsage(desc.Usage);
|
||||
var resourceDesc = desc.Dimension switch
|
||||
{
|
||||
TextureDimension.Texture2D => ResourceDescription.Tex2D(
|
||||
TextureDimension.Texture2D => D3D12_RESOURCE_DESC.Tex2D(
|
||||
d3d12Format,
|
||||
desc.Width,
|
||||
desc.Height,
|
||||
mipLevels: mipLevels,
|
||||
flags: resourceFlags),
|
||||
TextureDimension.Texture3D => ResourceDescription.Tex3D(
|
||||
TextureDimension.Texture3D => D3D12_RESOURCE_DESC.Tex3D(
|
||||
d3d12Format,
|
||||
desc.Width,
|
||||
desc.Height,
|
||||
(ushort)desc.Slice,
|
||||
flags: resourceFlags),
|
||||
TextureDimension.TextureCube => ResourceDescription.Tex2D(
|
||||
TextureDimension.TextureCube => D3D12_RESOURCE_DESC.Tex2D(
|
||||
d3d12Format,
|
||||
desc.Width,
|
||||
desc.Height,
|
||||
mipLevels: mipLevels,
|
||||
arraySize: 6,
|
||||
flags: resourceFlags),
|
||||
TextureDimension.Texture2DArray => ResourceDescription.Tex2D(
|
||||
TextureDimension.Texture2DArray => D3D12_RESOURCE_DESC.Tex2D(
|
||||
d3d12Format,
|
||||
desc.Width,
|
||||
desc.Height,
|
||||
mipLevels: mipLevels,
|
||||
arraySize: (ushort)desc.Slice,
|
||||
flags: resourceFlags),
|
||||
TextureDimension.TextureCubeArray => ResourceDescription.Tex2D(
|
||||
TextureDimension.TextureCubeArray => D3D12_RESOURCE_DESC.Tex2D(
|
||||
d3d12Format,
|
||||
desc.Width,
|
||||
desc.Height,
|
||||
@@ -190,57 +400,64 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
_ => throw new ArgumentException($"Unsupported texture dimension: {desc.Dimension}"),
|
||||
};
|
||||
|
||||
var allocationDesc = new AllocationDesc
|
||||
var allocationDesc = new D3D12MA_ALLOCATION_DESC
|
||||
{
|
||||
HeapType = HeapType.Default,
|
||||
Flags = AllocationFlags.None
|
||||
HeapType = D3D12_HEAP_TYPE_DEFAULT,
|
||||
Flags = D3D12MA_ALLOCATION_FLAG_NONE
|
||||
};
|
||||
|
||||
var initialState = DetermineInitialTextureState(desc.Usage);
|
||||
|
||||
Allocation allocation = default;
|
||||
ThrowIfFailed(_allocator.CreateResource(&allocationDesc, in resourceDesc, initialState, null, &allocation, IID_NULL, null));
|
||||
ComPtr<D3D12MA_Allocation> allocation = default;
|
||||
ThrowIfFailed(_allocator.Get()->CreateResource(&allocationDesc, &resourceDesc, initialState, null, allocation.GetAddressOf(), IID_NULL, null));
|
||||
|
||||
var resourceDescriptor = D3D12ResourceDescriptor.Invalid;
|
||||
var resourceDescriptor = ResourceViewGroup.Invalid;
|
||||
if (desc.Usage.HasFlag(TextureUsage.ShaderResource))
|
||||
{
|
||||
resourceDescriptor.srv = _descriptorAllocator.AllocateCbvSrvUav(isTemp);
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.srv);
|
||||
|
||||
CreateSRV(allocation.Resource, cpuHandle, d3d12Format, desc.Dimension, mipLevels, desc.Slice);
|
||||
var isCubeMap = desc.Dimension == TextureDimension.TextureCube || desc.Dimension == TextureDimension.TextureCubeArray;
|
||||
var srvDesc = CreateSrvDesc(allocation.Get()->GetResource(), isCubeMap, mipLevels, desc.Slice);
|
||||
|
||||
_device.NativeDevice->CreateShaderResourceView(allocation.Get()->GetResource(), &srvDesc, cpuHandle);
|
||||
}
|
||||
|
||||
if (desc.Usage.HasFlag(TextureUsage.RenderTarget))
|
||||
{
|
||||
resourceDescriptor.rtv = _descriptorAllocator.AllocateRTV(isTemp);
|
||||
var rtvDesc = new RenderTargetViewDescription(allocation.Resource);
|
||||
_device->CreateRenderTargetView(allocation.Resource, &rtvDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.rtv));
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.rtv);
|
||||
var rtvDesc = CreateRtvDesc(allocation.Get()->GetResource());
|
||||
|
||||
_device.NativeDevice->CreateRenderTargetView(allocation.Get()->GetResource(), &rtvDesc, cpuHandle);
|
||||
}
|
||||
|
||||
if (desc.Usage.HasFlag(TextureUsage.DepthStencil))
|
||||
{
|
||||
resourceDescriptor.dsv = _descriptorAllocator.AllocateDSV(isTemp);
|
||||
var dsvDesc = new DepthStencilViewDescription(allocation.Resource);
|
||||
_device->CreateDepthStencilView(allocation.Resource, &dsvDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.dsv));
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.dsv);
|
||||
var dsvDesc = CreateDsvDesc(allocation.Get()->GetResource());
|
||||
|
||||
_device.NativeDevice->CreateDepthStencilView(allocation.Get()->GetResource(), &dsvDesc, cpuHandle);
|
||||
}
|
||||
|
||||
if (desc.Usage.HasFlag(TextureUsage.UnorderedAccess))
|
||||
{
|
||||
resourceDescriptor.uav = _descriptorAllocator.AllocateCbvSrvUav(isTemp);
|
||||
var uavDesc = new UnorderedAccessViewDescription
|
||||
var uavDesc = new D3D12_UNORDERED_ACCESS_VIEW_DESC
|
||||
{
|
||||
ViewDimension = UavDimension.Texture2D,
|
||||
ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D,
|
||||
Format = d3d12Format,
|
||||
Texture2D = new Texture2DUav
|
||||
Texture2D = new D3D12_TEX2D_UAV
|
||||
{
|
||||
MipSlice = 0,
|
||||
PlaneSlice = 0,
|
||||
}
|
||||
};
|
||||
_device->CreateUnorderedAccessView(allocation.Resource, null, &uavDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.uav));
|
||||
_device.NativeDevice->CreateUnorderedAccessView(allocation.Get()->GetResource(), null, &uavDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.uav));
|
||||
}
|
||||
|
||||
var handle = TrackResource(ref allocation, initialState, resourceDescriptor, ResourceDesc.Texture(desc), isTemp);
|
||||
var handle = TrackResource(allocation, initialState, resourceDescriptor, ResourceDesc.Texture(desc), isTemp);
|
||||
|
||||
return handle.AsTexture();
|
||||
}
|
||||
@@ -253,56 +470,56 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
|
||||
public Handle<GraphicsBuffer> CreateBuffer(ref readonly BufferDesc desc, bool isTemp = false)
|
||||
{
|
||||
CheckBufferSize((uint)desc.Size);
|
||||
CheckBufferSize(desc.Size);
|
||||
|
||||
var resourceDescription = ResourceDescription.Buffer(desc.Size, ConvertBufferUsage(desc.Usage));
|
||||
var allocationDesc = new AllocationDesc
|
||||
var resourceDescription = D3D12_RESOURCE_DESC.Buffer(desc.Size, ConvertBufferUsage(desc.Usage));
|
||||
var allocationDesc = new D3D12MA_ALLOCATION_DESC
|
||||
{
|
||||
HeapType = ConvertMemoryType(desc.MemoryType),
|
||||
Flags = AllocationFlags.None
|
||||
Flags = D3D12MA_ALLOCATION_FLAG_NONE
|
||||
};
|
||||
|
||||
var initialState = DetermineInitialBufferState(desc.Usage, desc.MemoryType);
|
||||
|
||||
Allocation allocation = default;
|
||||
ThrowIfFailed(_allocator.CreateResource(&allocationDesc, in resourceDescription, initialState, null, &allocation, IID_NULL, null));
|
||||
ComPtr<D3D12MA_Allocation> allocation = default;
|
||||
ThrowIfFailed(_allocator.Get()->CreateResource(&allocationDesc, &resourceDescription, initialState, null, allocation.GetAddressOf(), IID_NULL, null));
|
||||
|
||||
var resourceDescriptor = D3D12ResourceDescriptor.Invalid;
|
||||
if (desc.Usage.HasFlag(BufferUsage.ShaderResource) && desc.CreationFlags.HasFlag(BufferCreationFlags.Bindless))
|
||||
var resourceDescriptor = ResourceViewGroup.Invalid;
|
||||
if (desc.Usage.HasFlag(BufferUsage.ShaderResource))
|
||||
{
|
||||
resourceDescriptor.srv = _descriptorAllocator.AllocateCbvSrvUav(isTemp);
|
||||
|
||||
var srvDesc = new ShaderResourceViewDescription
|
||||
var srvDesc = new D3D12_SHADER_RESOURCE_VIEW_DESC
|
||||
{
|
||||
ViewDimension = SrvDimension.Buffer,
|
||||
ViewDimension = D3D12_SRV_DIMENSION_BUFFER,
|
||||
Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING
|
||||
};
|
||||
|
||||
if (desc.Usage.HasFlag(BufferUsage.Raw))
|
||||
{
|
||||
srvDesc.Format = Format.R32Typeless;
|
||||
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
|
||||
srvDesc.Buffer.FirstElement = 0;
|
||||
srvDesc.Buffer.NumElements = (uint)(desc.Size / 4);
|
||||
srvDesc.Buffer.NumElements = desc.Size / 4;
|
||||
srvDesc.Buffer.StructureByteStride = 0;
|
||||
srvDesc.Buffer.Flags = BufferSrvFlags.Raw;
|
||||
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
|
||||
}
|
||||
else
|
||||
{
|
||||
srvDesc.Format = Format.Unknown;
|
||||
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
srvDesc.Buffer.FirstElement = 0;
|
||||
srvDesc.Buffer.NumElements = (uint)(desc.Size / desc.Stride);
|
||||
srvDesc.Buffer.NumElements = desc.Size / desc.Stride;
|
||||
srvDesc.Buffer.StructureByteStride = desc.Stride;
|
||||
srvDesc.Buffer.Flags = BufferSrvFlags.None;
|
||||
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
|
||||
}
|
||||
|
||||
_device->CreateShaderResourceView(allocation.Resource, &srvDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.srv));
|
||||
_device.NativeDevice->CreateShaderResourceView(allocation.Get()->GetResource(), &srvDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.srv));
|
||||
}
|
||||
|
||||
var handle = TrackResource(ref allocation, initialState, resourceDescriptor, ResourceDesc.Buffer(desc), isTemp);
|
||||
var handle = TrackResource(allocation, initialState, resourceDescriptor, ResourceDesc.Buffer(desc), isTemp);
|
||||
return handle.AsGraphicsBuffer();
|
||||
}
|
||||
|
||||
public Handle<GraphicsBuffer> CreateUploadBuffer(ulong size, bool isTemp = true)
|
||||
public Handle<GraphicsBuffer> CreateUploadBuffer(uint size, bool isTemp = true)
|
||||
{
|
||||
var desc = new BufferDesc
|
||||
{
|
||||
@@ -318,20 +535,18 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
{
|
||||
var vertexBufferDesc = new BufferDesc
|
||||
{
|
||||
Size = (ulong)(vertices.Count * Unsafe.SizeOf<Vertex>()),
|
||||
Size = (uint)(vertices.Count * Unsafe.SizeOf<Vertex>()),
|
||||
Stride = (uint)Unsafe.SizeOf<Vertex>(),
|
||||
Usage = BufferUsage.Vertex | BufferUsage.ShaderResource,
|
||||
MemoryType = MemoryType.Default,
|
||||
CreationFlags = BufferCreationFlags.Bindless
|
||||
};
|
||||
|
||||
var indexBufferDesc = new BufferDesc
|
||||
{
|
||||
Size = (ulong)(indices.Count * sizeof(uint)),
|
||||
Size = (uint)(indices.Count * sizeof(uint)),
|
||||
Stride = sizeof(uint),
|
||||
Usage = BufferUsage.Index | BufferUsage.ShaderResource,
|
||||
MemoryType = MemoryType.Default,
|
||||
CreationFlags = BufferCreationFlags.Bindless
|
||||
};
|
||||
|
||||
var vertexBuffer = CreateBuffer(ref vertexBufferDesc);
|
||||
@@ -357,30 +572,20 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
|
||||
ref var shaderRef = ref _resourceDatabase.GetShaderReference(shader);
|
||||
|
||||
if (shaderRef.ConstantBuffers.Count > 0)
|
||||
var desc = new BufferDesc
|
||||
{
|
||||
var maxSlot = shaderRef.ConstantBuffers.Max(cb => cb.RegisterSlot);
|
||||
materialData._cBufferCaches = new UnsafeArray<CBufferCache>((int)maxSlot + 1, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
||||
Size = shaderRef.PerMaterialBufferInfo.Size,
|
||||
Usage = BufferUsage.Constant,
|
||||
MemoryType = MemoryType.Default,
|
||||
};
|
||||
|
||||
foreach (var cbufferInfo in shaderRef.ConstantBuffers)
|
||||
{
|
||||
var desc = new BufferDesc
|
||||
{
|
||||
Size = cbufferInfo.Size,
|
||||
Usage = BufferUsage.Constant,
|
||||
MemoryType = MemoryType.Default,
|
||||
};
|
||||
|
||||
var buffer = CreateBuffer(ref desc);
|
||||
|
||||
materialData._cBufferCaches[cbufferInfo.RegisterSlot] = new CBufferCache(buffer, cbufferInfo.Size);
|
||||
}
|
||||
}
|
||||
var buffer = CreateBuffer(ref desc);
|
||||
materialData._materialPropertiesCache = new CBufferCache(buffer, shaderRef.PerMaterialBufferInfo.Size);
|
||||
|
||||
return _resourceDatabase.AddMaterial(ref materialData);
|
||||
}
|
||||
|
||||
public Identifier<Shader> CreateShader()
|
||||
public Identifier<Shader> CreateShader(ShaderDescriptor descriptor)
|
||||
{
|
||||
var shaderData = new Shader();
|
||||
return _resourceDatabase.AddShader(ref shaderData);
|
||||
@@ -388,149 +593,136 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
|
||||
#region Conversion Methods
|
||||
|
||||
private static Format ConvertTextureFormat(TextureFormat format)
|
||||
private static DXGI_FORMAT ConvertTextureFormat(TextureFormat format)
|
||||
{
|
||||
return format switch
|
||||
{
|
||||
TextureFormat.R8G8B8A8_UNorm => Format.R8G8B8A8Unorm,
|
||||
TextureFormat.B8G8R8A8_UNorm => Format.B8G8R8A8Unorm,
|
||||
TextureFormat.R16G16B16A16_Float => Format.R16G16B16A16Float,
|
||||
TextureFormat.R32G32B32A32_Float => Format.R32G32B32A32Float,
|
||||
TextureFormat.D24_UNorm_S8_UInt => Format.D24UnormS8Uint,
|
||||
TextureFormat.D32_Float => Format.D32Float,
|
||||
TextureFormat.R8G8B8A8_UNorm => DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
TextureFormat.B8G8R8A8_UNorm => DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
TextureFormat.R16G16B16A16_Float => DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
TextureFormat.R32G32B32A32_Float => DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
TextureFormat.D24_UNorm_S8_UInt => DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
TextureFormat.D32_Float => DXGI_FORMAT_D32_FLOAT,
|
||||
_ => throw new ArgumentException($"Unsupported texture format: {format}")
|
||||
};
|
||||
}
|
||||
|
||||
private static ResourceFlags ConvertTextureUsage(TextureUsage usage)
|
||||
private static D3D12_RESOURCE_FLAGS ConvertTextureUsage(TextureUsage usage)
|
||||
{
|
||||
var flags = ResourceFlags.None;
|
||||
var flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
if (usage.HasFlag(TextureUsage.RenderTarget))
|
||||
{
|
||||
flags |= ResourceFlags.AllowRenderTarget;
|
||||
flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(TextureUsage.DepthStencil))
|
||||
{
|
||||
flags |= ResourceFlags.AllowDepthStencil;
|
||||
flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(TextureUsage.UnorderedAccess))
|
||||
{
|
||||
flags |= ResourceFlags.AllowUnorderedAccess;
|
||||
flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
private static ResourceFlags ConvertBufferUsage(BufferUsage usage)
|
||||
private static D3D12_RESOURCE_FLAGS ConvertBufferUsage(BufferUsage usage)
|
||||
{
|
||||
var flags = ResourceFlags.None;
|
||||
var flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
if (usage.HasFlag(BufferUsage.Raw))
|
||||
{
|
||||
flags |= ResourceFlags.AllowUnorderedAccess;
|
||||
flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
private static HeapType ConvertMemoryType(MemoryType memoryType)
|
||||
private static D3D12_HEAP_TYPE ConvertMemoryType(MemoryType memoryType)
|
||||
{
|
||||
return memoryType switch
|
||||
{
|
||||
MemoryType.Default => HeapType.Default,
|
||||
MemoryType.Upload => HeapType.Upload,
|
||||
MemoryType.Readback => HeapType.Readback,
|
||||
MemoryType.Default => D3D12_HEAP_TYPE_DEFAULT,
|
||||
MemoryType.Upload => D3D12_HEAP_TYPE_UPLOAD,
|
||||
MemoryType.Readback => D3D12_HEAP_TYPE_READBACK,
|
||||
_ => throw new ArgumentException($"Unsupported memory type: {memoryType}")
|
||||
};
|
||||
}
|
||||
|
||||
private static ResourceStates DetermineInitialTextureState(TextureUsage usage)
|
||||
private static D3D12_RESOURCE_STATES DetermineInitialTextureState(TextureUsage usage)
|
||||
{
|
||||
if (usage.HasFlag(TextureUsage.RenderTarget))
|
||||
{
|
||||
return ResourceStates.RenderTarget;
|
||||
return D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(TextureUsage.DepthStencil))
|
||||
{
|
||||
return ResourceStates.DepthWrite;
|
||||
return D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(TextureUsage.UnorderedAccess))
|
||||
{
|
||||
return ResourceStates.UnorderedAccess;
|
||||
return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
}
|
||||
|
||||
return ResourceStates.Common;
|
||||
return D3D12_RESOURCE_STATE_COMMON;
|
||||
}
|
||||
|
||||
private static ResourceStates DetermineInitialBufferState(BufferUsage usage, MemoryType memoryType)
|
||||
private static D3D12_RESOURCE_STATES DetermineInitialBufferState(BufferUsage usage, MemoryType memoryType)
|
||||
{
|
||||
if (memoryType == MemoryType.Upload)
|
||||
{
|
||||
return ResourceStates.GenericRead;
|
||||
return D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||
}
|
||||
|
||||
if (memoryType == MemoryType.Readback)
|
||||
{
|
||||
return ResourceStates.CopyDest;
|
||||
return D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(BufferUsage.Vertex))
|
||||
{
|
||||
return ResourceStates.VertexAndConstantBuffer;
|
||||
return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(BufferUsage.Index))
|
||||
{
|
||||
return ResourceStates.IndexBuffer;
|
||||
return D3D12_RESOURCE_STATE_INDEX_BUFFER;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(BufferUsage.Constant))
|
||||
{
|
||||
return ResourceStates.VertexAndConstantBuffer;
|
||||
return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
|
||||
}
|
||||
|
||||
return ResourceStates.Common;
|
||||
return D3D12_RESOURCE_STATE_COMMON;
|
||||
}
|
||||
|
||||
private static ResourceState D3D12StatesToRHIState(ResourceStates states)
|
||||
private static ResourceState D3D12StatesToRHIState(D3D12_RESOURCE_STATES states)
|
||||
{
|
||||
switch (states)
|
||||
return states switch
|
||||
{
|
||||
//case ResourceStates.None:
|
||||
//case ResourceStates.Present:
|
||||
case ResourceStates.Common:
|
||||
return ResourceState.Common;
|
||||
case ResourceStates.VertexAndConstantBuffer:
|
||||
return ResourceState.VertexAndConstantBuffer;
|
||||
case ResourceStates.IndexBuffer:
|
||||
return ResourceState.IndexBuffer;
|
||||
case ResourceStates.RenderTarget:
|
||||
return ResourceState.RenderTarget;
|
||||
case ResourceStates.UnorderedAccess:
|
||||
return ResourceState.UnorderedAccess;
|
||||
case ResourceStates.DepthWrite:
|
||||
return ResourceState.DepthWrite;
|
||||
case ResourceStates.DepthRead:
|
||||
return ResourceState.DepthRead;
|
||||
case ResourceStates.PixelShaderResource:
|
||||
return ResourceState.PixelShaderResource;
|
||||
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,
|
||||
//case ResourceStates.Predication:
|
||||
case ResourceStates.IndirectArgument:
|
||||
return ResourceState.IndirectArgument;
|
||||
case ResourceStates.CopyDest:
|
||||
return ResourceState.CopyDest;
|
||||
case ResourceStates.CopySource:
|
||||
return ResourceState.CopySource;
|
||||
case ResourceStates.GenericRead:
|
||||
return ResourceState.GenericRead;
|
||||
default:
|
||||
return ResourceState.Common;
|
||||
}
|
||||
D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT => ResourceState.IndirectArgument,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST => ResourceState.CopyDest,
|
||||
D3D12_RESOURCE_STATE_COPY_SOURCE => ResourceState.CopySource,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ => ResourceState.GenericRead,
|
||||
_ => ResourceState.Common,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -580,7 +772,7 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
}
|
||||
|
||||
_temResources.Dispose();
|
||||
_allocator.Release();
|
||||
_allocator.Dispose();
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user