Use Silk.NET in GpuInterop sample (#20133)
* Replace SharpDX with Silk.NET in GpuInterop sample * Add Vulkan/D3D11 command line switch to GpuInterop * Fixed warnings in GpuInterop
This commit is contained in:
committed by
GitHub
parent
bc407c27b5
commit
4357a8dafc
@@ -6,6 +6,8 @@ namespace GpuInterop
|
||||
{
|
||||
public class App : Application
|
||||
{
|
||||
public DemoType DemoType { get; set; }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
@@ -15,7 +17,7 @@ namespace GpuInterop
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
|
||||
{
|
||||
desktopLifetime.MainWindow = new MainWindow();
|
||||
desktopLifetime.MainWindow = new MainWindow(DemoType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,57 +5,79 @@ using System.Numerics;
|
||||
using Avalonia;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering.Composition;
|
||||
using SharpDX;
|
||||
using SharpDX.Direct3D11;
|
||||
using SharpDX.DXGI;
|
||||
using SharpDX.Mathematics.Interop;
|
||||
using Buffer = SharpDX.Direct3D11.Buffer;
|
||||
using DxgiFactory1 = SharpDX.DXGI.Factory1;
|
||||
using Matrix = SharpDX.Matrix;
|
||||
using D3DDevice = SharpDX.Direct3D11.Device;
|
||||
using FeatureLevel = SharpDX.Direct3D.FeatureLevel;
|
||||
using Vector3 = SharpDX.Vector3;
|
||||
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 D3DDevice? _device;
|
||||
private ComPtr<ID3D11Device> _device;
|
||||
private D3D11Swapchain? _swapchain;
|
||||
private DeviceContext? _context;
|
||||
private Matrix _view;
|
||||
private ComPtr<ID3D11DeviceContext> _context;
|
||||
private Matrix4x4 _view;
|
||||
private PixelSize _lastSize;
|
||||
private Texture2D? _depthBuffer;
|
||||
private DepthStencilView? _depthView;
|
||||
private Matrix _proj;
|
||||
private Buffer? _constantBuffer;
|
||||
private ComPtr<ID3D11Texture2D> _depthBuffer;
|
||||
private ComPtr<ID3D11DepthStencilView> _depthView;
|
||||
private Matrix4x4 _proj;
|
||||
private ComPtr<ID3D11Buffer> _constantBuffer;
|
||||
private readonly Stopwatch _st = Stopwatch.StartNew();
|
||||
|
||||
protected override (bool success, string info) InitializeGraphicsResources(Compositor compositor,
|
||||
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");
|
||||
|
||||
var factory = new DxgiFactory1();
|
||||
using var adapter = factory.GetAdapter1(0);
|
||||
_device = new D3DDevice(adapter, DeviceCreationFlags.None, new[]
|
||||
|
||||
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]
|
||||
{
|
||||
FeatureLevel.Level_12_1,
|
||||
FeatureLevel.Level_12_0,
|
||||
FeatureLevel.Level_11_1,
|
||||
FeatureLevel.Level_11_0,
|
||||
FeatureLevel.Level_10_0,
|
||||
FeatureLevel.Level_9_3,
|
||||
FeatureLevel.Level_9_2,
|
||||
FeatureLevel.Level_9_1,
|
||||
});
|
||||
_swapchain = new D3D11Swapchain(_device, interop, surface);
|
||||
_context = _device.ImmediateContext;
|
||||
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 = Matrix.LookAtLH(new Vector3(0, 0, -5), new Vector3(0, 0, 0), Vector3.UnitY);
|
||||
return (true, $"D3D11 ({_device.FeatureLevel}) {adapter.Description1.Description}");
|
||||
_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()
|
||||
@@ -66,16 +88,16 @@ public class D3D11DemoControl : DrawingSurfaceDemoBase
|
||||
_swapchain = null;
|
||||
}
|
||||
|
||||
Utilities.Dispose(ref _depthView);
|
||||
Utilities.Dispose(ref _depthBuffer);
|
||||
Utilities.Dispose(ref _constantBuffer);
|
||||
Utilities.Dispose(ref _context);
|
||||
Utilities.Dispose(ref _device);
|
||||
_depthView.Dispose();
|
||||
_depthBuffer.Dispose();
|
||||
_constantBuffer.Dispose();
|
||||
_context.Dispose();
|
||||
_device.Dispose();
|
||||
}
|
||||
|
||||
protected override bool SupportsDisco => true;
|
||||
|
||||
protected override void RenderFrame(PixelSize pixelSize)
|
||||
protected override unsafe void RenderFrame(PixelSize pixelSize)
|
||||
{
|
||||
if (pixelSize == default)
|
||||
return;
|
||||
@@ -86,69 +108,70 @@ public class D3D11DemoControl : DrawingSurfaceDemoBase
|
||||
}
|
||||
using (_swapchain!.BeginDraw(pixelSize, out var renderView))
|
||||
{
|
||||
|
||||
_device!.ImmediateContext.OutputMerger.SetTargets(_depthView, renderView);
|
||||
var viewProj = Matrix.Multiply(_view, _proj);
|
||||
var context = _device.ImmediateContext;
|
||||
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, DepthStencilClearFlags.Depth, 1.0f, 0);
|
||||
context.ClearRenderTargetView(renderView,
|
||||
new RawColor4(1 - colorOff, colorOff, (float)0.5 + colorOff / 2, 1));
|
||||
_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);
|
||||
|
||||
|
||||
var ypr = Matrix4x4.CreateFromYawPitchRoll(Yaw, Pitch, Roll);
|
||||
// Update WorldViewProj Matrix
|
||||
var worldViewProj = Matrix.RotationX(Yaw) * Matrix.RotationY(Pitch)
|
||||
* Matrix.RotationZ(Roll)
|
||||
* Matrix.Scaling(new Vector3(scaleX, scaleY, 1))
|
||||
* viewProj;
|
||||
worldViewProj.Transpose();
|
||||
context.UpdateSubresource(ref worldViewProj, _constantBuffer);
|
||||
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.Draw(36, 0);
|
||||
|
||||
|
||||
_context!.Flush();
|
||||
_context.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
private void Resize(PixelSize size)
|
||||
private unsafe void Resize(PixelSize size)
|
||||
{
|
||||
Utilities.Dispose(ref _depthBuffer);
|
||||
_depthBuffer.Dispose();
|
||||
|
||||
if (_device is null)
|
||||
if (_device.Handle == null)
|
||||
return;
|
||||
|
||||
_depthBuffer = new Texture2D(_device,
|
||||
new Texture2DDescription()
|
||||
{
|
||||
Format = Format.D32_Float_S8X24_UInt,
|
||||
ArraySize = 1,
|
||||
MipLevels = 1,
|
||||
Width = size.Width,
|
||||
Height = size.Height,
|
||||
SampleDescription = new SampleDescription(1, 0),
|
||||
Usage = ResourceUsage.Default,
|
||||
BindFlags = BindFlags.DepthStencil,
|
||||
CpuAccessFlags = CpuAccessFlags.None,
|
||||
OptionFlags = ResourceOptionFlags.None
|
||||
});
|
||||
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()));
|
||||
|
||||
Utilities.Dispose(ref _depthView);
|
||||
_depthView = new DepthStencilView(_device, _depthBuffer);
|
||||
_depthBuffer = depthBuffer;
|
||||
|
||||
_depthView.Dispose();
|
||||
ThrowHResult(_device.CreateDepthStencilView(_depthBuffer, null, ref _depthView));
|
||||
|
||||
// Setup targets and viewport for rendering
|
||||
_device.ImmediateContext.Rasterizer.SetViewport(new Viewport(0, 0, size.Width, size.Height, 0.0f, 1.0f));
|
||||
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 = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, size.Width / (float) size.Height, 0.1f, 100.0f);
|
||||
_proj = Matrix4x4.CreatePerspectiveFieldOfViewLeftHanded((float)Math.PI / 4.0f, size.Width / (float) size.Height, 0.1f, 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering;
|
||||
using Avalonia.Rendering.Composition;
|
||||
using SharpDX.Direct3D11;
|
||||
using SharpDX.DXGI;
|
||||
using DxgiFactory1 = SharpDX.DXGI.Factory1;
|
||||
using D3DDevice = SharpDX.Direct3D11.Device;
|
||||
using DxgiResource = SharpDX.DXGI.Resource;
|
||||
using Silk.NET.Core.Native;
|
||||
using Silk.NET.Direct3D11;
|
||||
using Silk.NET.DXGI;
|
||||
using static Silk.NET.Core.Native.SilkMarshal;
|
||||
|
||||
namespace GpuInterop.D3DDemo;
|
||||
|
||||
class D3D11Swapchain : SwapchainBase<D3D11SwapchainImage>
|
||||
{
|
||||
private readonly D3DDevice _device;
|
||||
private readonly ComPtr<ID3D11Device> _device;
|
||||
|
||||
public D3D11Swapchain(D3DDevice device, ICompositionGpuInterop interop, CompositionDrawingSurface target)
|
||||
public D3D11Swapchain(ComPtr<ID3D11Device> device, ICompositionGpuInterop interop, CompositionDrawingSurface target)
|
||||
: base(interop, target)
|
||||
{
|
||||
_device = device;
|
||||
@@ -24,7 +24,7 @@ class D3D11Swapchain : SwapchainBase<D3D11SwapchainImage>
|
||||
|
||||
protected override D3D11SwapchainImage CreateImage(PixelSize size) => new(_device, size, Interop, Target);
|
||||
|
||||
public IDisposable BeginDraw(PixelSize size, out RenderTargetView view)
|
||||
public IDisposable BeginDraw(PixelSize size, out ComPtr<ID3D11RenderTargetView> view)
|
||||
{
|
||||
var rv = BeginDrawCore(size, out var image);
|
||||
view = image.RenderTargetView;
|
||||
@@ -37,53 +37,67 @@ public class D3D11SwapchainImage : ISwapchainImage
|
||||
public PixelSize Size { get; }
|
||||
private readonly ICompositionGpuInterop _interop;
|
||||
private readonly CompositionDrawingSurface _target;
|
||||
private readonly Texture2D _texture;
|
||||
private readonly KeyedMutex _mutex;
|
||||
private ComPtr<ID3D11Texture2D> _texture;
|
||||
private ComPtr<IDXGIKeyedMutex> _mutex;
|
||||
private ComPtr<ID3D11RenderTargetView> _renderTargetView;
|
||||
private readonly IntPtr _handle;
|
||||
private PlatformGraphicsExternalImageProperties _properties;
|
||||
private ICompositionImportedGpuImage? _imported;
|
||||
public Task? LastPresent { get; private set; }
|
||||
public RenderTargetView RenderTargetView { get; }
|
||||
|
||||
public D3D11SwapchainImage(D3DDevice device, PixelSize size,
|
||||
public Task? LastPresent { get; private set; }
|
||||
public ComPtr<ID3D11RenderTargetView> RenderTargetView => _renderTargetView;
|
||||
|
||||
public unsafe D3D11SwapchainImage(
|
||||
ComPtr<ID3D11Device> device,
|
||||
PixelSize size,
|
||||
ICompositionGpuInterop interop,
|
||||
CompositionDrawingSurface target)
|
||||
{
|
||||
Size = size;
|
||||
_interop = interop;
|
||||
_target = target;
|
||||
_texture = new Texture2D(device,
|
||||
new Texture2DDescription
|
||||
{
|
||||
Format = Format.R8G8B8A8_UNorm,
|
||||
Width = size.Width,
|
||||
Height = size.Height,
|
||||
ArraySize = 1,
|
||||
MipLevels = 1,
|
||||
SampleDescription = new SampleDescription { Count = 1, Quality = 0 },
|
||||
CpuAccessFlags = default,
|
||||
OptionFlags = ResourceOptionFlags.SharedKeyedmutex,
|
||||
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource
|
||||
});
|
||||
_mutex = _texture.QueryInterface<KeyedMutex>();
|
||||
using (var res = _texture.QueryInterface<DxgiResource>())
|
||||
_handle = res.SharedHandle;
|
||||
|
||||
ComPtr<ID3D11Texture2D> texture = default;
|
||||
var textureDesc = new Texture2DDesc
|
||||
{
|
||||
Format = Format.FormatR8G8B8A8Unorm,
|
||||
Width = (uint)size.Width,
|
||||
Height = (uint)size.Height,
|
||||
ArraySize = 1,
|
||||
MipLevels = 1,
|
||||
SampleDesc = new SampleDesc(1, 0),
|
||||
Usage = Usage.Default,
|
||||
BindFlags = (uint)(BindFlag.RenderTarget | BindFlag.ShaderResource),
|
||||
CPUAccessFlags = 0,
|
||||
MiscFlags = (uint)ResourceMiscFlag.SharedKeyedmutex
|
||||
};
|
||||
ThrowHResult(device.CreateTexture2D(&textureDesc, (SubresourceData*)null, texture.GetAddressOf()));
|
||||
_texture = texture;
|
||||
|
||||
_mutex = _texture.QueryInterface<IDXGIKeyedMutex>();
|
||||
using (var res = _texture.QueryInterface<IDXGIResource>())
|
||||
{
|
||||
void* handle = null;
|
||||
ThrowHResult(res.GetSharedHandle(ref handle));
|
||||
_handle = (IntPtr)handle;
|
||||
}
|
||||
|
||||
_properties = new PlatformGraphicsExternalImageProperties
|
||||
{
|
||||
Width = size.Width, Height = size.Height, Format = PlatformGraphicsExternalImageFormat.B8G8R8A8UNorm
|
||||
};
|
||||
|
||||
RenderTargetView = new RenderTargetView(device, _texture);
|
||||
ThrowHResult(device.CreateRenderTargetView(_texture, null, ref _renderTargetView));
|
||||
}
|
||||
|
||||
public void BeginDraw()
|
||||
{
|
||||
_mutex.Acquire(0, int.MaxValue);
|
||||
_mutex.AcquireSync(0, int.MaxValue);
|
||||
}
|
||||
|
||||
public void Present()
|
||||
{
|
||||
_mutex.Release(1);
|
||||
_mutex.ReleaseSync(1);
|
||||
_imported ??= _interop.ImportImage(
|
||||
new PlatformHandle(_handle, KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureGlobalSharedHandle),
|
||||
_properties);
|
||||
@@ -103,8 +117,8 @@ public class D3D11SwapchainImage : ISwapchainImage
|
||||
// Ignore
|
||||
}
|
||||
|
||||
RenderTargetView.Dispose();
|
||||
_renderTargetView.Dispose();
|
||||
_mutex.Dispose();
|
||||
_texture.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,110 +1,158 @@
|
||||
using SharpDX;
|
||||
using SharpDX.D3DCompiler;
|
||||
using SharpDX.Direct3D;
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using SharpDX.Direct2D1;
|
||||
using SharpDX.Direct3D11;
|
||||
using SharpDX.DXGI;
|
||||
using SharpDX.Mathematics.Interop;
|
||||
using Buffer = SharpDX.Direct3D11.Buffer;
|
||||
using DeviceContext = SharpDX.Direct2D1.DeviceContext;
|
||||
using DxgiFactory1 = SharpDX.DXGI.Factory1;
|
||||
using Matrix = SharpDX.Matrix;
|
||||
using D3DDevice = SharpDX.Direct3D11.Device;
|
||||
using DxgiResource = SharpDX.DXGI.Resource;
|
||||
using FeatureLevel = SharpDX.Direct3D.FeatureLevel;
|
||||
using InputElement = SharpDX.Direct3D11.InputElement;
|
||||
|
||||
using System.Numerics;
|
||||
using Silk.NET.Core.Native;
|
||||
using Silk.NET.Direct3D.Compilers;
|
||||
using Silk.NET.Direct3D11;
|
||||
using Silk.NET.DXGI;
|
||||
using static Silk.NET.Core.Native.SilkMarshal;
|
||||
|
||||
namespace GpuInterop.D3DDemo;
|
||||
|
||||
public class D3DContent
|
||||
public static class D3DContent
|
||||
{
|
||||
private static D3DCompiler s_compiler = D3DCompiler.GetApi();
|
||||
|
||||
public static Buffer CreateMesh(D3DDevice device)
|
||||
public static unsafe ComPtr<ID3D11Buffer> CreateMesh(ComPtr<ID3D11Device> device)
|
||||
{
|
||||
// Compile Vertex and Pixel shaders
|
||||
var vertexShaderByteCode = ShaderBytecode.CompileFromFile("D3DDemo\\MiniCube.fx", "VS", "vs_4_0");
|
||||
var vertexShader = new VertexShader(device, vertexShaderByteCode);
|
||||
using var vertexShaderByteCode = CompileShader("D3DDemo\\MiniCube.fx", "VS", "vs_4_0");
|
||||
using ComPtr<ID3D11VertexShader> vertexShader = default;
|
||||
ThrowHResult(device.CreateVertexShader(
|
||||
vertexShaderByteCode.GetBufferPointer(),
|
||||
vertexShaderByteCode.GetBufferSize(),
|
||||
(ID3D11ClassLinkage*)null,
|
||||
vertexShader.GetAddressOf()));
|
||||
|
||||
var pixelShaderByteCode = ShaderBytecode.CompileFromFile("D3DDemo\\MiniCube.fx", "PS", "ps_4_0");
|
||||
var pixelShader = new PixelShader(device, pixelShaderByteCode);
|
||||
using var pixelShaderByteCode = CompileShader("D3DDemo\\MiniCube.fx", "PS", "ps_4_0");
|
||||
using ComPtr<ID3D11PixelShader> pixelShader = default;
|
||||
ThrowHResult(device.CreatePixelShader(
|
||||
pixelShaderByteCode.GetBufferPointer(),
|
||||
pixelShaderByteCode.GetBufferSize(),
|
||||
(ID3D11ClassLinkage*)null,
|
||||
pixelShader.GetAddressOf()));
|
||||
|
||||
var signature = ShaderSignature.GetInputSignature(vertexShaderByteCode);
|
||||
|
||||
var inputElements = new[]
|
||||
{
|
||||
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
|
||||
new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0)
|
||||
};
|
||||
using ComPtr<ID3D10Blob> vertexShaderSignature = default;
|
||||
ThrowHResult(s_compiler.GetInputSignatureBlob(
|
||||
vertexShaderByteCode.GetBufferPointer(),
|
||||
vertexShaderByteCode.GetBufferSize(),
|
||||
vertexShaderSignature.GetAddressOf()));
|
||||
|
||||
// Layout from VertexShader input signature
|
||||
var layout = new InputLayout(
|
||||
device,
|
||||
signature,
|
||||
inputElements);
|
||||
using ComPtr<ID3D11InputLayout> inputLayout = default;
|
||||
var positionNamePtr = StringToPtr("POSITION", NativeStringEncoding.LPStr);
|
||||
var colorNamePtr = StringToPtr("COLOR", NativeStringEncoding.LPStr);
|
||||
try
|
||||
{
|
||||
const int inputCount = 2;
|
||||
var inputs = stackalloc InputElementDesc[inputCount]
|
||||
{
|
||||
new InputElementDesc((byte*)positionNamePtr, 0, Format.FormatR32G32B32A32Float, 0, 0),
|
||||
new InputElementDesc((byte*)colorNamePtr, 0, Format.FormatR32G32B32A32Float, 0, 16)
|
||||
};
|
||||
|
||||
ThrowHResult(device.CreateInputLayout(
|
||||
inputs,
|
||||
inputCount,
|
||||
vertexShaderSignature.GetBufferPointer(),
|
||||
vertexShaderSignature.GetBufferSize(),
|
||||
inputLayout.GetAddressOf()));
|
||||
}
|
||||
finally
|
||||
{
|
||||
FreeString(positionNamePtr, NativeStringEncoding.LPStr);
|
||||
FreeString(colorNamePtr, NativeStringEncoding.LPStr);
|
||||
}
|
||||
|
||||
// Instantiate Vertex buffer from vertex data
|
||||
using var vertices = Buffer.Create(
|
||||
device,
|
||||
BindFlags.VertexBuffer,
|
||||
new[]
|
||||
var vertices = new[]
|
||||
{
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
|
||||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
|
||||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
|
||||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
|
||||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
|
||||
};
|
||||
|
||||
using ComPtr<ID3D11Buffer> vertexBuffer = default;
|
||||
|
||||
fixed (Vector4* verticesPtr = vertices)
|
||||
{
|
||||
var vertexBufferDesc = new BufferDesc
|
||||
{
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
|
||||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
|
||||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
|
||||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
|
||||
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
|
||||
new Vector4(1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
|
||||
});
|
||||
ByteWidth = (uint)(sizeof(Vector4) * vertices.Length),
|
||||
Usage = Usage.Default,
|
||||
BindFlags = (uint)BindFlag.VertexBuffer,
|
||||
CPUAccessFlags = (uint)CpuAccessFlag.None,
|
||||
MiscFlags = (uint)ResourceMiscFlag.None,
|
||||
StructureByteStride = 0
|
||||
};
|
||||
var subresourceData = new SubresourceData(verticesPtr);
|
||||
ThrowHResult(device.CreateBuffer(&vertexBufferDesc, &subresourceData, vertexBuffer.GetAddressOf()));
|
||||
}
|
||||
|
||||
// Create Constant Buffer
|
||||
var constantBuffer = new Buffer(device, Utilities.SizeOf<Matrix>(), ResourceUsage.Default,
|
||||
BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
|
||||
|
||||
var context = device.ImmediateContext;
|
||||
ComPtr<ID3D11Buffer> constantBuffer = default;
|
||||
var constantBufferDesc = new BufferDesc
|
||||
{
|
||||
ByteWidth = (uint)sizeof(Matrix4x4),
|
||||
Usage = Usage.Default,
|
||||
BindFlags = (uint)BindFlag.ConstantBuffer,
|
||||
CPUAccessFlags = (uint)CpuAccessFlag.None,
|
||||
MiscFlags = (uint)ResourceMiscFlag.None,
|
||||
StructureByteStride = 0
|
||||
};
|
||||
ThrowHResult(device.CreateBuffer(&constantBufferDesc, (SubresourceData*)null, constantBuffer.GetAddressOf()));
|
||||
|
||||
// Prepare All the stages
|
||||
context.InputAssembler.InputLayout = layout;
|
||||
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
|
||||
context.InputAssembler.SetVertexBuffers(0,
|
||||
new VertexBufferBinding(vertices, Utilities.SizeOf<Vector4>() * 2, 0));
|
||||
context.VertexShader.SetConstantBuffer(0, constantBuffer);
|
||||
context.VertexShader.Set(vertexShader);
|
||||
context.PixelShader.Set(pixelShader);
|
||||
using ComPtr<ID3D11DeviceContext> context = default;
|
||||
device.GetImmediateContext(context.GetAddressOf());
|
||||
|
||||
context.IASetInputLayout(inputLayout);
|
||||
context.IASetPrimitiveTopology(D3DPrimitiveTopology.D3D10PrimitiveTopologyTrianglelist);
|
||||
var stride = (uint)(sizeof(Vector4) * 2);
|
||||
var offset = 0u;
|
||||
context.IASetVertexBuffers(0, 1, &vertexBuffer.Handle, &stride, &offset);
|
||||
context.VSSetConstantBuffers(0, 1, &constantBuffer.Handle);
|
||||
context.VSSetShader(vertexShader, (ID3D11ClassInstance**)null, 0);
|
||||
context.PSSetShader(pixelShader, (ID3D11ClassInstance**)null, 0);
|
||||
|
||||
return constantBuffer;
|
||||
}
|
||||
|
||||
private static unsafe ComPtr<ID3D10Blob> CompileShader(string fileName, string entryPoint, string profile)
|
||||
{
|
||||
ComPtr<ID3D10Blob> blob = default;
|
||||
ThrowHResult(s_compiler.CompileFromFile(fileName, null, null, entryPoint, profile, 0u, 0u, blob.GetAddressOf(), null));
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace GpuInterop;
|
||||
|
||||
public enum DemoType
|
||||
{
|
||||
Vulkan,
|
||||
D3D11
|
||||
}
|
||||
@@ -7,7 +7,6 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateDocumentationFile>false</GenerateDocumentationFile>
|
||||
<UseD3DCompiler>true</UseD3DCompiler>
|
||||
<UseSharpDXMathematics>true</UseSharpDXMathematics>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -25,10 +24,13 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Silk.NET.Vulkan" Version="2.16.0" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.16.0" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.16.0" />
|
||||
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
||||
<PackageReference Include="Silk.NET.Direct3D11" Version="2.22.0" />
|
||||
<PackageReference Include="Silk.NET.Direct3D.Compilers" Version="2.22.0" />
|
||||
<PackageReference Include="Silk.NET.Vulkan" Version="2.22.0" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.22.0" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.22.0" />
|
||||
<!-- Silk.NET 2.22 targets an obsolete System.Text.Json, update to avoid warnings. -->
|
||||
<PackageReference Include="System.Text.Json" Version="10.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -37,6 +39,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\src\Avalonia.Base\Rendering\SwapchainBase.cs" />
|
||||
<Compile Include="..\..\src\Avalonia.Base\Reactive\Disposable.cs" />
|
||||
<None Remove="VulkanDemo\Assets\Shaders\frag.spirv" />
|
||||
<EmbeddedResource Include="VulkanDemo\Assets\Shaders\frag.spirv" />
|
||||
<None Remove="VulkanDemo\Assets\Shaders\vert.spirv" />
|
||||
@@ -47,5 +50,4 @@
|
||||
<Import Project="..\..\build\SampleApp.props" />
|
||||
<Import Project="..\..\build\ReferenceCoreLibraries.props" />
|
||||
<Import Project="..\..\build\BuildTargets.targets" />
|
||||
<Import Project="..\..\build\SharpDX.props" />
|
||||
</Project>
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
|
||||
xmlns:gpuInterop="clr-namespace:GpuInterop"
|
||||
xmlns:d3DDemo="clr-namespace:GpuInterop.D3DDemo"
|
||||
xmlns:vulkanDemo="clr-namespace:GpuInterop.VulkanDemo"
|
||||
x:Class="GpuInterop.MainWindow">
|
||||
<gpuInterop:GpuDemo>
|
||||
<gpuInterop:GpuDemo.Demo>
|
||||
<!--<d3DDemo:D3D11DemoControl/>-->
|
||||
<vulkanDemo:VulkanDemoControl/>
|
||||
</gpuInterop:GpuDemo.Demo>
|
||||
</gpuInterop:GpuDemo>
|
||||
|
||||
</Window>
|
||||
|
||||
@@ -1,15 +1,35 @@
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Rendering;
|
||||
using GpuInterop.D3DDemo;
|
||||
using GpuInterop.VulkanDemo;
|
||||
|
||||
namespace GpuInterop
|
||||
{
|
||||
public class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
public MainWindow() : this(DemoType.Vulkan)
|
||||
{
|
||||
}
|
||||
|
||||
public MainWindow(DemoType demoType)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Title = demoType.ToString();
|
||||
|
||||
Content = new GpuDemo
|
||||
{
|
||||
Demo = demoType switch
|
||||
{
|
||||
DemoType.Vulkan => new VulkanDemoControl(),
|
||||
DemoType.D3D11 => new D3D11DemoControl(),
|
||||
var unknown => throw new InvalidOperationException($"Unknown demo type {unknown}")
|
||||
}
|
||||
};
|
||||
|
||||
this.AttachDevTools();
|
||||
RendererDiagnostics.DebugOverlays = RendererDebugOverlays.Fps;
|
||||
}
|
||||
|
||||
@@ -1,29 +1,35 @@
|
||||
global using System.Reactive.Disposables;
|
||||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Logging;
|
||||
using Avalonia.Vulkan;
|
||||
|
||||
namespace GpuInterop
|
||||
{
|
||||
public class Program
|
||||
public static class Program
|
||||
{
|
||||
static void Main(string[] args) => BuildAvaloniaApp()
|
||||
.StartWithClassicDesktopLifetime(args);
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var demoType = OperatingSystem.IsWindows() && args.AsSpan().Contains("--d3d") ? DemoType.D3D11 : DemoType.Vulkan;
|
||||
BuildAvaloniaAppCore(demoType).StartWithClassicDesktopLifetime(args);
|
||||
}
|
||||
|
||||
public static AppBuilder BuildAvaloniaApp() =>
|
||||
AppBuilder.Configure<App>()
|
||||
public static AppBuilder BuildAvaloniaApp() => BuildAvaloniaAppCore(DemoType.Vulkan);
|
||||
|
||||
private static AppBuilder BuildAvaloniaAppCore(DemoType demoType) =>
|
||||
AppBuilder
|
||||
.Configure(() => new App { DemoType = demoType })
|
||||
.UsePlatformDetect()
|
||||
.With(new Win32PlatformOptions
|
||||
{
|
||||
RenderingMode = new []
|
||||
{
|
||||
Win32RenderingMode.Vulkan
|
||||
}
|
||||
RenderingMode = [demoType == DemoType.D3D11 ? Win32RenderingMode.AngleEgl : Win32RenderingMode.Vulkan]
|
||||
})
|
||||
.With(new X11PlatformOptions(){RenderingMode =new[] { X11RenderingMode.Vulkan } })
|
||||
.With(new VulkanOptions()
|
||||
.With(new X11PlatformOptions
|
||||
{
|
||||
VulkanInstanceCreationOptions = new VulkanInstanceCreationOptions()
|
||||
RenderingMode = [X11RenderingMode.Vulkan]
|
||||
})
|
||||
.With(new VulkanOptions
|
||||
{
|
||||
VulkanInstanceCreationOptions = new VulkanInstanceCreationOptions
|
||||
{
|
||||
UseDebug = true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"GpuInterop (Vulkan)": {
|
||||
"commandName": "Project",
|
||||
},
|
||||
"GpuInterop (Direct3D)": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "--d3d"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +1,97 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Avalonia;
|
||||
using SharpDX.Direct3D;
|
||||
using SharpDX.Direct3D11;
|
||||
using SharpDX.DXGI;
|
||||
using D3DDevice = SharpDX.Direct3D11.Device;
|
||||
using DxgiFactory1 = SharpDX.DXGI.Factory1;
|
||||
using Silk.NET.Core.Native;
|
||||
using Silk.NET.Direct3D11;
|
||||
using Silk.NET.DXGI;
|
||||
using VulkanFormat = Silk.NET.Vulkan.Format;
|
||||
using static Silk.NET.Core.Native.SilkMarshal;
|
||||
|
||||
namespace GpuInterop.VulkanDemo;
|
||||
|
||||
public class D3DMemoryHelper
|
||||
{
|
||||
public static D3DDevice CreateDeviceByLuid(Span<byte> luid)
|
||||
{
|
||||
var factory = new DxgiFactory1();
|
||||
var longLuid = MemoryMarshal.Cast<byte, long>(luid)[0];
|
||||
for (var c = 0; c < factory.GetAdapterCount1(); c++)
|
||||
{
|
||||
using var adapter = factory.GetAdapter1(c);
|
||||
if (adapter.Description1.Luid != longLuid)
|
||||
continue;
|
||||
private const int DxgiErrorNotFound = unchecked((int)0x887A0002);
|
||||
|
||||
return new D3DDevice(adapter, DeviceCreationFlags.None,
|
||||
new[]
|
||||
{
|
||||
FeatureLevel.Level_12_1, FeatureLevel.Level_12_0, FeatureLevel.Level_11_1,
|
||||
FeatureLevel.Level_11_0, FeatureLevel.Level_10_0, FeatureLevel.Level_9_3,
|
||||
FeatureLevel.Level_9_2, FeatureLevel.Level_9_1,
|
||||
});
|
||||
public static unsafe ComPtr<ID3D11Device> CreateDeviceByLuid(Luid luid)
|
||||
{
|
||||
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 var adapter = GetAdapterByLuid(factory, luid);
|
||||
|
||||
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()));
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
private static unsafe ComPtr<IDXGIAdapter> GetAdapterByLuid(ComPtr<IDXGIFactory1> factory, Luid luid)
|
||||
{
|
||||
var index = 0u;
|
||||
ComPtr<IDXGIAdapter> adapter = default;
|
||||
|
||||
while (factory.EnumAdapters(index, adapter.GetAddressOf()) != DxgiErrorNotFound)
|
||||
{
|
||||
AdapterDesc adapterDesc;
|
||||
if (adapter.GetDesc(&adapterDesc) == 0 & AreLuidsEqual(adapterDesc.AdapterLuid, luid))
|
||||
return adapter;
|
||||
|
||||
adapter.Dispose();
|
||||
++index;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Device with the corresponding LUID not found");
|
||||
}
|
||||
|
||||
public static Texture2D CreateMemoryHandle(D3DDevice device, PixelSize size, Silk.NET.Vulkan.Format format)
|
||||
public static unsafe ComPtr<ID3D11Texture2D> CreateMemoryHandle(ComPtr<ID3D11Device> device, PixelSize size, VulkanFormat format)
|
||||
{
|
||||
if (format != Silk.NET.Vulkan.Format.R8G8B8A8Unorm)
|
||||
if (format != VulkanFormat.R8G8B8A8Unorm)
|
||||
throw new ArgumentException("Not supported format");
|
||||
return new Texture2D(device,
|
||||
new Texture2DDescription
|
||||
{
|
||||
Format = Format.R8G8B8A8_UNorm,
|
||||
Width = size.Width,
|
||||
Height = size.Height,
|
||||
ArraySize = 1,
|
||||
MipLevels = 1,
|
||||
SampleDescription = new SampleDescription { Count = 1, Quality = 0 },
|
||||
CpuAccessFlags = default,
|
||||
OptionFlags = ResourceOptionFlags.SharedKeyedmutex|ResourceOptionFlags.SharedNthandle,
|
||||
BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource
|
||||
});
|
||||
|
||||
ComPtr<ID3D11Texture2D> texture = default;
|
||||
var textureDesc = new Texture2DDesc
|
||||
{
|
||||
Format = Format.FormatR8G8B8A8Unorm,
|
||||
Width = (uint)size.Width,
|
||||
Height = (uint)size.Height,
|
||||
ArraySize = 1,
|
||||
MipLevels = 1,
|
||||
SampleDesc = new SampleDesc(1, 0),
|
||||
Usage = Usage.Default,
|
||||
BindFlags = (uint)(BindFlag.RenderTarget | BindFlag.ShaderResource),
|
||||
CPUAccessFlags = 0,
|
||||
MiscFlags = (uint)(ResourceMiscFlag.SharedKeyedmutex | ResourceMiscFlag.SharedNthandle)
|
||||
};
|
||||
ThrowHResult(device.CreateTexture2D(&textureDesc, (SubresourceData*)null, texture.GetAddressOf()));
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
private static bool AreLuidsEqual(Luid x, Luid y)
|
||||
=> x.Low == y.Low && x.High == y.High;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ static class VulkanBufferHelper
|
||||
Usage = bufferUsageFlags,
|
||||
SharingMode = SharingMode.Exclusive
|
||||
};
|
||||
api.CreateBuffer(device, bufferInfo, null, out buffer).ThrowOnError();
|
||||
api.CreateBuffer(device, in bufferInfo, null, out buffer).ThrowOnError();
|
||||
|
||||
api.GetBufferMemoryRequirements(device, buffer, out var memoryRequirements);
|
||||
|
||||
@@ -42,7 +42,7 @@ static class VulkanBufferHelper
|
||||
MemoryPropertyFlags.HostVisibleBit)
|
||||
};
|
||||
|
||||
api.AllocateMemory(device, memoryAllocateInfo, null, out memory).ThrowOnError();
|
||||
api.AllocateMemory(device, in memoryAllocateInfo, null, out memory).ThrowOnError();
|
||||
api.BindBufferMemory(device, buffer, memory, 0);
|
||||
UpdateBufferMemory(vk, memory, initialData);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Avalonia.Vulkan
|
||||
QueueFamilyIndex = queueFamilyIndex
|
||||
};
|
||||
|
||||
_api.CreateCommandPool(_device, commandPoolCreateInfo, null, out _commandPool)
|
||||
_api.CreateCommandPool(_device, in commandPoolCreateInfo, null, out _commandPool)
|
||||
.ThrowOnError();
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Avalonia.Vulkan
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_api.AllocateCommandBuffers(_device, commandBufferAllocateInfo, out var commandBuffer);
|
||||
_api.AllocateCommandBuffers(_device, in commandBufferAllocateInfo, out var commandBuffer);
|
||||
|
||||
return commandBuffer;
|
||||
}
|
||||
@@ -111,15 +111,16 @@ namespace Avalonia.Vulkan
|
||||
Flags = FenceCreateFlags.SignaledBit
|
||||
};
|
||||
|
||||
api.CreateFence(device, fenceCreateInfo, null, out _fence);
|
||||
api.CreateFence(device, in fenceCreateInfo, null, out _fence);
|
||||
}
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
_api.WaitForFences(_device, 1, _fence, true, ulong.MaxValue);
|
||||
_api.WaitForFences(_device, 1, in _fence, true, ulong.MaxValue);
|
||||
lock (_commandBufferPool._lock)
|
||||
{
|
||||
_api.FreeCommandBuffers(_device, _commandBufferPool._commandPool, 1, InternalHandle);
|
||||
var handle = InternalHandle;
|
||||
_api.FreeCommandBuffers(_device, _commandBufferPool._commandPool, 1, in handle);
|
||||
}
|
||||
_api.DestroyFence(_device, _fence, null);
|
||||
}
|
||||
@@ -136,7 +137,7 @@ namespace Avalonia.Vulkan
|
||||
Flags = CommandBufferUsageFlags.OneTimeSubmitBit
|
||||
};
|
||||
|
||||
_api.BeginCommandBuffer(InternalHandle, beginInfo);
|
||||
_api.BeginCommandBuffer(InternalHandle, in beginInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,9 +213,10 @@ namespace Avalonia.Vulkan
|
||||
PSignalSemaphores = pSignalSemaphores,
|
||||
};
|
||||
|
||||
_api.ResetFences(_device, 1, fence.Value);
|
||||
var fenceValue = fence.Value;
|
||||
_api.ResetFences(_device, 1, in fenceValue);
|
||||
|
||||
_api.QueueSubmit(_queue, 1, submitInfo, fence.Value);
|
||||
_api.QueueSubmit(_queue, 1, in submitInfo, fenceValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ unsafe class VulkanContent : IDisposable
|
||||
PCode = (uint*)ptr,
|
||||
};
|
||||
|
||||
api.CreateShaderModule(device, shaderCreateInfo, null, out _vertShader);
|
||||
api.CreateShaderModule(device, in shaderCreateInfo, null, out _vertShader);
|
||||
}
|
||||
|
||||
fixed (byte* ptr = fragShaderData)
|
||||
@@ -105,7 +105,7 @@ unsafe class VulkanContent : IDisposable
|
||||
PCode = (uint*)ptr,
|
||||
};
|
||||
|
||||
api.CreateShaderModule(device, shaderCreateInfo, null, out _fragShader);
|
||||
api.CreateShaderModule(device, in shaderCreateInfo, null, out _fragShader);
|
||||
}
|
||||
|
||||
CreateBuffers();
|
||||
@@ -160,16 +160,16 @@ unsafe class VulkanContent : IDisposable
|
||||
|
||||
var commandBufferHandle = new CommandBuffer(commandBuffer.Handle);
|
||||
|
||||
api.CmdSetViewport(commandBufferHandle, 0, 1,
|
||||
new Viewport()
|
||||
{
|
||||
Width = (float)image.Size.Width,
|
||||
Height = (float)image.Size.Height,
|
||||
MaxDepth = 1,
|
||||
MinDepth = 0,
|
||||
X = 0,
|
||||
Y = 0
|
||||
});
|
||||
var viewport = new Viewport()
|
||||
{
|
||||
Width = (float)image.Size.Width,
|
||||
Height = (float)image.Size.Height,
|
||||
MaxDepth = 1,
|
||||
MinDepth = 0,
|
||||
X = 0,
|
||||
Y = 0
|
||||
};
|
||||
api.CmdSetViewport(commandBufferHandle, 0, 1, in viewport);
|
||||
|
||||
var scissor = new Rect2D
|
||||
{
|
||||
@@ -196,7 +196,7 @@ unsafe class VulkanContent : IDisposable
|
||||
PClearValues = clearValue
|
||||
};
|
||||
|
||||
api.CmdBeginRenderPass(commandBufferHandle, beginInfo, SubpassContents.Inline);
|
||||
api.CmdBeginRenderPass(commandBufferHandle, in beginInfo, SubpassContents.Inline);
|
||||
}
|
||||
|
||||
api.CmdBindPipeline(commandBufferHandle, PipelineBindPoint.Graphics, _pipeline);
|
||||
@@ -207,7 +207,8 @@ unsafe class VulkanContent : IDisposable
|
||||
|
||||
api.CmdPushConstants(commandBufferHandle, _pipelineLayout, ShaderStageFlags.VertexBit | ShaderStageFlags.FragmentBit, 0,
|
||||
(uint)Marshal.SizeOf<VertexPushConstant>(), &vertexConstant);
|
||||
api.CmdBindVertexBuffers(commandBufferHandle, 0, 1, _vertexBuffer, 0);
|
||||
var offsets = 0ul;
|
||||
api.CmdBindVertexBuffers(commandBufferHandle, 0, 1, in _vertexBuffer, in offsets);
|
||||
api.CmdBindIndexBuffer(commandBufferHandle, _indexBuffer, 0, IndexType.Uint16);
|
||||
|
||||
api.CmdDrawIndexed(commandBufferHandle, (uint)_indices.Length, 1, 0, 0, 0);
|
||||
@@ -250,7 +251,7 @@ unsafe class VulkanContent : IDisposable
|
||||
|
||||
api.CmdBlitImage(commandBuffer.InternalHandle, _colorAttachment.InternalHandle,
|
||||
ImageLayout.TransferSrcOptimal,
|
||||
image.InternalHandle, ImageLayout.TransferDstOptimal, 1, srcBlitRegion, Filter.Linear);
|
||||
image.InternalHandle, ImageLayout.TransferDstOptimal, 1, in srcBlitRegion, Filter.Linear);
|
||||
|
||||
commandBuffer.Submit();
|
||||
}
|
||||
@@ -341,7 +342,7 @@ unsafe class VulkanContent : IDisposable
|
||||
var api = _context.Api;
|
||||
var device = _context.Device;
|
||||
api
|
||||
.CreateImage(device, imageCreateInfo, null, out _depthImage).ThrowOnError();
|
||||
.CreateImage(device, in imageCreateInfo, null, out _depthImage).ThrowOnError();
|
||||
|
||||
api.GetImageMemoryRequirements(device, _depthImage,
|
||||
out var memoryRequirements);
|
||||
@@ -355,7 +356,7 @@ unsafe class VulkanContent : IDisposable
|
||||
memoryRequirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocalBit)
|
||||
};
|
||||
|
||||
api.AllocateMemory(device, memoryAllocateInfo, null,
|
||||
api.AllocateMemory(device, in memoryAllocateInfo, null,
|
||||
out _depthImageMemory).ThrowOnError();
|
||||
|
||||
api.BindImageMemory(device, _depthImage, _depthImageMemory, 0);
|
||||
@@ -380,7 +381,7 @@ unsafe class VulkanContent : IDisposable
|
||||
};
|
||||
|
||||
api
|
||||
.CreateImageView(device, imageViewCreateInfo, null, out _depthImageView)
|
||||
.CreateImageView(device, in imageViewCreateInfo, null, out _depthImageView)
|
||||
.ThrowOnError();
|
||||
}
|
||||
|
||||
@@ -467,7 +468,7 @@ unsafe class VulkanContent : IDisposable
|
||||
PDependencies = &subpassDependency
|
||||
};
|
||||
|
||||
api.CreateRenderPass(device, renderPassCreateInfo, null, out _renderPass).ThrowOnError();
|
||||
api.CreateRenderPass(device, in renderPassCreateInfo, null, out _renderPass).ThrowOnError();
|
||||
|
||||
|
||||
// create framebuffer
|
||||
@@ -486,7 +487,7 @@ unsafe class VulkanContent : IDisposable
|
||||
Layers = 1
|
||||
};
|
||||
|
||||
api.CreateFramebuffer(device, framebufferCreateInfo, null, out _framebuffer).ThrowOnError();
|
||||
api.CreateFramebuffer(device, in framebufferCreateInfo, null, out _framebuffer).ThrowOnError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,7 +692,7 @@ unsafe class VulkanContent : IDisposable
|
||||
PSetLayouts = &setLayout
|
||||
};
|
||||
|
||||
api.CreatePipelineLayout(device, pipelineLayoutCreateInfo, null, out _pipelineLayout)
|
||||
api.CreatePipelineLayout(device, in pipelineLayoutCreateInfo, null, out _pipelineLayout)
|
||||
.ThrowOnError();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,15 @@ using Avalonia.Vulkan;
|
||||
using Silk.NET.Core;
|
||||
using Silk.NET.Core.Contexts;
|
||||
using Silk.NET.Core.Loader;
|
||||
using Silk.NET.Core.Native;
|
||||
using Silk.NET.Direct3D11;
|
||||
using Silk.NET.DXGI;
|
||||
using Silk.NET.Vulkan;
|
||||
using Silk.NET.Vulkan.Extensions.EXT;
|
||||
using Silk.NET.Vulkan.Extensions.KHR;
|
||||
using SilkNetDemo;
|
||||
using SkiaSharp;
|
||||
using D3DDevice = SharpDX.Direct3D11.Device;
|
||||
#pragma warning disable CS0162 // Unreachable code detected
|
||||
|
||||
|
||||
namespace GpuInterop.VulkanDemo;
|
||||
|
||||
@@ -30,7 +32,7 @@ public unsafe class VulkanContext : IDisposable
|
||||
public required VulkanCommandBufferPool Pool { get; init; }
|
||||
public required GRContext? GrContext { get; init; }
|
||||
public required DescriptorPool DescriptorPool { get; init; }
|
||||
public required D3DDevice? D3DDevice { get; init; }
|
||||
public required ComPtr<ID3D11Device> D3DDevice { get; init; }
|
||||
|
||||
public static (VulkanContext? result, string info) TryCreate(ICompositionGpuInterop gpuInterop)
|
||||
{
|
||||
@@ -79,7 +81,8 @@ public unsafe class VulkanContext : IDisposable
|
||||
enabledLayers.Clear();
|
||||
using var pRequiredExtensions = new ByteStringList(enabledExtensions);
|
||||
using var pEnabledLayers = new ByteStringList(enabledLayers);
|
||||
api.CreateInstance(new InstanceCreateInfo
|
||||
|
||||
var instanceCreateInfo = new InstanceCreateInfo
|
||||
{
|
||||
SType = StructureType.InstanceCreateInfo,
|
||||
PApplicationInfo = &applicationInfo,
|
||||
@@ -88,7 +91,9 @@ public unsafe class VulkanContext : IDisposable
|
||||
PpEnabledLayerNames = pEnabledLayers,
|
||||
EnabledLayerCount = pEnabledLayers.UCount,
|
||||
Flags = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? InstanceCreateFlags.EnumeratePortabilityBitKhr : default
|
||||
}, null, out var vkInstance).ThrowOnError();
|
||||
};
|
||||
|
||||
api.CreateInstance(in instanceCreateInfo, null, out var vkInstance).ThrowOnError();
|
||||
|
||||
|
||||
if (api.TryGetInstanceExtension(vkInstance, out ExtDebugUtils debugUtils))
|
||||
@@ -105,7 +110,7 @@ public unsafe class VulkanContext : IDisposable
|
||||
PfnUserCallback = new PfnDebugUtilsMessengerCallbackEXT(LogCallback),
|
||||
};
|
||||
|
||||
debugUtils.CreateDebugUtilsMessenger(vkInstance, debugCreateInfo, null, out _);
|
||||
debugUtils.CreateDebugUtilsMessenger(vkInstance, in debugCreateInfo, null, out _);
|
||||
}
|
||||
|
||||
var requireDeviceExtensions = new List<string>();
|
||||
@@ -273,13 +278,13 @@ public unsafe class VulkanContext : IDisposable
|
||||
return (null, "Can't create Skia GrContext, device is likely broken");
|
||||
}
|
||||
|
||||
D3DDevice? d3dDevice = null;
|
||||
ComPtr<ID3D11Device> d3dDevice = null;
|
||||
if (physicalDeviceIDProperties.DeviceLuidvalid &&
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) &&
|
||||
!gpuInterop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes.VulkanOpaqueNtHandle)
|
||||
)
|
||||
d3dDevice = D3DMemoryHelper.CreateDeviceByLuid(
|
||||
new Span<byte>(physicalDeviceIDProperties.DeviceLuid, 8));
|
||||
MemoryMarshal.Read<Luid>(new Span<byte>(physicalDeviceIDProperties.DeviceLuid, 8)));
|
||||
success = true;
|
||||
return (new VulkanContext
|
||||
{
|
||||
@@ -354,20 +359,14 @@ public unsafe class VulkanContext : IDisposable
|
||||
|
||||
|
||||
private const string MacVulkanSdkGlobalPath = "/usr/local/lib/libvulkan.dylib";
|
||||
class MacLibraryNameContainer : SearchPathContainer
|
||||
{
|
||||
public override string Windows64 { get; }
|
||||
public override string Windows86 { get; }
|
||||
public override string Linux { get; }
|
||||
public override string MacOS { get; } = MacVulkanSdkGlobalPath;
|
||||
}
|
||||
|
||||
private static Vk GetApi()
|
||||
{
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || !File.Exists(MacVulkanSdkGlobalPath))
|
||||
return Vk.GetApi();
|
||||
var ctx = new MultiNativeContext(new INativeContext[2]
|
||||
{
|
||||
Vk.CreateDefaultContext(new MacLibraryNameContainer().GetLibraryName()),
|
||||
Vk.CreateDefaultContext([MacVulkanSdkGlobalPath]),
|
||||
null!
|
||||
});
|
||||
var ret = new Vk(ctx);
|
||||
@@ -383,7 +382,7 @@ public unsafe class VulkanContext : IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
D3DDevice?.Dispose();
|
||||
D3DDevice.Dispose();
|
||||
GrContext?.Dispose();
|
||||
Pool.Dispose();
|
||||
Api.DestroyDescriptorPool(Device, DescriptorPool, null);
|
||||
|
||||
@@ -6,12 +6,15 @@ using System.Runtime.InteropServices;
|
||||
using Avalonia;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Vulkan;
|
||||
using SharpDX.DXGI;
|
||||
using Silk.NET.Core.Native;
|
||||
using Silk.NET.Direct3D11;
|
||||
using Silk.NET.DXGI;
|
||||
using Silk.NET.Vulkan;
|
||||
using Silk.NET.Vulkan.Extensions.EXT;
|
||||
using Silk.NET.Vulkan.Extensions.KHR;
|
||||
using SilkNetDemo;
|
||||
using SkiaSharp;
|
||||
using static Silk.NET.Core.Native.SilkMarshal;
|
||||
using Device = Silk.NET.Vulkan.Device;
|
||||
using Format = Silk.NET.Vulkan.Format;
|
||||
|
||||
@@ -29,7 +32,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
private ImageUsageFlags _imageUsageFlags { get; }
|
||||
private ImageView _imageView { get; set; }
|
||||
private DeviceMemory _imageMemory { get; set; }
|
||||
private readonly SharpDX.Direct3D11.Texture2D? _d3dTexture2D;
|
||||
private ComPtr<ID3D11Texture2D> _d3dTexture2D;
|
||||
|
||||
internal Image InternalHandle { get; private set; }
|
||||
internal Format Format { get; }
|
||||
@@ -111,7 +114,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
};
|
||||
|
||||
Api
|
||||
.CreateImage(_device, imageCreateInfo, null, out var image).ThrowOnError();
|
||||
.CreateImage(_device, in imageCreateInfo, null, out var image).ThrowOnError();
|
||||
InternalHandle = image;
|
||||
|
||||
if (!exportable || !RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
@@ -135,16 +138,16 @@ public unsafe class VulkanImage : IDisposable
|
||||
ImportMemoryWin32HandleInfoKHR handleImport = default;
|
||||
if (handleType == ExternalMemoryHandleTypeFlags.D3D11TextureBit && exportable)
|
||||
{
|
||||
var d3dDevice = vk.D3DDevice ?? throw new NotSupportedException("Vulkan D3DDevice wasn't created");
|
||||
_d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(d3dDevice, size, Format);
|
||||
using var dxgi = _d3dTexture2D.QueryInterface<SharpDX.DXGI.Resource1>();
|
||||
if (vk.D3DDevice.Handle == null)
|
||||
throw new NotSupportedException("Vulkan D3DDevice wasn't created");
|
||||
_d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(vk.D3DDevice, size, Format);
|
||||
|
||||
handleImport = new ImportMemoryWin32HandleInfoKHR
|
||||
{
|
||||
PNext = &dedicatedAllocation,
|
||||
SType = StructureType.ImportMemoryWin32HandleInfoKhr,
|
||||
HandleType = ExternalMemoryHandleTypeFlags.D3D11TextureBit,
|
||||
Handle = dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
|
||||
Handle = CreateDxgiSharedHandle()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -160,7 +163,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
memoryRequirements.MemoryTypeBits, MemoryPropertyFlags.DeviceLocalBit)
|
||||
};
|
||||
|
||||
Api.AllocateMemory(_device, memoryAllocateInfo, null,
|
||||
Api.AllocateMemory(_device, in memoryAllocateInfo, null,
|
||||
out var imageMemory).ThrowOnError();
|
||||
|
||||
_imageMemory = imageMemory;
|
||||
@@ -192,7 +195,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
};
|
||||
|
||||
Api
|
||||
.CreateImageView(_device, imageViewCreateInfo, null, out var imageView)
|
||||
.CreateImageView(_device, in imageViewCreateInfo, null, out var imageView)
|
||||
.ThrowOnError();
|
||||
|
||||
_imageView = imageView;
|
||||
@@ -202,6 +205,20 @@ public unsafe class VulkanImage : IDisposable
|
||||
TransitionLayout(ImageLayout.ColorAttachmentOptimal, AccessFlags.NoneKhr);
|
||||
}
|
||||
|
||||
private IntPtr CreateDxgiSharedHandle()
|
||||
{
|
||||
using var dxgiResource = _d3dTexture2D.QueryInterface<IDXGIResource1>();
|
||||
|
||||
void* sharedHandle;
|
||||
ThrowHResult(dxgiResource.CreateSharedHandle(
|
||||
(SecurityAttributes*) null,
|
||||
DXGI.SharedResourceRead | DXGI.SharedResourceWrite,
|
||||
(char*)null,
|
||||
&sharedHandle));
|
||||
|
||||
return (IntPtr)sharedHandle;
|
||||
}
|
||||
|
||||
public int ExportFd()
|
||||
{
|
||||
if (!Api.TryGetDeviceExtension<KhrExternalMemoryFd>(_instance, _device, out var ext))
|
||||
@@ -212,7 +229,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
SType = StructureType.MemoryGetFDInfoKhr,
|
||||
HandleType = ExternalMemoryHandleTypeFlags.OpaqueFDBit
|
||||
};
|
||||
ext.GetMemoryF(_device, info, out var fd).ThrowOnError();
|
||||
ext.GetMemoryF(_device, in info, out var fd).ThrowOnError();
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -226,7 +243,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
SType = StructureType.MemoryGetWin32HandleInfoKhr,
|
||||
HandleType = ExternalMemoryHandleTypeFlags.OpaqueWin32Bit
|
||||
};
|
||||
ext.GetMemoryWin32Handle(_device, info, out var fd).ThrowOnError();
|
||||
ext.GetMemoryWin32Handle(_device, in info, out var fd).ThrowOnError();
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -254,11 +271,10 @@ public unsafe class VulkanImage : IDisposable
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
if (_d3dTexture2D != null)
|
||||
if (_d3dTexture2D.Handle != null)
|
||||
{
|
||||
using var dxgi = _d3dTexture2D!.QueryInterface<Resource1>();
|
||||
return new PlatformHandle(
|
||||
dxgi.CreateSharedHandle(null, SharedResourceFlags.Read | SharedResourceFlags.Write),
|
||||
CreateDxgiSharedHandle(),
|
||||
KnownPlatformGraphicsExternalImageHandleTypes.D3D11TextureNtHandle);
|
||||
}
|
||||
|
||||
@@ -275,7 +291,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
|
||||
public ImageTiling Tiling => ImageTiling.Optimal;
|
||||
|
||||
public bool IsDirectXBacked => _d3dTexture2D != null;
|
||||
public bool IsDirectXBacked => _d3dTexture2D.Handle != null;
|
||||
|
||||
internal void TransitionLayout(CommandBuffer commandBuffer,
|
||||
ImageLayout fromLayout, AccessFlags fromAccessFlags,
|
||||
@@ -367,8 +383,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
}
|
||||
};
|
||||
|
||||
using (var backendTexture = new GRBackendRenderTarget(_image.Size.Width, _image.Size.Height, 1,
|
||||
imageInfo))
|
||||
using (var backendTexture = new GRBackendRenderTarget(_image.Size.Width, _image.Size.Height, imageInfo))
|
||||
using (var surface = SKSurface.Create(_vk.GrContext, backendTexture,
|
||||
GRSurfaceOrigin.TopLeft,
|
||||
SKColorType.Rgba8888, SKColorSpace.CreateSrgb()))
|
||||
|
||||
@@ -54,6 +54,6 @@ internal static class VulkanMemoryHelper
|
||||
0,
|
||||
null,
|
||||
1,
|
||||
barrier);
|
||||
in barrier);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ class VulkanSemaphorePair : IDisposable
|
||||
PNext = exportable ? &semaphoreExportInfo : null
|
||||
};
|
||||
|
||||
resources.Api.CreateSemaphore(resources.Device, semaphoreCreateInfo, null, out var semaphore).ThrowOnError();
|
||||
resources.Api.CreateSemaphore(resources.Device, in semaphoreCreateInfo, null, out var semaphore).ThrowOnError();
|
||||
ImageAvailableSemaphore = semaphore;
|
||||
|
||||
resources.Api.CreateSemaphore(resources.Device, semaphoreCreateInfo, null, out semaphore).ThrowOnError();
|
||||
resources.Api.CreateSemaphore(resources.Device, in semaphoreCreateInfo, null, out semaphore).ThrowOnError();
|
||||
RenderFinishedSemaphore = semaphore;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class VulkanSemaphorePair : IDisposable
|
||||
Semaphore = renderFinished ? RenderFinishedSemaphore : ImageAvailableSemaphore,
|
||||
HandleType = ExternalSemaphoreHandleTypeFlags.OpaqueFDBit
|
||||
};
|
||||
ext.GetSemaphoreF(_resources.Device, info, out var fd).ThrowOnError();
|
||||
ext.GetSemaphoreF(_resources.Device, in info, out var fd).ThrowOnError();
|
||||
return fd;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class VulkanSemaphorePair : IDisposable
|
||||
Semaphore = renderFinished ? RenderFinishedSemaphore : ImageAvailableSemaphore,
|
||||
HandleType = ExternalSemaphoreHandleTypeFlags.OpaqueWin32Bit
|
||||
};
|
||||
ext.GetSemaphoreWin32Handle(_resources.Device, info, out var fd).ThrowOnError();
|
||||
ext.GetSemaphoreWin32Handle(_resources.Device, in info, out var fd).ThrowOnError();
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ class VulkanSwapchainImage : ISwapchainImage
|
||||
buffer.Submit();
|
||||
}
|
||||
else
|
||||
buffer.Submit(new[] { _semaphorePair.ImageAvailableSemaphore },
|
||||
buffer.Submit(new[] { _semaphorePair!.ImageAvailableSemaphore },
|
||||
new[]
|
||||
{
|
||||
PipelineStageFlags.AllGraphicsBit
|
||||
@@ -160,7 +160,7 @@ class VulkanSwapchainImage : ISwapchainImage
|
||||
}
|
||||
}
|
||||
else
|
||||
buffer.Submit(null, null, new[] { _semaphorePair.RenderFinishedSemaphore });
|
||||
buffer.Submit(null, null, new[] { _semaphorePair!.RenderFinishedSemaphore });
|
||||
|
||||
if (_timelineSemaphore != null)
|
||||
{
|
||||
@@ -168,9 +168,9 @@ class VulkanSwapchainImage : ISwapchainImage
|
||||
}
|
||||
else if (!_image.IsDirectXBacked)
|
||||
{
|
||||
_availableSemaphore ??= _interop.ImportSemaphore(_semaphorePair.Export(false));
|
||||
_availableSemaphore ??= _interop.ImportSemaphore(_semaphorePair!.Export(false));
|
||||
|
||||
_renderCompletedSemaphore ??= _interop.ImportSemaphore(_semaphorePair.Export(true));
|
||||
_renderCompletedSemaphore ??= _interop.ImportSemaphore(_semaphorePair!.Export(true));
|
||||
}
|
||||
|
||||
_importedImage ??= _interop.ImportImage(_image.Export(),
|
||||
|
||||
@@ -32,7 +32,7 @@ class VulkanTimelineSemaphore : IDisposable
|
||||
SType = StructureType.SemaphoreCreateInfo,
|
||||
PNext = &semaphoreTypeInfo,
|
||||
};
|
||||
resources.Api.CreateSemaphore(resources.Device, semaphoreCreateInfo, null, out var semaphore).ThrowOnError();
|
||||
resources.Api.CreateSemaphore(resources.Device, in semaphoreCreateInfo, null, out var semaphore).ThrowOnError();
|
||||
Handle = semaphore;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user