dotnet / Silk.NET

The high-speed OpenGL, OpenCL, OpenAL, OpenXR, GLFW, SDL, Vulkan, Assimp, WebGPU, and DirectX bindings library your mother warned you about.
https://dotnet.github.io/Silk.NET
MIT License
4.15k stars 397 forks source link

Unexpected exception moving from SharpDX to Silk.NET #1504

Closed Momeigetsu closed 1 year ago

Momeigetsu commented 1 year ago

​I am renovating a project I wrote before which had some Direct2D content using SharpDX. Then I moved to Silk.NET and encountered a strange problem. I can't use the CreateBitmapFromDxgiSurface method (hr=0x80070002). I think this should not be a problem with my environment configuration? Because it can still be used normally in SharpDX.

SharpDX version:

using D2D = SharpDX.Direct2D1;
using D3D = SharpDX.Direct3D;
using D3D11 = SharpDX.Direct3D11;
using DXGI = SharpDX.DXGI;

D3D11.Device _d3d11_Device;
DXGI.Device _dxgi_Device;
D2D.Device _d2d_Device;
DXGI.SwapChain _swapChain;
D2D.DeviceContext _d2d_DeviceContext;

D3D11.Device.CreateWithSwapChain (
    D3D.DriverType.Hardware,
    D3D11.DeviceCreationFlags.BgraSupport,
    new DXGI.SwapChainDescription {
        ModeDescription = new DXGI.ModeDescription {
            RefreshRate = new DXGI.Rational (60, 1),
            Format = DXGI.Format.B8G8R8A8_Unorm,
        },
        SampleDescription = new DXGI.SampleDescription (1, 0),
        Usage = DXGI.Usage.RenderTargetOutput,
        BufferCount = 1,
        OutputHandle = handle,
        IsWindowed = true,
    },
    out _d3d11_Device,
    out _swapChain);
_dxgi_Device = _d3d11_Device.QueryInterface<D3D11.Device1> ().QueryInterface<DXGI.Device> ();
_d2d_Device = new D2D.Device (_dxgi_Device);
_d2d_DeviceContext = new D2D.DeviceContext (_d2d_Device, D2D.DeviceContextOptions.EnableMultithreadedOptimizations);
_d2d_DeviceContext.Target = new D2D.Bitmap1 (_d2d_DeviceContext, DXGI.Surface.FromSwapChain (_swapChain, 0));

Silk.NET version:

using Silk.NET.Core.Native;
using D2D = Silk.NET.Direct2D;
using D3D = Silk.NET.Direct3D11;
using DXGI = Silk.NET.DXGI;

const uint DXGI_USAGE_RENDER_TARGET_OUTPUT = 1U << (1 + 4);
const uint D3D11_CREATE_DEVICE_BGRA_SUPPORT = 0x20;

D2D.D2D _d2d;
D3D.D3D11 _d3d;
ComPtr<D3D.ID3D11Device> _d3d_device;
ComPtr<D3D.ID3D11DeviceContext> _d3d_deviceContext;
ComPtr<DXGI.IDXGIDevice> _dx_device;
ComPtr<D2D.ID2D1Device> _d2d_device;
ComPtr<D2D.ID2D1DeviceContext> _d2d_deviceContext;
ComPtr<DXGI.IDXGISwapChain> _swapChain;
ComPtr<DXGI.IDXGISurface> _surface;
ComPtr<D2D.ID2D1Bitmap1> _bitmap1;

_d2d = D2D.D2D.GetApi ();
_d3d = D3D.D3D11.GetApi ();

var swapChainDesc = new DXGI.SwapChainDesc {
    BufferCount = 1,
    BufferDesc = new DXGI.ModeDesc {
        Format = DXGI.Format.FormatB8G8R8A8Unorm,
        RefreshRate = new DXGI.Rational (60, 1),
    },
    BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
    OutputWindow = handle,
    SampleDesc = new DXGI.SampleDesc (1, 0),
    SwapEffect = DXGI.SwapEffect.Discard,
    Windowed = true,
};

var hr = _d3d.CreateDeviceAndSwapChain (
    default (ComPtr<DXGI.IDXGIAdapter>),
    D3DDriverType.Hardware,
    0,
    D3D11_CREATE_DEVICE_BGRA_SUPPORT, null, 0,
    D3D.D3D11.SdkVersion,
    swapChainDesc,
    ref _swapChain,
    ref _d3d_device,
    null,
    ref _d3d_deviceContext);
SilkMarshal.ThrowHResult (hr);

hr = _d3d_device.Get ().QueryInterface (out _dx_device);
SilkMarshal.ThrowHResult (hr);

var options = new D2D.CreationProperties {
    Options = D2D.DeviceContextOptions.EnableMultithreadedOptimizations,
    ThreadingMode = D2D.ThreadingMode.MultiThreaded
};

hr = _d2d.D2D1CreateDevice (_dx_device, in options, ref _d2d_device);
SilkMarshal.ThrowHResult (hr);

hr = _d2d_device.Get ().CreateDeviceContext (D2D.DeviceContextOptions.EnableMultithreadedOptimizations, ref _d2d_deviceContext);
SilkMarshal.ThrowHResult (hr);

hr = _swapChain.Get ().GetBuffer (0, out _surface);
SilkMarshal.ThrowHResult (hr);

var bitmapProperties = new D2D.BitmapProperties1 {
    BitmapOptions = D2D.BitmapOptions.Target | D2D.BitmapOptions.CannotDraw,
    PixelFormat = new D2D.PixelFormat {
        AlphaMode = D2D.AlphaMode.Ignore,
        Format = DXGI.Format.FormatB8G8R8A8Unorm
    }
};

hr = _d2d_deviceContext.Get ().CreateBitmapFromDxgiSurface (_surface, bitmapProperties, ref _bitmap1);
SilkMarshal.ThrowHResult (hr); // 0x80070002

This makes me very strange because new D2D.Bitmap1 (_d2d_DeviceContext, DXGI.Surface.FromSwapChain (_swapChain, 0)); in SharpDX also uses CreateBitmapFromDxgiSurface, but it cannot be used in Silk.NET.

Perksey commented 1 year ago

Moving this to a discussion until we have evidence that this is a Silk.NET bug. At a guess this is an incorrect porting of implicit behaviour in SharpDX.