csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
6.3 KiB
177 lines
6.3 KiB
using System;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using Avalonia;
|
|
using Avalonia.Platform;
|
|
using Avalonia.Rendering.Composition;
|
|
using Silk.NET.Core.Native;
|
|
using Silk.NET.Direct3D11;
|
|
using Silk.NET.DXGI;
|
|
using static Silk.NET.Core.Native.SilkMarshal;
|
|
|
|
namespace GpuInterop.D3DDemo;
|
|
|
|
public class D3D11DemoControl : DrawingSurfaceDemoBase
|
|
{
|
|
private ComPtr<ID3D11Device> _device;
|
|
private D3D11Swapchain? _swapchain;
|
|
private ComPtr<ID3D11DeviceContext> _context;
|
|
private Matrix4x4 _view;
|
|
private PixelSize _lastSize;
|
|
private ComPtr<ID3D11Texture2D> _depthBuffer;
|
|
private ComPtr<ID3D11DepthStencilView> _depthView;
|
|
private Matrix4x4 _proj;
|
|
private ComPtr<ID3D11Buffer> _constantBuffer;
|
|
private readonly Stopwatch _st = Stopwatch.StartNew();
|
|
|
|
protected override unsafe (bool success, string info) InitializeGraphicsResources(Compositor compositor,
|
|
CompositionDrawingSurface surface, ICompositionGpuInterop interop)
|
|
{
|
|
if (interop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes
|
|
.D3D11TextureGlobalSharedHandle) != true)
|
|
return (false, "DXGI shared handle import is not supported by the current graphics backend");
|
|
|
|
using var dxgi = new DXGI(DXGI.CreateDefaultContext(["DXGI.dll"]));
|
|
using var d3d11 = new D3D11(D3D11.CreateDefaultContext(["d3d11.dll"]));
|
|
using var factory = dxgi.CreateDXGIFactory1<IDXGIFactory1>();
|
|
|
|
using ComPtr<IDXGIAdapter> adapter = default;
|
|
ThrowHResult(factory.EnumAdapters(0, adapter.GetAddressOf()));
|
|
|
|
const int featureLevelCount = 8;
|
|
var featureLevels = stackalloc D3DFeatureLevel[featureLevelCount]
|
|
{
|
|
D3DFeatureLevel.Level121,
|
|
D3DFeatureLevel.Level120,
|
|
D3DFeatureLevel.Level111,
|
|
D3DFeatureLevel.Level110,
|
|
D3DFeatureLevel.Level100,
|
|
D3DFeatureLevel.Level93,
|
|
D3DFeatureLevel.Level92,
|
|
D3DFeatureLevel.Level91
|
|
};
|
|
|
|
ComPtr<ID3D11Device> device = default;
|
|
ComPtr<ID3D11DeviceContext> context = default;
|
|
D3DFeatureLevel actualFeatureLevel;
|
|
ThrowHResult(d3d11.CreateDevice(
|
|
adapter,
|
|
D3DDriverType.Unknown,
|
|
IntPtr.Zero,
|
|
0u,
|
|
featureLevels,
|
|
featureLevelCount,
|
|
D3D11.SdkVersion,
|
|
device.GetAddressOf(),
|
|
&actualFeatureLevel,
|
|
context.GetAddressOf()));
|
|
|
|
_device = device;
|
|
_swapchain = new D3D11Swapchain(device, interop, surface);
|
|
_context = context;
|
|
_constantBuffer = D3DContent.CreateMesh(_device);
|
|
_view = Matrix4x4.CreateLookAtLeftHanded(new Vector3(0, 0, -5), new Vector3(0, 0, 0), Vector3.UnitY);
|
|
|
|
AdapterDesc adapterDesc;
|
|
ThrowHResult(adapter.GetDesc(&adapterDesc));
|
|
var description = PtrToString((IntPtr)adapterDesc.Description, NativeStringEncoding.LPWStr);
|
|
|
|
return (true, $"D3D11 ({actualFeatureLevel}) {description}");
|
|
}
|
|
|
|
protected override void FreeGraphicsResources()
|
|
{
|
|
if (_swapchain is not null)
|
|
{
|
|
_swapchain.DisposeAsync().GetAwaiter().GetResult();
|
|
_swapchain = null;
|
|
}
|
|
|
|
_depthView.Dispose();
|
|
_depthBuffer.Dispose();
|
|
_constantBuffer.Dispose();
|
|
_context.Dispose();
|
|
_device.Dispose();
|
|
}
|
|
|
|
protected override bool SupportsDisco => true;
|
|
|
|
protected override unsafe void RenderFrame(PixelSize pixelSize)
|
|
{
|
|
if (pixelSize == default)
|
|
return;
|
|
if (pixelSize != _lastSize)
|
|
{
|
|
_lastSize = pixelSize;
|
|
Resize(pixelSize);
|
|
}
|
|
using (_swapchain!.BeginDraw(pixelSize, out var renderView))
|
|
{
|
|
var renderViewHandle = renderView.Handle;
|
|
_context.OMSetRenderTargets(1, &renderViewHandle, _depthView);
|
|
var viewProj = _view * _proj;
|
|
|
|
var now = _st.Elapsed.TotalSeconds * 5;
|
|
var scaleX = (float)(1f + Disco * (Math.Sin(now) + 1) / 6);
|
|
var scaleY = (float)(1f + Disco * (Math.Cos(now) + 1) / 8);
|
|
var colorOff =(float) (Math.Sin(now) + 1) / 2 * Disco;
|
|
|
|
// Clear views
|
|
_context.ClearDepthStencilView(_depthView, (uint)ClearFlag.Depth, 1.0f, 0);
|
|
var color = new Vector4(1f - colorOff, colorOff, 0.5f + colorOff * 0.5f, 1.0f);
|
|
_context.ClearRenderTargetView(renderView, (float*)&color);
|
|
|
|
// Update WorldViewProj Matrix
|
|
var ypr = Matrix4x4.CreateFromYawPitchRoll(Yaw, Pitch, Roll);
|
|
var worldViewProj = ypr * Matrix4x4.CreateScale(new Vector3(scaleX, scaleY, 1)) * viewProj;
|
|
worldViewProj = Matrix4x4.Transpose(worldViewProj);
|
|
|
|
_context.UpdateSubresource(_constantBuffer, 0, null, &worldViewProj, 0, 0);
|
|
|
|
// Draw the cube
|
|
_context.Draw(36, 0);
|
|
|
|
_context.Flush();
|
|
}
|
|
}
|
|
|
|
private unsafe void Resize(PixelSize size)
|
|
{
|
|
_depthBuffer.Dispose();
|
|
|
|
if (_device.Handle == null)
|
|
return;
|
|
|
|
ComPtr<ID3D11Texture2D> depthBuffer = default;
|
|
var textureDesc = new Texture2DDesc
|
|
{
|
|
Format = Format.FormatD32FloatS8X24Uint,
|
|
ArraySize = 1,
|
|
MipLevels = 1,
|
|
Width = (uint)size.Width,
|
|
Height = (uint)size.Height,
|
|
SampleDesc = new SampleDesc(1, 0),
|
|
Usage = Usage.Default,
|
|
BindFlags = (uint)BindFlag.DepthStencil,
|
|
CPUAccessFlags = (uint)CpuAccessFlag.None,
|
|
MiscFlags = (uint)ResourceMiscFlag.None
|
|
};
|
|
ThrowHResult(_device.CreateTexture2D(
|
|
&textureDesc,
|
|
(SubresourceData*)null,
|
|
depthBuffer.GetAddressOf()));
|
|
|
|
_depthBuffer = depthBuffer;
|
|
|
|
_depthView.Dispose();
|
|
ThrowHResult(_device.CreateDepthStencilView(_depthBuffer, null, ref _depthView));
|
|
|
|
// Setup targets and viewport for rendering
|
|
var viewport = new Viewport(0, 0, size.Width, size.Height, 0.0f, 1.0f);
|
|
_context.RSSetViewports(1, &viewport);
|
|
|
|
// Setup new projection matrix with correct aspect ratio
|
|
_proj = Matrix4x4.CreatePerspectiveFieldOfViewLeftHanded((float)Math.PI / 4.0f, size.Width / (float) size.Height, 0.1f, 100.0f);
|
|
}
|
|
}
|
|
|