feat: Implement D3D12 resource factory and improve swap chain management
- Added D3D12ResourceFactory for creating render targets, textures, and buffers. - Enhanced D3D12SwapChain to manage back buffer render targets and provide access to them. - Updated D3D12Texture to utilize resource handles for better resource management. - Removed legacy ResourceAllocator and integrated improvements for resource handling. - Introduced new interfaces for resource factory and swap chain to streamline resource creation. - Added support for mip levels and texture dimensions in render target and texture descriptions. - Created new markdown files to document allocator and swap chain improvements.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using Ghost.Graphics.Data;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Win32;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
@@ -5,110 +6,85 @@ using Win32.Graphics.Direct3D12;
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
/// <summary>
|
||||
/// D3D12 implementation of texture interface
|
||||
/// D3D12 implementation of texture interface using resource handles
|
||||
/// </summary>
|
||||
internal unsafe class D3D12Texture : ITexture
|
||||
{
|
||||
private ComPtr<ID3D12Resource> _resource;
|
||||
private readonly TextureHandle _handle;
|
||||
private readonly ComPtr<ID3D12Resource> _externalResource;
|
||||
private ResourceState _currentState;
|
||||
private bool _disposed;
|
||||
|
||||
public uint Width { get; }
|
||||
public uint Height { get; }
|
||||
public TextureFormat Format { get; }
|
||||
public uint MipLevels { get; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public ulong Size { get; }
|
||||
public uint Width
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public uint Height
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public TextureFormat Format
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public uint MipLevels
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get; set;
|
||||
} = string.Empty;
|
||||
|
||||
public ulong Size
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public ResourceState CurrentState => _currentState;
|
||||
|
||||
public ID3D12Resource* NativeResource => _resource.Get();
|
||||
public ID3D12Resource* NativeResource => _handle.IsValid ? _handle.ResourceHandle.GetAllocation().Resource : _externalResource.Get();
|
||||
|
||||
public D3D12Texture(ComPtr<ID3D12Resource> resource, uint width, uint height, TextureFormat format, uint mipLevels = 1)
|
||||
{
|
||||
_resource = resource.Move();
|
||||
_handle = TextureHandle.Invalid;
|
||||
_externalResource = resource.Move();
|
||||
|
||||
Width = width;
|
||||
Height = height;
|
||||
Format = format;
|
||||
MipLevels = mipLevels;
|
||||
_currentState = ResourceState.Common;
|
||||
|
||||
var desc = _resource.Get()->GetDesc();
|
||||
Size = (ulong)(desc.Width * desc.Height * GetBytesPerPixel(format));
|
||||
Size = Width * Height * GetBytesPerPixel(Format);
|
||||
}
|
||||
|
||||
public D3D12Texture(ComPtr<ID3D12Device14> device, TextureDesc desc)
|
||||
public D3D12Texture(TextureHandle handle, ref readonly TextureDesc desc)
|
||||
{
|
||||
_handle = handle;
|
||||
_externalResource = default;
|
||||
|
||||
Width = desc.Width;
|
||||
Height = desc.Height;
|
||||
Format = desc.Format;
|
||||
MipLevels = desc.MipLevels;
|
||||
|
||||
var mipLevels = desc.MipLevels;
|
||||
if (mipLevels <= 0)
|
||||
{
|
||||
mipLevels = (uint)(Math.Floor(Math.Log2(Math.Max(Width, Height))) + 1);
|
||||
}
|
||||
|
||||
MipLevels = mipLevels;
|
||||
_currentState = ResourceState.Common;
|
||||
|
||||
CreateTexture(device, desc);
|
||||
Size = (ulong)(Width * Height * GetBytesPerPixel(Format));
|
||||
Size = Width * Height * GetBytesPerPixel(Format);
|
||||
}
|
||||
|
||||
private void CreateTexture(ComPtr<ID3D12Device14> device, TextureDesc desc)
|
||||
~D3D12Texture()
|
||||
{
|
||||
var resourceDesc = new ResourceDescription
|
||||
{
|
||||
Dimension = ResourceDimension.Texture2D,
|
||||
Alignment = 0,
|
||||
Width = desc.Width,
|
||||
Height = desc.Height,
|
||||
DepthOrArraySize = 1,
|
||||
MipLevels = (ushort)desc.MipLevels,
|
||||
Format = ConvertTextureFormat(desc.Format),
|
||||
SampleDesc = new Win32.Graphics.Dxgi.Common.SampleDescription(1, 0),
|
||||
Layout = TextureLayout.Unknown,
|
||||
Flags = ConvertTextureUsage(desc.Usage)
|
||||
};
|
||||
|
||||
var heapProps = new HeapProperties
|
||||
{
|
||||
Type = HeapType.Default,
|
||||
CPUPageProperty = CpuPageProperty.Unknown,
|
||||
MemoryPoolPreference = MemoryPool.Unknown,
|
||||
CreationNodeMask = 1,
|
||||
VisibleNodeMask = 1
|
||||
};
|
||||
|
||||
device.Get()->CreateCommittedResource(
|
||||
&heapProps,
|
||||
HeapFlags.None,
|
||||
&resourceDesc,
|
||||
Win32.Graphics.Direct3D12.ResourceStates.Common,
|
||||
null,
|
||||
__uuidof<ID3D12Resource>(),
|
||||
_resource.GetVoidAddressOf());
|
||||
}
|
||||
|
||||
private static Win32.Graphics.Dxgi.Common.Format ConvertTextureFormat(TextureFormat format)
|
||||
{
|
||||
return format switch
|
||||
{
|
||||
TextureFormat.R8G8B8A8_UNorm => Win32.Graphics.Dxgi.Common.Format.R8G8B8A8Unorm,
|
||||
TextureFormat.B8G8R8A8_UNorm => Win32.Graphics.Dxgi.Common.Format.B8G8R8A8Unorm,
|
||||
TextureFormat.R16G16B16A16_Float => Win32.Graphics.Dxgi.Common.Format.R16G16B16A16Float,
|
||||
TextureFormat.R32G32B32A32_Float => Win32.Graphics.Dxgi.Common.Format.R32G32B32A32Float,
|
||||
TextureFormat.D24_UNorm_S8_UInt => Win32.Graphics.Dxgi.Common.Format.D24UnormS8Uint,
|
||||
TextureFormat.D32_Float => Win32.Graphics.Dxgi.Common.Format.D32Float,
|
||||
_ => throw new ArgumentException($"Unsupported texture format: {format}")
|
||||
};
|
||||
}
|
||||
|
||||
private static ResourceFlags ConvertTextureUsage(TextureUsage usage)
|
||||
{
|
||||
var flags = ResourceFlags.None;
|
||||
|
||||
if ((usage & TextureUsage.RenderTarget) != 0)
|
||||
flags |= ResourceFlags.AllowRenderTarget;
|
||||
if ((usage & TextureUsage.DepthStencil) != 0)
|
||||
flags |= ResourceFlags.AllowDepthStencil;
|
||||
if ((usage & TextureUsage.UnorderedAccess) != 0)
|
||||
flags |= ResourceFlags.AllowUnorderedAccess;
|
||||
|
||||
return flags;
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private static uint GetBytesPerPixel(TextureFormat format)
|
||||
@@ -125,11 +101,29 @@ internal unsafe class D3D12Texture : ITexture
|
||||
};
|
||||
}
|
||||
|
||||
public void SetCurrentState(ResourceState state)
|
||||
{
|
||||
_currentState = state;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_handle.IsValid)
|
||||
{
|
||||
_handle.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
_externalResource.Dispose();
|
||||
}
|
||||
|
||||
_resource.Dispose();
|
||||
_disposed = true;
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user