Refactor: add command allocator & render target strategies
Major refactor of graphics infrastructure: - Introduce ICommandAllocator and D3D12CommandAllocator for explicit command buffer management. - Change ICommandBuffer.Begin to require an allocator. - Add IRenderTargetStrategy abstraction with swap chain and texture implementations. - Update IRenderer to use RenderTargetStrategy instead of direct handle. - Add DPI scaling support to swap chains (ScaleX/ScaleY, SetScale). - RenderSystem now supports thread-safe swap chain resize requests. - Remove persistent copy command buffer; use per-frame allocators. - Make Logger public/static and clean up API visibility. - Update .editorconfig and debug layer enablement. These changes improve modularity, DPI-awareness, and future extensibility.
This commit is contained in:
34
Ghost.Graphics/D3D12/D3D12CommandAllocator.cs
Normal file
34
Ghost.Graphics/D3D12/D3D12CommandAllocator.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Ghost.Core.Utilities;
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel;
|
||||
using TerraFX.Interop.DirectX;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
internal unsafe class D3D12CommandAllocator : ICommandAllocator
|
||||
{
|
||||
private UniquePtr<ID3D12CommandAllocator> _allocator;
|
||||
|
||||
public SharedPtr<ID3D12CommandAllocator> NativeAllocator => _allocator.Share();
|
||||
|
||||
public D3D12CommandAllocator(D3D12RenderDevice device, CommandBufferType type)
|
||||
{
|
||||
ID3D12CommandAllocator* pAllocator = default;
|
||||
var commandListType = D3D12Utility.ToCommandListType(type);
|
||||
|
||||
device.NativeDevice.Get()->CreateCommandAllocator(commandListType, __uuidof(pAllocator), (void**)&pAllocator);
|
||||
|
||||
_allocator.Attach(pAllocator);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_allocator.Get()->Reset();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_allocator.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ namespace Ghost.Graphics.D3D12;
|
||||
internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
{
|
||||
private UniquePtr<ID3D12GraphicsCommandList10> _commandList;
|
||||
private UniquePtr<ID3D12CommandAllocator> _allocator;
|
||||
|
||||
private readonly D3D12PipelineLibrary _pipelineLibrary;
|
||||
private readonly D3D12ResourceDatabase _resourceDatabase;
|
||||
@@ -62,14 +61,11 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
{
|
||||
_type = type;
|
||||
|
||||
ID3D12CommandAllocator* pAllocator = default;
|
||||
ID3D12GraphicsCommandList10* pCommandList = default;
|
||||
var commandListType = ConvertCommandBufferType(type);
|
||||
var commandListType = D3D12Utility.ToCommandListType(type);
|
||||
|
||||
device.NativeDevice.Get()->CreateCommandAllocator(commandListType, __uuidof(pAllocator), (void**)&pAllocator);
|
||||
device.NativeDevice.Get()->CreateCommandList1(0u, commandListType, D3D12_COMMAND_LIST_FLAG_NONE, __uuidof(pCommandList), (void**)&pCommandList);
|
||||
|
||||
_allocator.Attach(pAllocator);
|
||||
_commandList.Attach(pCommandList);
|
||||
|
||||
_pipelineLibrary = stateController;
|
||||
@@ -85,17 +81,6 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private static D3D12_COMMAND_LIST_TYPE ConvertCommandBufferType(CommandBufferType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
CommandBufferType.Graphics => D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
CommandBufferType.Compute => D3D12_COMMAND_LIST_TYPE_COMPUTE,
|
||||
CommandBufferType.Copy => D3D12_COMMAND_LIST_TYPE_COPY,
|
||||
_ => throw new ArgumentException($"Unknown command buffer type: {type}")
|
||||
};
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void ThrowIfDisposed()
|
||||
{
|
||||
@@ -145,32 +130,28 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Begin()
|
||||
public void Begin(ICommandAllocator allocator)
|
||||
{
|
||||
void ResetCommandList()
|
||||
ThrowIfDisposed();
|
||||
ThrowIfRecording();
|
||||
|
||||
if (allocator is not D3D12CommandAllocator d3d12Allocator)
|
||||
{
|
||||
ThrowIfFailed(_allocator.Get()->Reset());
|
||||
ThrowIfFailed(_commandList.Get()->Reset(_allocator.Get(), null));
|
||||
throw new ArgumentException("Invalid command allocator type", nameof(allocator));
|
||||
}
|
||||
|
||||
void SetBindlessHeap()
|
||||
ThrowIfFailed(_commandList.Get()->Reset(d3d12Allocator.NativeAllocator, null));
|
||||
|
||||
if (Type == CommandBufferType.Graphics || Type == CommandBufferType.Compute)
|
||||
{
|
||||
// Set descriptor heaps for bindless resources and samplers
|
||||
|
||||
var heaps = stackalloc ID3D12DescriptorHeap*[2];
|
||||
heaps[0] = _descriptorAllocator.GetCbvSrvUavHeap(); // Bindless resource heap
|
||||
heaps[1] = _descriptorAllocator.GetSamplerHeap(); // Bindless sampler heap
|
||||
_commandList.Get()->SetDescriptorHeaps(2, heaps);
|
||||
}
|
||||
|
||||
ThrowIfDisposed();
|
||||
ThrowIfRecording();
|
||||
|
||||
ResetCommandList();
|
||||
|
||||
if (Type == CommandBufferType.Graphics || Type == CommandBufferType.Compute)
|
||||
{
|
||||
SetBindlessHeap();
|
||||
}
|
||||
|
||||
_commandCount = 0;
|
||||
_isRecording = true;
|
||||
}
|
||||
@@ -684,7 +665,6 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
}
|
||||
|
||||
_commandList.Dispose();
|
||||
_allocator.Dispose();
|
||||
_commandCount = 0;
|
||||
|
||||
_disposed = true;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#if DEBUG
|
||||
#define ENABLE_DEBUG
|
||||
#endif
|
||||
|
||||
using Ghost.Core;
|
||||
using Ghost.Graphics.Contracts;
|
||||
using Ghost.Graphics.RHI;
|
||||
@@ -11,7 +15,7 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
{
|
||||
private readonly IRenderSystem _renderSystem;
|
||||
|
||||
#if DEBUG
|
||||
#if ENABLE_DEBUG
|
||||
private readonly D3D12DebugLayer _debugLayer;
|
||||
#endif
|
||||
|
||||
@@ -21,7 +25,6 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
private readonly D3D12ResourceDatabase _resourceDatabase;
|
||||
private readonly D3D12PipelineLibrary _pipelineLibrary;
|
||||
private readonly D3D12ResourceAllocator _resourceAllocator;
|
||||
private readonly D3D12CommandBuffer _copyCommandBuffer;
|
||||
|
||||
private ImmutableArray<IRenderer> _renderers;
|
||||
|
||||
@@ -32,13 +35,12 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
public IPipelineLibrary PipelineLibrary => _pipelineLibrary;
|
||||
public IResourceDatabase ResourceDatabase => _resourceDatabase;
|
||||
public IResourceAllocator ResourceAllocator => _resourceAllocator;
|
||||
public ICommandBuffer CopyCommandBuffer => _copyCommandBuffer;
|
||||
|
||||
public D3D12GraphicsEngine(IRenderSystem renderSystem)
|
||||
{
|
||||
_renderSystem = renderSystem;
|
||||
|
||||
#if DEBUG
|
||||
#if ENABLE_DEBUG
|
||||
_debugLayer = new D3D12DebugLayer();
|
||||
#endif
|
||||
_device = new D3D12RenderDevice();
|
||||
@@ -49,14 +51,6 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
_pipelineLibrary = new D3D12PipelineLibrary(_device, _resourceDatabase);
|
||||
_resourceAllocator = new D3D12ResourceAllocator(renderSystem, _device, _descriptorAllocator, _resourceDatabase, _pipelineLibrary);
|
||||
|
||||
_copyCommandBuffer = new D3D12CommandBuffer(
|
||||
_device,
|
||||
_pipelineLibrary,
|
||||
_resourceDatabase,
|
||||
_resourceAllocator,
|
||||
_descriptorAllocator,
|
||||
CommandBufferType.Copy);
|
||||
|
||||
_renderers = ImmutableArray<IRenderer>.Empty;
|
||||
|
||||
_pipelineLibrary.InitializeLibrary(null);
|
||||
@@ -94,6 +88,11 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
ImmutableInterlocked.Update(ref _renderers, renderers => renderers.Clear());
|
||||
}
|
||||
|
||||
public ICommandAllocator CreateCommandAllocator(CommandBufferType type = CommandBufferType.Graphics)
|
||||
{
|
||||
return new D3D12CommandAllocator(_device, type);
|
||||
}
|
||||
|
||||
public ICommandBuffer CreateCommandBuffer(CommandBufferType type = CommandBufferType.Graphics)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -113,22 +112,27 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
return new D3D12SwapChain(_resourceDatabase, _descriptorAllocator, _device, desc, _renderSystem.MaxFrameLatency);
|
||||
}
|
||||
|
||||
public void RenderFrame(ICommandBuffer commandBuffer)
|
||||
public Result RenderFrame(ICommandAllocator commandAllocator)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
_copyCommandBuffer.Begin();
|
||||
var r = Result.Success();
|
||||
|
||||
foreach (var renderer in _renderers)
|
||||
{
|
||||
renderer.Render(commandBuffer);
|
||||
r = renderer.Render(commandAllocator);
|
||||
if (r.IsFailure)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_copyCommandBuffer.End().ThrowIfFailed();
|
||||
_resourceAllocator.ReleaseTempResources();
|
||||
_descriptorAllocator.ResetCbvSrvUavDynamicHeap();
|
||||
_descriptorAllocator.ResetDSVDynamicHeap();
|
||||
_descriptorAllocator.ResetRTVDynamicHeap();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -138,8 +142,6 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
return;
|
||||
}
|
||||
|
||||
_copyCommandBuffer.Dispose();
|
||||
|
||||
_resourceAllocator.Dispose();
|
||||
_pipelineLibrary.Dispose();
|
||||
_resourceDatabase.Dispose();
|
||||
@@ -147,7 +149,7 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
_descriptorAllocator.Dispose();
|
||||
_shaderCompiler.Dispose();
|
||||
_device.Dispose();
|
||||
#if DEBUG
|
||||
#if ENABLE_DEBUG
|
||||
_debugLayer.Dispose();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ internal unsafe class D3D12RenderDevice : IRenderDevice
|
||||
public ICommandQueue ComputeQueue => _computeQueue;
|
||||
public ICommandQueue CopyQueue => _copyQueue;
|
||||
|
||||
public SharedPtr<IDXGIFactory7> DXGIFactory => _dxgiFactory.Get();
|
||||
public SharedPtr<ID3D12Device14> NativeDevice => _device.Get();
|
||||
public SharedPtr<IDXGIAdapter1> Adapter => _adapter.Get();
|
||||
public SharedPtr<IDXGIFactory7> DXGIFactory => _dxgiFactory.Share();
|
||||
public SharedPtr<ID3D12Device14> NativeDevice => _device.Share();
|
||||
public SharedPtr<IDXGIAdapter1> Adapter => _adapter.Share();
|
||||
public SharedPtr<ID3D12CommandQueue> NativeGraphicsQueue => _graphicsQueue.NativeQueue;
|
||||
public SharedPtr<ID3D12CommandQueue> NativeComputeQueue => _computeQueue.NativeQueue;
|
||||
public SharedPtr<ID3D12CommandQueue> NativeCopyQueue => _copyQueue.NativeQueue;
|
||||
|
||||
@@ -2,6 +2,7 @@ using Ghost.Core;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Ghost.Graphics.Core;
|
||||
using Ghost.Graphics.RenderPasses;
|
||||
using Ghost.Graphics.Contracts;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -10,48 +11,30 @@ namespace Ghost.Graphics.D3D12;
|
||||
/// </summary>
|
||||
internal class D3D12Renderer : IRenderer
|
||||
{
|
||||
private struct FrameResource : IDisposable
|
||||
{
|
||||
public ICommandBuffer commandBuffer;
|
||||
public ulong fenceValue;
|
||||
|
||||
public FrameResource(D3D12GraphicsEngine graphicsEngine, int index)
|
||||
{
|
||||
commandBuffer = graphicsEngine.CreateCommandBuffer();
|
||||
commandBuffer.Name = $"Frame Command Buffer {index}";
|
||||
fenceValue = 0;
|
||||
}
|
||||
|
||||
public readonly void Dispose()
|
||||
{
|
||||
commandBuffer?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private readonly D3D12GraphicsEngine _graphicsEngine;
|
||||
private uint _frameIndex;
|
||||
|
||||
private readonly D3D12ResourceDatabase _resourceDatabase;
|
||||
|
||||
private Handle<Texture> _renderTarget;
|
||||
private readonly ICommandBuffer _commandBuffer;
|
||||
|
||||
private uint _frameIndex;
|
||||
private bool _disposed;
|
||||
|
||||
// NOTE: Testing only.
|
||||
private readonly MeshRenderPass _pass;
|
||||
|
||||
public Handle<Texture> RenderTarget => _renderTarget;
|
||||
public IRenderTargetStrategy? RenderTargetStrategy
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
// TODO: Add render passes support
|
||||
// private ImmutableArray<IRenderPass> _renderPasses;
|
||||
// TODO: Add render graph support
|
||||
|
||||
public D3D12Renderer(D3D12GraphicsEngine graphicsEngine, D3D12ResourceDatabase resourceDatabase)
|
||||
{
|
||||
_graphicsEngine = graphicsEngine;
|
||||
_resourceDatabase = resourceDatabase;
|
||||
|
||||
_renderTarget = Handle<Texture>.Invalid;
|
||||
|
||||
_commandBuffer = _graphicsEngine.CreateCommandBuffer(CommandBufferType.Graphics);
|
||||
|
||||
// NOTE: Testing only.
|
||||
_pass = new();
|
||||
@@ -62,36 +45,47 @@ internal class D3D12Renderer : IRenderer
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public void SetRenderTarget(Handle<Texture> renderTarget)
|
||||
public Result Render(ICommandAllocator commandAllocator)
|
||||
{
|
||||
_resourceDatabase.ReleaseResource(_renderTarget.AsResource());
|
||||
_renderTarget = renderTarget;
|
||||
}
|
||||
|
||||
public Result Render(ICommandBuffer commandBuffer)
|
||||
{
|
||||
if (!_renderTarget.IsValid)
|
||||
if (RenderTargetStrategy is null)
|
||||
{
|
||||
return Result.Failure("Render target is not set.");
|
||||
return Result.Failure("Render target strategy is not set.");
|
||||
}
|
||||
|
||||
commandBuffer.Begin();
|
||||
var target = RenderTargetStrategy.GetRenderTarget();
|
||||
if (target.IsNotValid)
|
||||
{
|
||||
return Result.Failure("Render target is invalid.");
|
||||
}
|
||||
|
||||
_commandBuffer.Begin(commandAllocator);
|
||||
RenderTargetStrategy.BeginRender(_commandBuffer);
|
||||
|
||||
// NOTE: Temperary solution: render directly to the swap chain back buffer if available.
|
||||
// HACK: This is hard coded for testing purposes only.
|
||||
|
||||
var error = RenderScene(_renderTarget, commandBuffer);
|
||||
var error = RenderScene(target);
|
||||
if (error != ErrorStatus.None)
|
||||
{
|
||||
commandBuffer.End();
|
||||
_commandBuffer.End();
|
||||
return Result.Failure(error);
|
||||
}
|
||||
|
||||
return commandBuffer.End();
|
||||
RenderTargetStrategy.EndRender(_commandBuffer);
|
||||
var r = _commandBuffer.End();
|
||||
if (r.IsFailure)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
_graphicsEngine.Device.GraphicsQueue.Submit(_commandBuffer);
|
||||
RenderTargetStrategy.Present();
|
||||
|
||||
return Result.Success();
|
||||
}
|
||||
|
||||
// TODO: A proper render graph integration.
|
||||
private ErrorStatus RenderScene(Handle<Texture> target, ICommandBuffer cmd)
|
||||
private ErrorStatus RenderScene(Handle<Texture> target)
|
||||
{
|
||||
var clearColor = new Color128 { r = 1.0f, g = 0.0f, b = 1.0f, a = 1.0f };
|
||||
|
||||
@@ -112,7 +106,7 @@ internal class D3D12Renderer : IRenderer
|
||||
};
|
||||
|
||||
// NOTE: Testing only.
|
||||
var ctx = new RenderingContext(_graphicsEngine, cmd, _graphicsEngine.CopyCommandBuffer, null!);
|
||||
var ctx = new RenderingContext(_graphicsEngine, _commandBuffer);
|
||||
if (_frameIndex == 0)
|
||||
{
|
||||
_pass.Initialize(ref ctx);
|
||||
@@ -124,18 +118,20 @@ internal class D3D12Renderer : IRenderer
|
||||
return result.Error;
|
||||
}
|
||||
|
||||
// TODO: Decouple viewport and scissor from the texture size.
|
||||
var texDesc = result.Value.TextureDescription;
|
||||
var viewport = new ViewportDesc { Width = texDesc.Width, Height = texDesc.Height, MinDepth = 0, MaxDepth = 1 };
|
||||
var scissor = new RectDesc { Right = texDesc.Width, Bottom = texDesc.Height };
|
||||
|
||||
cmd.BeginRenderPass(rtDesc, depthDesc, false);
|
||||
cmd.SetViewport(viewport);
|
||||
cmd.SetScissorRect(scissor);
|
||||
_commandBuffer.BeginRenderPass(rtDesc, depthDesc, false);
|
||||
_commandBuffer.SetViewport(viewport);
|
||||
_commandBuffer.SetScissorRect(scissor);
|
||||
|
||||
// NOTE: Testing only.
|
||||
_pass.Execute(ref ctx);
|
||||
|
||||
cmd.EndRenderPass();
|
||||
_commandBuffer.EndRenderPass();
|
||||
_frameIndex++;
|
||||
|
||||
return ErrorStatus.None;
|
||||
}
|
||||
@@ -150,6 +146,8 @@ internal class D3D12Renderer : IRenderer
|
||||
// NOTE: Testing only.
|
||||
_pass.Cleanup(_resourceDatabase);
|
||||
|
||||
_commandBuffer.Dispose();
|
||||
|
||||
_disposed = true;
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
@@ -104,7 +104,6 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
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 int _lastSamplerId;
|
||||
private bool _disposed;
|
||||
|
||||
public D3D12ResourceDatabase(D3D12DescriptorAllocator descriptorAllocator)
|
||||
@@ -120,8 +119,6 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
_materials = new UnsafeSlotMap<Material>(16, Allocator.Persistent, AllocationOption.Clear);
|
||||
_shaders = new DynamicArray<Shader?>(16);
|
||||
_shaderPasses = new Dictionary<ShaderPassKey, ShaderPass>(16);
|
||||
|
||||
_lastSamplerId = -1;
|
||||
}
|
||||
|
||||
~D3D12ResourceDatabase()
|
||||
|
||||
@@ -42,6 +42,16 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public float ScaleX
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public float ScaleY
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public D3D12SwapChain(D3D12ResourceDatabase resourceDatabase, D3D12DescriptorAllocator descriptorAllocator, D3D12RenderDevice device, SwapChainDesc desc, uint bufferCount)
|
||||
{
|
||||
Debug.Assert(bufferCount >= 2);
|
||||
@@ -55,8 +65,11 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
Width = desc.Width;
|
||||
Height = desc.Height;
|
||||
|
||||
CreateSwapChain(desc, bufferCount);
|
||||
var pSwapChian = CreateSwapChain(desc, bufferCount);
|
||||
_swapChain.Attach(pSwapChian);
|
||||
|
||||
CreateBackBuffers();
|
||||
SetScale(desc.ScaleX, desc.ScaleY);
|
||||
|
||||
_compositionSurface = desc.Target.CompositionSurface;
|
||||
}
|
||||
@@ -66,7 +79,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private void CreateSwapChain(SwapChainDesc desc, uint bufferCount)
|
||||
private IDXGISwapChain4* CreateSwapChain(SwapChainDesc desc, uint bufferCount)
|
||||
{
|
||||
var swapChainDesc = new DXGI_SWAP_CHAIN_DESC1
|
||||
{
|
||||
@@ -124,7 +137,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
pTempSwapChain->QueryInterface(__uuidof(pSwapChain), (void**)&pSwapChain);
|
||||
pTempSwapChain->Release();
|
||||
|
||||
_swapChain.Attach(pSwapChain);
|
||||
return pSwapChain;
|
||||
}
|
||||
|
||||
private void CreateBackBuffers()
|
||||
@@ -155,6 +168,13 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
return _backBuffers[_swapChain.Get()->GetCurrentBackBufferIndex()];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ReadOnlySpan<Handle<Texture>> GetBackBuffers()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _backBuffers.AsSpan();
|
||||
}
|
||||
|
||||
public void Present(bool vsync = true)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
@@ -186,20 +206,27 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
Height = height;
|
||||
|
||||
CreateBackBuffers();
|
||||
}
|
||||
|
||||
//float inverseScale = 1.0f / scale;
|
||||
public void SetScale(float scaleX, float scaleY)
|
||||
{
|
||||
var inverseScaleX = 1.0f / scaleX;
|
||||
var inverseScaleY = 1.0f / scaleY;
|
||||
|
||||
//DXGI_MATRIX_3X2_F inverseScaleMatrix = new DXGI_MATRIX_3X2_F
|
||||
//{
|
||||
// _11 = inverseScale, // Scale X
|
||||
// _22 = inverseScale, // Scale Y
|
||||
// _12 = 0.0f,
|
||||
// _21 = 0.0f,
|
||||
// _31 = 0.0f, // Offset X
|
||||
// _32 = 0.0f // Offset Y
|
||||
//};
|
||||
DXGI_MATRIX_3X2_F inverseScaleMatrix = new DXGI_MATRIX_3X2_F
|
||||
{
|
||||
_11 = inverseScaleX, // Scale X
|
||||
_22 = inverseScaleY, // Scale Y
|
||||
_12 = 0.0f,
|
||||
_21 = 0.0f,
|
||||
_31 = 0.0f, // Offset X
|
||||
_32 = 0.0f // Offset Y
|
||||
};
|
||||
|
||||
//_swapChain.Get()->SetMatrixTransform(&inverseScaleMatrix);
|
||||
_swapChain.Get()->SetMatrixTransform(&inverseScaleMatrix);
|
||||
|
||||
ScaleX = scaleX;
|
||||
ScaleY = scaleY;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -155,6 +155,17 @@ internal unsafe static class D3D12Utility
|
||||
};
|
||||
}
|
||||
|
||||
public static D3D12_COMMAND_LIST_TYPE ToCommandListType(CommandBufferType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
CommandBufferType.Graphics => D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
CommandBufferType.Compute => D3D12_COMMAND_LIST_TYPE_COMPUTE,
|
||||
CommandBufferType.Copy => D3D12_COMMAND_LIST_TYPE_COPY,
|
||||
_ => throw new ArgumentException($"Unknown command buffer type: {type}")
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static D3D12_RASTERIZER_DESC D3D12_RASTERIZER_DESC_CREATE(
|
||||
D3D12_FILL_MODE fillMode,
|
||||
|
||||
Reference in New Issue
Block a user